<?php
/**
 * Registry class
 * This class with hold shared/global variables needed for the entire system during each user request
 * Some common variables
 *      + $user_info
 *      + $company_info
 *
 */

namespace Hura8\System;

final class Registry {
    /**
     * Hold all other class instances
     * Example:
     * array(
    'user'  => $user;
     * )
     *
     * Usage: if we want to use the $user instance of User class, do this
     * $user = Registry::getInstance('user');
     */
    private static $instances = [];

    /**
     * Hold all shared variables used for views
     * Example:
     * array(
    'user_info'  => $user_info;
     * )
     *
     * Usage: if we want to use the $user instance of User class, do this
     * $user_info = Registry::getVariable('user_info');
     */
    private static $variables = [];

    /**
     * hold template variables to render in the template
     * Example:
     * array(
    'user_info'  => $user_info;
     * )
     *
     */
    private static $tpl_vars = [];

    /**
     * hold registered plugins for each template
     * Example:
     * array(
    'homepage/homepage'  => [

    ];
     * )
     *
     */
    private static $register_plugins = [];


    private function __construct(){
        //do nothing
    }

    private function __clone(){
        //do nothing
    }

    public static function setInstance($key, $value){
        self::$instances[$key] = $value;
    }

    public static function getInstance($key){
        return isset( self::$instances[$key]) ?  self::$instances[$key] : null;
    }

    //02-11-2015 create an instance for a class and save it
    public static function createInstance($className, $class_constructor_args = array()){
        $key = strtolower($className);
        if(self::getInstance($key)) {
            return self::getInstance($key);
        }else{
            //check for additional arguments for __constructor
            if (sizeof($class_constructor_args)) {
                $class = new \ReflectionClass($className);
                $instance = $class->newInstanceArgs($class_constructor_args);
                //$instance = new $className();
                self::setInstance($key, $instance);
            }else{
                //$className = 'Adman\\'.$className;
                $instance = new $className();
                self::setInstance($key, $instance);
            }

            return $instance;
        }
    }

    public static function setVariables($key, $value = ''){
        if(is_array($key)) {
            foreach ($key as $_k => $_v) {
                self::$variables[$_k] = $_v;
            }
        } else {
            self::$variables[$key] = $value;
        }
    }

    public static function getVariable($key){
        return self::$variables[$key] ?? null;
    }

    //set key=> value or array(key=>value)
    public static function setTplVar($key, $value = ''){
        if(is_array($key)) {
            foreach ($key as $_k => $_v) {
                self::$tpl_vars[$_k] = $_v;
            }
        } else {
            self::$tpl_vars[$key] = $value;
        }
    }

    public static function getTplVar(){
        return self::$tpl_vars;
    }

    //set key=> value or array(key=>value)
    public static function setPlugins($tpl, $plugin_name, callable $callable, $parameters){

        if(!isset(self::$register_plugins[$tpl])) self::$register_plugins[$tpl] = [];

        //not allow to overwrite
        if(isset(self::$register_plugins[$tpl][$plugin_name])) return false;

        self::$register_plugins[$tpl][$plugin_name] = [
            "callable" => $callable,
            "para"  => $parameters,
        ];

        return true;
    }

    public static function getPlugins($tpl){
        return (isset(self::$register_plugins[$tpl])) ? self::$register_plugins[$tpl] : false;
    }

    public function __destruct(){
        self::$instances = null;
        self::$variables = null;
    }
}
