<?php

class MapBox
{
	static $id = 0;
    protected $doc;
    protected $baseUrl;
    protected $assetsUrl;
    protected $entryPoint = 'public';
    protected $manifest = [];
    protected $admin = false;
    protected $params;

    public function __construct($admin = false, ?\Joomla\Registry\Registry $params = null)
    {
        $this->doc = JFactory::getDocument();
        $this->baseUrl = JUri::root(true);
        $this->params = $params;
        $this->admin = $admin;
        if ($admin) {
            $this->entryPoint = 'admin';
        }
        $this->assetsUrl = "$this->baseUrl/media/mod_mapbox";
        $this->manifest['modern'] = json_decode(file_get_contents(JPATH_ROOT . '/media/mod_mapbox/manifest.json'), true);
        $this->manifest['legacy'] = json_decode(file_get_contents(JPATH_ROOT . '/media/mod_mapbox/manifest-legacy.json'), true);

        static::$id++;
    }

	protected function getId()
	{
		return 'mapbox_' . static::$id;
    }

    private function attachScripts()
    {
        if ($this->params && $token = $this->params->get('token')) {
            $this->doc->addScriptDeclaration("window.mapboxToken = '$token';");
        }

        $this->addScript($this->manifest['modern']["$this->entryPoint.js"], ['type' => 'module']);
        $this->addScript($this->manifest['modern']["chunk-common.js"], ['type' => 'module']);

        $this->addScript($this->manifest['legacy']["$this->entryPoint.js"], ['nomodule' => true]);
        $this->addScript($this->manifest['legacy']["chunk-common.js"], ['nomodule' => true]);
    }

    private function attachStyles()
    {
        $this->addStyleSheet($this->manifest['modern']["$this->entryPoint.css"]);
        $this->addStyleSheet($this->manifest['modern']["chunk-common.css"]);
    }

    private function addScript(string $script, array $options = [])
    {
        $this->doc->addScript("$this->assetsUrl/$script", array_merge([
            'defer' => true,
            'async' => true,
        ]), $options);
    }

    private function addStyleSheet(string $style)
    {
        $this->doc->addStyleSheet("$this->assetsUrl/$style");
    }

    public function render($value, $name = null)
    {
        $this->attachScripts();
        $this->attachStyles();

        $id = $this->getId();

        if ($name) {
            return "<div id='$id' class='mapbox-admin js-mod-mapbox' data-title='$name' data-name='$name' data-value='$value' data-baseurl='$this->baseUrl'></div>";
        }

        return "<div id='$id' class='js-mod-mapbox' data-value='$value' data-baseurl='$this->baseUrl'></div>";
    }

    public static function prepareContent(string $content)
    {
        $options = self::decodeOpt($content);

        $options->geoJson->features = array_map(function($feature) {
            if ($feature->properties->web && strpos($feature->properties->web, 'index.php') === 0) {
                $link = JRoute::_($feature->properties->web);
                $feature->properties->web = $link;
            }
            return $feature;
        }, $options->geoJson->features);

        return self::encodeOpt($options);
    }

    protected static function decodeOpt(string $options)
    {
        return json_decode(utf8_encode(base64_decode($options)));
    }

    protected static function encodeOpt($options): string
    {
        return base64_encode(json_encode($options));
    }
}
