<?php

/**
 * Class
 *
 * 组件创建器
 */
class Atom_Component_Creator {

	public $config = array();
    public $path = '';
    public $className = '';

    static public $cache = array();

	/**
     * return the absolute path of the component file
     * @param $componentPath string
     * @return string|void
     */
    private static function resolveComponentPath($componentPath) {

        if (!is_string($componentPath)) {
            return;
        }

        static $cache = array();

        $postfix = '.php';
        $postfixLength = 4;
        if (substr($componentPath, strlen($componentPath) - $postfixLength) !== $postfix) {
            $componentPath .= $postfix;
        }

        if (isset($cache[$componentPath])) {
            return $cache[$componentPath];
        }

        if ($componentPath[0] === DIRECTORY_SEPARATOR && is_file($componentPath)) {
            $cache[$componentPath] = $componentPath;
            return $componentPath;
        }

        foreach (Atom_Global_Config::$componentsDir as $dir) {
            $path = realpath($dir . DIRECTORY_SEPARATOR . $componentPath);
            if (is_file($path)) {
                $cache[$componentPath] = $path;
                return $path;
            }
        }
    }

	/**
	 * 获取组件的配置
	 *
	 * @param $componentPath string 组件名
	 * @return array
	 * @throws Exception
	 */
	public static function getConfig($componentPath) {

		static $cache = array();

        $filePath = self::resolveComponentPath($componentPath);

		if (!isset($filePath)) {
		    throw new Exception('[Atom Runtime] resolve component path fail. ' . $componentPath);
        }

        if (isset($cache[$filePath])) {
            return $cache[$filePath];
        }

		$_vue_component = new Atom_Component_Creator();

		$_vue_component->path = $filePath;

        include($filePath);

        $cache[$filePath] = $_vue_component;

		return $_vue_component;
	}

	/**
     * 工厂函数
     * @param $componentPath string 组件名
     * @param $context Atom_Component 父组件
     * @return Atom_Component
     * @throws Exception
     */
    public static function createInstance ($componentPath, $context = null) {
        $atom_creator = self::getConfig($componentPath);
        return new $atom_creator->className($atom_creator->path, $context, $atom_creator->config);
    }

    /**
     * This function is executed automatically when a compiled .php file is included
     * - Accept the config from compiled atom component file
     * @param $config array
     * @return bool flag if should define render function
     */
    private function configure ($config) {

        // 获取版本号
        $runtimeVersion = $config['runtime_version'];

        // if compiled component has no runtime_version, we set a default version `runtime_default` to it;
        // some old environments still have compiled runtime version embeded.
        if (!$runtimeVersion) {
            $runtimeVersion = 'runtime_default';
        }

        $this->className = "\\Atom\\$runtimeVersion\\Atom_Component";

        // 如果已经加载过，就不重复加载了
        if (!isset(self::$cache[$this->className])) {

            $classFilepathPrefix = ATOM_DIR . "lib" . DIRECTORY_SEPARATOR . $runtimeVersion . DIRECTORY_SEPARATOR;
            $classFilepath = $classFilepathPrefix . "instance/Atom_Component.php";

            // 类文件不存在，需要报错
            if (!is_file($classFilepath)) {
                throw new Exception('[Atom Runtime] Atom_Component is not exist: ' . $classFilepath);
            }

            // 加载需要的类
            require($classFilepath);

            self::$cache[$this->className] = 1;
        }

        $this->config = &$config;

        return !function_exists($config['render']);
    }

}
