<?php

/**
 * Handles script assets.
 *
 * @package northmill-online-shared
 *
 * @phpcs:disable Squiz.Commenting.FunctionComment.MissingParamTag
 */
declare (strict_types=1);
namespace Northmill_Online_Shared_Sync\Northmill_Online_Shared\Modules\Assets\Models;

use Closure;
use Northmill_Online_Shared_Sync\Northmill_Online_Shared\Abstract_Shared_Base;
use Northmill_Online_Shared_Sync\Northmill_Online_Shared\Modules\Assets\Asset_Location_Enum;
defined('ABSPATH') || exit;
/**
 * Class Script_Asset_Model
 */
class Script_Asset_Model extends Abstract_Asset_Model
{
    /**
     * The available base names for the script object.
     *
     * @var string[]
     */
    protected array $script_object_name_bases;
    /**
     * The localization data for the asset.
     * If a Closure is provided, it will be called with a boolean parameter indicating whether the asset is in Shared.
     *
     * @var array|Closure|null
     */
    protected array|Closure|null $plugin_localization;
    /**
     * Constructor.
     *
     * @param string              $filename            The filename of the asset.
     * @param Asset_Location_Enum $location            Where asset should be enqueued.
     * @param array               $asset_dependencies  The dependencies of the asset.
     * @param array|Closure|null  $plugin_localization The localization data for the asset.
     * @param bool|array|Closure  $should_enqueue      Whether the asset should be enqueued. Defaults to true.
     */
    public function __construct(string $filename, Asset_Location_Enum $location, array $asset_dependencies = array(), array|Closure|null $plugin_localization = null, bool|array|Closure $should_enqueue = \true, bool $is_dependency = \false)
    {
        parent::__construct($filename, $location, $asset_dependencies, $should_enqueue, $is_dependency);
        $name_base_addon = Asset_Location_Enum::ADMIN === $location ? 'admin_' : '';
        $this->plugin_localization = $plugin_localization;
        $this->script_object_name_bases = array('package' => Abstract_Shared_Base::base_instance()->package_info->get_service_name_underscored() . '_' . $name_base_addon, 'shared' => 'northmill_online_shared_' . $name_base_addon);
    }
    /**
     * Enqueues a script if the asset is available and adds localization data if provided.
     *
     * @param bool   $is_shared Whether trying to load an asset from Shared.
     * @param string $path_base The base path for the asset.
     * @param string $url_base  The base URL for the asset.
     *
     * @return void
     */
    protected function maybe_enqueue_asset(bool $is_shared, string $path_base, string $url_base): void
    {
        $asset = $this->get_asset($path_base, $url_base);
        if ($asset) {
            $handle = $this->build_handle('script', $is_shared);
            if ($this->is_dependency) {
                wp_register_script($handle, $asset['url'], $this->asset_dependencies, filemtime($asset['path']), \true);
            } else {
                wp_enqueue_script($handle, $asset['url'], $this->asset_dependencies, filemtime($asset['path']), \true);
            }
            $this->maybe_localize_script($handle, $is_shared, $asset['url']);
        }
    }
    /**
     * Localizes a script if localization data is provided.
     *
     * @param string $handle    The script handle.
     * @param bool   $is_shared Whether trying to load an asset from Shared.
     * @param string $src       The script URL.
     *
     * @return void
     */
    private function maybe_localize_script(string $handle, bool $is_shared, string $src): void
    {
        if (is_callable($this->plugin_localization)) {
            $plugin_localization = call_user_func($this->plugin_localization, $is_shared);
        } else {
            $plugin_localization = $this->plugin_localization;
        }
        if (!empty($plugin_localization)) {
            $object_name_base = $is_shared ? 'shared' : 'package';
            $object_name = $this->script_object_name_bases[$object_name_base] . $this->underscored_filename;
            $localized = wp_localize_script($handle, $object_name, $plugin_localization);
            if (!$localized) {
                Abstract_Shared_Base::base_instance()->logger->log('assets', 'Failed to localize script', array('handle' => $handle, 'object_name' => $object_name, 'script_path' => $src, 'localization' => $plugin_localization));
            }
        }
    }
}
