<?php

/**
 * Abstract class for package info modules.
 *
 * @package northmill-online-shared
 */
namespace Northmill_Online_Shared_Checkout\Northmill_Online_Shared\Modules\Info;

use Northmill_Online_Shared_Checkout\Northmill_Online_Shared\Abstract_Shared_Base;
use Northmill_Online_Shared_Checkout\Northmill_Online_Shared\Helpers\File_System_Helper;
use Northmill_Online_Shared_Checkout\Northmill_Online_Shared\Helpers\Hook_Helpers;
use Northmill_Online_Shared_Checkout\Northmill_Online_Shared\Modules\Abstract_Module;
use Northmill_Online_Shared_Checkout\Northmill_Online_Shared\Modules\Info\Models\Info_Package_Data_Model;
use Northmill_Online_Shared_Checkout\Northmill_Online_Shared\Modules\Info\Models\Info_Paths_Model;
/**
 * Abstract class for package info modules.
 */
abstract class Abstract_Package_Info_Module extends Abstract_Module
{
    /**
     * The paths model.
     *
     * @var Info_Paths_Model
     */
    public Info_Paths_Model $paths;
    /**
     * The package data model.
     *
     * @var Info_Package_Data_Model
     */
    public Info_Package_Data_Model $package_data;
    /**
     * The name of the service. Sanitized with sanitize_title().
     *
     * @var string
     */
    private string $service_name;
    /**
     * The name of the service with underscores instead of dashes.
     *
     * @var string
     */
    private string $service_name_underscored;
    /**
     * The path to the package file, including the filename itself.
     *
     * @var string
     */
    private string $file_path;
    /**
     * The package slug.
     *
     * @var string
     */
    protected string $slug;
    /**
     * URL to info JSON file with package info.
     *
     * @var string
     */
    private string $package_info_json_url;
    /**
     * Package banners.
     * Should contain keys 'high' and/or 'low' with URLs as values.
     *
     * @var string[]
     */
    private array $banners = array();
    /**
     * The version of the shared instance.
     *
     * @var string
     */
    private string $shared_version;
    /**
     * Construct
     *
     * @param Abstract_Shared_Base $shared  Shared instance.
     */
    public function __construct(Abstract_Shared_Base $shared)
    {
        parent::__construct($shared);
        $this->file_path = $shared->get_package_file_path();
        $this->package_data = new Info_Package_Data_Model($this->get_file_path(), array($this, 'get_package_data'));
        $this->service_name = self::generate_service_name($this->package_data->get_name());
        $this->service_name_underscored = self::generate_underscored_service_name($this->service_name);
        $this->paths = $this->create_paths_model($this->get_file_path());
    }
    /**
     * Get the service name.
     *
     * @param string|null $package_name The package name.
     *
     * @return string
     */
    public static function generate_service_name(?string $package_name = null): string
    {
        $package_name = $package_name ?? static::get_package_name();
        return sanitize_title($package_name);
    }
    /**
     * Get the service name with underscores instead of dashes.
     *
     * @param string|null $service_name The service name.
     *
     * @return string
     */
    public static function generate_underscored_service_name(?string $service_name = null): string
    {
        $service_name = $service_name ?? static::generate_service_name();
        return str_replace('-', '_', $service_name);
    }
    /**
     * Get the package name from the main file data.
     *
     * @return string
     */
    abstract protected static function get_package_name(): string;
    /**
     * Get the service name.
     *
     * @return string
     */
    public function get_service_name(): string
    {
        return $this->service_name;
    }
    /**
     * Get the service name with underscores instead of dashes.
     *
     * @return string
     */
    public function get_service_name_underscored(): string
    {
        return $this->service_name_underscored;
    }
    /**
     * Get the absolute path to the package file, including filename.
     *
     * @return string
     */
    public function get_file_path(): string
    {
        return $this->file_path;
    }
    /**
     * Get the package paths data module.
     *
     * @param string $package_file_path The path to the package file.
     *
     * @return Info_Paths_Model
     */
    abstract protected function create_paths_model(string $package_file_path): Info_Paths_Model;
    /**
     * Get the URL to the package info JSON file.
     *
     * @return string
     */
    public function get_info_json_url(): string
    {
        if (!isset($this->package_info_json_url)) {
            $constant_name = strtoupper($this->get_service_name_underscored()) . '_CUSTOM_PLUGIN_INFO_JSON_URL';
            if (defined($constant_name)) {
                $this->package_info_json_url = constant($constant_name);
            } else {
                $this->package_info_json_url = Hook_Helpers::apply_scoped_filters_custom($this->get_service_name_underscored(), 'northmill_online_shared_package_info_json_url', '');
            }
        }
        return $this->package_info_json_url;
    }
    /**
     * Get the banner URLs.
     *
     * @return array
     */
    protected function get_banner_urls(): array
    {
        if (!isset($this->banners)) {
            $banner_urls = Hook_Helpers::apply_scoped_filters_custom($this->get_service_name_underscored(), 'northmill_online_shared_banner_urls', array());
            if (!empty($banner_urls['low'])) {
                $this->banners['low'] = $banner_urls['low'];
            }
            if (!empty($banner_urls['high'])) {
                $this->banners['high'] = $banner_urls['high'];
            }
        }
        return $this->banners;
    }
    /**
     * Retrieves the URL of the package banner image based on the provided type.
     *
     * @param string $type The type of banner image to retrieve. Default is 'high'.
     *
     * @return string The URL of the package banner image.
     */
    public function get_banner(string $type = 'high'): string
    {
        $banners = $this->get_banner_urls();
        return match ($type) {
            'low' => $banners['low'] ?? $banners['high'] ?? '',
            default => $banners['high'] ?? $banners['low'] ?? '',
        };
    }
    /**
     * Get the package slug as class property.
     *
     * @return string
     */
    abstract public function get_slug(): string;
    /**
     * Get whether the package is a plugin or not.
     *
     * @return bool
     */
    abstract public function is_plugin(): bool;
    /**
     * Get the package data.
     *
     * @param string $file_path        The path to the package file.
     * @param bool   $should_translate Whether the data should be translated.
     *
     * @return array
     */
    abstract public static function get_package_data(string $file_path, bool $should_translate = \false): array;
    /**
     * Get the version of Shared.
     *
     * @return string
     */
    public function get_shared_version(): string
    {
        if (!isset($this->shared_version)) {
            $this->shared_version = '0.0.0';
            $composer_file_path = $this->paths->get_shared_path() . 'composer.json';
            if (file_exists($composer_file_path)) {
                $composer_data = json_decode(File_System_Helper::get_contents($composer_file_path), \true);
                if (isset($composer_data['version'])) {
                    $this->shared_version = $composer_data['version'];
                }
            }
        }
        return $this->shared_version;
    }
}
