<?php
namespace IntellexApps\PHP\UploadFile;

use SuperClosure\Serializer;

class Dossier
{

    var $id;
    var $config;
    var $hooks = [];

    /**
     * Construct object
     *
     * Dossier constructor.
     * @param $config
     */
    public function __construct($config)
    {
        $this->buildInstance($config);
    }

    /**
     * Build instance
     *
     * @param $config
     */
    public function buildInstance($config)
    {

        // If not config provided, then it's existing instance stored in session
        if(!is_array($config)) {
            $this->initializeFromId($config);
            return;
        }

        // Initialize from config
        $this->id = base64_encode(mt_rand(5000000, 10000000));
        $this->config = $this->parseConfig($config);

        // Store to session
        $this->storeToSession();
    }

    /**
     * Initialize from id
     *
     * @param $id
     */
    public function initializeFromId($id)
    {
        $sessionState = $this->getFromSession($id);
        $this->config = $sessionState['config'];
        $this->hooks = $sessionState['hooks'];
        $this->id = $id;
    }

    /**
     * @return string
     */
    public function getHtml()
    {
        return '<iframe data-dossier-id="' . $this->id . '" src="/dossier.php?url=/iframe&dossier_id=' . $this->id . '&session_id=' . urlencode(session_id()) . '" class="dossier-iframe"></iframe>';
    }

    /**
     * Get javascript to include
     *
     * @return string
     */
    public function getJs()
    {
        return '<script src="' . $this->config['assets_prefix'] . 'assets/asset-manager.js"></script>';
    }

    /**
     * Get css to include
     *
     * @return string
     */
    public function getCss()
    {
        return '<link rel="stylesheet" type="text/css" href="' . $this->config['assets_prefix'] . 'assets/asset-manager.css">';
    }

    /**
     * Parse config
     */
    private function parseConfig($config)
    {

        $config['id'] = $this->id;
        $config['base_url'] = $this->parseBaseUrl($config);
        $config['api_prefix'] = $this->parseApiPrefix($config);
        $config['download_prefix'] = $this->parseDownloadPrefix($config);

        return $config;
    }

    /**
     * Get javascript config
     *
     * @return array
     */
    public function getJsConfig()
    {
        $allowedKeys = [
            'assets_prefix',
            'api_prefix',
            'id',
            'base_url',
            'download_prefix'
        ];

        $clientConfig = [];

        foreach($allowedKeys as $allowedKey) {
            if(isset($this->config[$allowedKey])) {
                $clientConfig[$allowedKey] = $this->config[$allowedKey];
            }
        }

        return $clientConfig;

    }

    /**
     * Parse base url if not provided
     *
     * @param $config
     * @return mixed
     * @throws \Exception
     */
    private function parseBaseUrl($config)
    {

        if(isset($config['base_url'])) {
            return $config['base_url'];
        }

        if(isset($_SERVER['REQUEST_URI'])) {
            return $_SERVER['REQUEST_URI'];
        } else {
            throw new \Exception('Please define base_url dossier parameter');
        }

    }

    /**
     * Parse api prefix
     *
     * @param $config
     * @return string
     */
    private function parseApiPrefix($config)
    {
        /**
         * Handle api prefix
         */
        $apiPrefixParsed = parse_url($config['dossier_location']);

        $result = array();

        $result['dossier_id'] = $this->id;
        $result['session_id'] = session_id();
        $result['url'] = '/';

        $q = http_build_query($result);

        $url = $apiPrefixParsed['scheme'] . '://' . $apiPrefixParsed['host'] . $apiPrefixParsed['path'] . '?' . $q;

        return $url;
    }

    /**
     * Parse download prefix
     *
     * @param $config
     * @return string
     */
    private function parseDownloadPrefix($config)
    {
        /**
         * Handle download prefix
         */
        if(!isset($config['download_prefix'])) {
            return $config['api_prefix'] . 'download&file=';
        }

        return $config['download_prefix'];
    }

    /**
     * Store to session
     */
    private function storeToSession()
    {
        if(!isset($_SESSION['dossier'])) {
            $_SESSION['dossier'] = array();
        }

        foreach($_SESSION['dossier'] as $id => $data) {
            if($data['config']['working_dir'] == $this->config['working_dir']) {
                unset($_SESSION['dossier'][$id]);
            }
        }

        $_SESSION['dossier'][$this->id] = [
            'hooks' => $this->hooks,
            'config' => $this->config
        ];
    }

    /**
     * Get from session
     *
     * @param $id
     * @return null
     */
    private function getFromSession($id)
    {
        if(!isset($_SESSION['dossier'])) {
            return null;
        }

        $dossiers = $_SESSION['dossier'];
        if(isset($dossiers[$id])) {
            return $dossiers[$id];
        }

        return null;
    }

    /**
     * Add hook
     *
     * @param $hookName
     * @param $callable
     */
    public function addHook($hookName, $callable)
    {
        if(!isset($this->hooks[$hookName])) {
            $this->hooks[$hookName] = [];
        }

        $serializer = new Serializer();
        $this->hooks[$hookName][] = $serializer->serialize($callable);

        $this->storeToSession();
    }

}