<?php

/**
 * Template loader.
 *
 * @package northmill-online-shared
 */
declare (strict_types=1);
namespace Northmill_Online_Shared_Sync\Northmill_Online_Shared\Modules;

use Northmill_Online_Shared_Sync\Northmill_Online_Shared\Helpers\General_Helpers;
use Northmill_Online_Shared_Sync\Northmill_Online_Shared\Helpers\Hook_Helpers;
use Northmill_Online_Shared_Sync\Northmill_Online_Shared\Modules\Loggers\Log_Level_Enum;
defined('ABSPATH') || exit;
/**
 * Class Template_Loader
 */
class Template_Loader_Module extends Abstract_Module
{
    /**
     * The directory where the templates are stored.
     *
     * @var string
     */
    private string $template_path;
    /**
     * Module setup.
     *
     * @return void
     */
    public function setup(): void
    {
        $package_path = $this->shared->package_info->paths->get_path();
        $package_templates_path = Hook_Helpers::apply_scoped_filters('northmill_online_shared_template_loader_dir', 'views');
        $this->template_path = !empty($package_templates_path) ? General_Helpers::ensure_trailing_slash($package_path . $package_templates_path) : '';
    }
    /**
     * Get the absolute path to the template directory.
     *
     * @return string
     */
    public function get_template_path(): string
    {
        return $this->template_path;
    }
    /**
     * Loads a template file and passes view parameters to it.
     *
     * @param string $template         The name of the template part to load (without the file extension).
     * @param array  $view_params      Optional. An array of key-value pairs for passing data to the template.
     * @param bool   $use_require_once Whether to use require_once(), otherwise require() is used.
     * @param bool   $return_content   Whether to return the content of the included file, or require it.
     *
     * @return string|false
     * @noinspection PhpUnused Used by plugins loading this composer package.
     */
    public function get_template(string $template, array $view_params = array(), bool $use_require_once = \true, bool $return_content = \false): string|false
    {
        return $this->include_file($template . '.php', $view_params, $use_require_once, $return_content);
    }
    /**
     * Loads a template part file and passes view parameters to it.
     *
     * @param string $template_part The name of the template part to load (without the file extension).
     * @param array  $view_params   Optional. An array of key-value pairs for passing data to the template part.
     * @param bool   $use_require_once Whether to use require_once(), otherwise require() is used.
     * @param bool   $return_content     Whether to return the content of the included file, or require it.
     *
     * @return string|false
     * @noinspection PhpUnused Used by plugins loading this composer package.
     */
    public function get_template_part(string $template_part, array $view_params = array(), bool $use_require_once = \true, bool $return_content = \false): string|false
    {
        return $this->include_file('parts/' . $template_part . '.php', $view_params, $use_require_once, $return_content);
    }
    /**
     * Loads an admin template file and passes view parameters to it.
     *
     * @param string $template    The name of the admin template to load (without the file extension).
     * @param array  $view_params Optional. An array of key-value pairs for passing data to the admin template.
     * @param bool   $use_require_once Whether to use require_once(), otherwise require() is used.
     * @param bool   $return_content     Whether to return the content of the included file, or require it.
     *
     * @return string|false
     * @noinspection PhpUnused Used by plugins loading this composer package.
     */
    public function get_admin_template(string $template, array $view_params = array(), bool $use_require_once = \true, bool $return_content = \false): string|false
    {
        return $this->include_file('admin/' . $template . '.php', $view_params, $use_require_once, $return_content);
    }
    /**
     * Retrieves and renders an admin template part with optional view parameters.
     *
     * @param string $template_part The name of the admin template part to retrieve and render.
     * @param array  $view_params   Optional. An array of view parameters to pass to the template part. Default empty array.
     * @param bool   $use_require_once Whether to use require_once(), otherwise require() is used.
     * @param bool   $return_content     Whether to return the content of the included file, or require it.
     *
     * @return string|false
     * @noinspection PhpUnused Used by plugins loading this composer package.
     */
    public function get_admin_template_part(string $template_part, array $view_params = array(), bool $use_require_once = \true, bool $return_content = \false): string|false
    {
        return $this->include_file('admin/parts/' . $template_part . '.php', $view_params, $use_require_once, $return_content);
    }
    /**
     * Includes a file if it exists.
     *
     * This method checks if a file exists at the specified path and includes it
     * if it does. The file path is relative to the 'templates' directory.
     *
     * @param string $file_path_and_name The path and name of the file to include.
     * @param array  $params             An associative array of parameters to pass to the included file. Default is an empty array.
     * @param bool   $use_require_once   Whether to use require_once(), otherwise require() is used.
     * @param bool   $return_content     Whether to return the content of the included file, or require it.
     *
     * @return string|false
     *
     * @noinspection PhpUnusedParameterInspection $params variable is used in the loaded view.
     *
     * @psalm-suppress UnusedParam
     */
    private function include_file(string $file_path_and_name, array $params = array(), bool $use_require_once = \true, bool $return_content = \false): string|false
    {
        $full_path = \false;
        if (!empty($this->template_path) && file_exists($this->template_path . $file_path_and_name)) {
            $full_path = $this->template_path . $file_path_and_name;
        } elseif (file_exists($this->shared->package_info->paths->get_path() . 'online-shared/templates/' . $file_path_and_name)) {
            $full_path = $this->shared->package_info->paths->get_path() . 'online-shared/templates/' . $file_path_and_name;
        }
        if (!$full_path) {
            $this->shared->logger->log('template-loader', 'Template file not found', array('file_path_and_name' => $file_path_and_name, 'template_dir' => $this->template_path ?? '[not set]'), Log_Level_Enum::ERROR);
            return \false;
        }
        if ($return_content) {
            ob_start();
        }
        if ($use_require_once) {
            require_once $full_path;
        } else {
            require $full_path;
        }
        if ($return_content) {
            return ob_get_clean();
        } else {
            return \false;
        }
    }
}
