<?php

namespace BlackSheepResearch\Component\UserPoints\Site;

defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Uri\Uri;

class WebAssetManager {

    protected static $instance = [];
    protected $extension = '';
    protected $assets = [];
    protected $style = [];
    protected $script = [];

    protected function __construct($extension) {
        $this->extension = $extension;
        $this->assets = json_decode(file_get_contents(JPATH_SITE . "/media/$extension/joomla.asset.json"), true);
    }

    public static function getInstance($extension) {
        if (!isset(self::$instance[$extension])) {
            self::$instance[$extension] = class_exists('\Joomla\CMS\WebAsset\WebAssetManager')
                ? Factory::getApplication()->getDocument()->getWebAssetManager()
                : new self($extension);
        }
        return self::$instance[$extension];
    }

    public function useStyle($name) {
        return $this->useAsset('style', $name);
    }

    public function useScript($name) {
        return $this->useAsset('script', $name);
    }

    private function useAsset(string $type, string $name) {
        if (!isset($this->$type[$name])) {
            $asset = $this->findAsset($type, $name);
            if ($asset) {
                $this->useDependencies($asset['dependencies'] ?? []);
                $this->addAsset($type, $this->expandURI($asset['uri'], $type), $asset['attributes'] ?? []);
                $this->$type[$name] = true;
            }
        }
        return $this;
    }

    private function useDependencies(array $dependencies) {
        foreach ($dependencies as $dependency) {
            $this->useScript($dependency);
        }
    }

    public function assetExists(string $type, string $name): bool {
        return !empty($this->findAsset($type, $name));
    }

    private function findAsset(string $type, string $name): array {
        foreach ($this->assets['assets'] as $asset) {
            if ($type === $asset['type'] && $name === $asset['name']) {
                return $asset;
            }
        }
        return [];
    }

    public function registerScript(string $name, string $uri, array $options = [], array $attributes = [], array $dependencies = []) {
        $this->register('script', $name, $uri, $options, $attributes, $dependencies);
    }

    public function registerStyle(string $name, string $uri, array $options = [], array $attributes = [], array $dependencies = []) {
        $this->register('style', $name, $uri, $options, $attributes, $dependencies);
    }

    private function register(string $type, string $name, string $uri, array $options = [], array $attributes = [], array $dependencies = []) {
        $this->assets[] = compact('type', 'name', 'uri', 'options', 'attributes', 'dependencies');
    }

    private function expandURI(string $uri, string $type) : string {
        $typecode = ['script' => 'js', 'style' => 'css'];
        $dir = $typecode[$type];
        $file = $this->lastPart($uri, '/');
        return "media/$this->extension/$dir/$file";
    }

    private function addAsset(string $type, string $file, array $attributes) {
        $prefix = 0 === stripos($file, 'http') ? '' : Uri::root();
        HTMLHelper::{$type}($prefix . $file, [], $attributes);
    }

    private function lastPart(string $field, string $separator, bool $lowercase = true) : string {
        $parts = explode($separator, $field);
        $last = end($parts);
        return $lowercase ? strtolower($last) : $last;
    }
}