<?php
/**
 * Link         :   http://www.phpcorner.net
 * User         :   qingbing<780042175@qq.com>
 * Date         :   2018-12-05
 * Version      :   1.0
 */

namespace Abstracts;

use Config;
use Helper\Exception;

abstract class Component extends Base
{
    /* @var Component[] */
    private static $_instances = [];

    /**
     * 组件实例化
     * @param mixed $configs
     * @return $this
     * @throws Exception
     */
    public static function getInstance($configs = null)
    {
        if (null === $configs) {
            throw new Exception('组件实例化参数为空', 100300101);
        }
        if (is_string($configs)) {
            $configs = Config::getInstance($configs)->getAll();
        } else if (!is_array($configs)) {
            throw new Exception('组件实例化参数错误', 100300102);
        } else if (isset($configs['c-file'])) {
            if (isset($configs['c-group']) && !empty($configs['c-group'])) {
                $configs = Config::getInstance($configs['c-file'], $configs['c-group'])->getAll();
            } else {
                $configs = Config::getInstance($configs['c-file'])->getAll();
            }
        }

        $className = get_called_class();
        $id = md5($className . serialize($configs));
        if (!isset(self::$_instances[$id])) {
            if (!is_array($configs)) {
                throw new Exception('组件实例化时参数必须为数组', 100300103);
            }
            $instance = new $className($configs);
            if (!$instance instanceof Component) {
                throw new Exception('组件必须继承基类"\Abstracts\Component"', 100300104);
            }
            $instance->init();
            self::$_instances[$id] = $instance;
        }
        return self::$_instances[$id];
    }

    /**
     * 构造函数
     * constructor.
     * @param array $configs
     */
    final public function __construct(array $configs = [])
    {
        $this->configure($configs);
    }

    /**
     * 属性赋值后执行函数
     */
    abstract public function init();
}