<?php

/**
 * Class SocialSharing_Ui_Asset
 */
abstract class SocialSharing_Ui_Asset implements SocialSharing_Ui_AssetInterface
{
    /**
     * @var string
     */
    protected $hookName;

    /**
     * @var string
     */
    protected $handle;

    /**
     * @var string|null
     */
    protected $source;

    /**
     * @var string[]
     */
    protected $dependencies;

    /**
     * @var string|null
     */
    protected $version;

    /**
     * @var bool
     */
    protected $cachingAllowed;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->dependencies = array();
        $this->cachingAllowed = true;

        if (defined('WP_DEBUG') && WP_DEBUG) {
            $this->cachingAllowed = false;
            $this->version = uniqid();
        }
    }

    public function __toString()
    {
        return $this->getHandle().' @ '.$this->getSource().'?version='.$this->getVersion();
    }

    /**
     * Adds asset to the global WordPress assets queue.
     */
    abstract public function enqueue();

    /**
     * Register current asset in the WordPress hook system.
     *
     * @throws UnexpectedValueException If hookName or handle isn't presented.
     */
    public function register()
    {
        if (!$this->hookName) {
            throw new UnexpectedValueException(
                'Mandatory property "hookName" is empty.'
            );
        }

        if (!$this->handle) {
            throw new UnexpectedValueException(
                'Mandatory property "handle" is empty.'
            );
        }

        add_action($this->hookName, array($this, 'enqueue'));
    }

    /**
     * Returns Handle.
     * @return string
     */
    public function getHandle()
    {
        return $this->handle;
    }

    /**
     * Sets Handle.
     * @param string $handle
     * @return $this
     */
    public function setHandle($handle)
    {
        $this->handle = strtolower((string)$handle);

        return $this;
    }

    /**
     * Returns Source.
     * @return null|string
     */
    public function getSource()
    {
        return $this->source;
    }

    /**
     * Sets Source.
     * @param null|string $source
     * @return $this
     */
    public function setSource($source)
    {
        $this->source = (string)$source;

        return $this;
    }

    /**
     * @param string $externalSource URL to the external resource.
     * @param bool $stripSchema Strip http or https prefix or not.
     * @return $this
     */
    public function setExternalSource($externalSource, $stripSchema = true)
    {
        if ((bool)$stripSchema) {
            $externalSource = preg_replace('#^https?:#', '', $externalSource);
        }

        return $this->setSource($externalSource);
    }

    /**
     * @param string $localSource
     * @return SocialSharing_Ui_Asset
     */
    public function setLocalSource($localSource)
    {
        $baseUrl = plugin_dir_url(dirname(dirname(dirname(__FILE__))));

        return $this->setSource($baseUrl.'app/assets/'.$localSource);
    }

    public function setProModuleSource($path, $moduleSource = null) {

        return $this->setSource($path.'/assets/'.$moduleSource);
    }

    /**
     * @param string|Rsc_Mvc_Module $module
     * @param string $moduleSource
     * @return SocialSharing_Ui_Asset
     */
    public function setModuleSource($module, $moduleSource)
    {
        $baseUrl = plugin_dir_url(dirname(__FILE__));

        if (is_string($module)) {
            $module = ucfirst($module);
        } elseif ($module instanceof Rsc_Mvc_Module) {
            $module = ucfirst($module->getModuleName());
        } else {
            throw new InvalidArgumentException(
                'First parameter must be module name or the instance of the module.'
            );
        }

        return $this->setSource($baseUrl.$module.'/assets/'.$moduleSource);
    }

    /**
     * Adds dependency.
     * @param string|SocialSharing_Ui_Asset $dependency
     * @return $this
     */
    public function addDependency($dependency)
    {
        if ($dependency instanceof SocialSharing_Ui_Asset) {
            $dependency = $dependency->getHandle();
        }

        $dependency = strtolower($dependency);

        if (in_array($dependency, $this->dependencies, false)) {
            return $this;
        }

        $this->dependencies[] = $dependency;

        return $this;
    }

    /**
     * Returns Dependencies.
     * @return string[]
     */
    public function getDependencies()
    {
        return $this->dependencies;
    }

    /**
     * Sets Dependencies.
     * @param string[] $dependencies
     * @return $this
     */
    public function setDependencies(array $dependencies)
    {
        $this->dependencies = $dependencies;

        return $this;
    }

    /**
     * Removes dependency.
     *
     * @param string $dependency
     * @return bool TRUE on success, FALSE otherwise
     */
    public function removeDependency($dependency)
    {
        if (false === $key = array_search(
                strtolower($dependency),
                $this->dependencies,
                false
            )
        ) {
            return false;
        }

        unset($this->dependencies[$key]);

        return true;
    }

    /**
     * Returns Version.
     * @return string
     */
    public function getVersion()
    {
        return $this->version;
    }

    /**
     * Sets Version.
     * @param string $version
     * @return $this
     */
    public function setVersion($version)
    {
        if (!$this->cachingAllowed) {
            $version = uniqid($version.'_');
        }

        $this->version = (string)$version;

        return $this;
    }

    /**
     * Returns CachingAllowed.
     * @return boolean
     */
    public function isCachingAllowed()
    {
        return $this->cachingAllowed;
    }

    /**
     * Sets CachingAllowed.
     * @param boolean $cachingAllowed
     * @return $this
     */
    public function setCachingAllowed($cachingAllowed)
    {
        $this->cachingAllowed = (bool)$cachingAllowed;

        return $this;
    }

    /**
     * Returns HookName.
     * @return string
     */
    public function getHookName()
    {
        return $this->hookName;
    }

    /**
     * Sets HookName.
     * @param string $hookName
     * @return $this
     */
    public function setHookName($hookName)
    {
        $this->hookName = $hookName;

        return $this;
    }
}