<?php
use \Qii\Application;

use \Qii\Autoloader\Factory;
use Qii\Autoloader\Import;
use \Qii\Autoloader\Psr4;

use \Qii\Config\Register;
/**
 * Qii 框架基本库所在路径
 */
define('QII_DIR', dirname(__FILE__));
/**
 * DIRECTORY_SEPARATOR 的简写
 */
define('DS', DIRECTORY_SEPARATOR);
/**
 * 定义包含的路径分隔符
 */
define('PS', PATH_SEPARATOR);
/**
 * 定义操作系统类型
 */
define('OS', strtoupper(substr(PHP_OS, 0, 3)));

define('IS_CLI', php_sapi_name() == 'cli' ? true : false);
if (IS_CLI) {
    $args = isset($argv) && is_array($argv) && count($argv) > 0 ? $argv : array();
    if(count($args) == 0 && isset($_SERVER['argv'])
        && is_array($_SERVER['argv']) && count($_SERVER['argv']) > 0) {
        $args = $_SERVER['argv'];
    }
    $cliAgs = QiiHandleCliArgs($args);
    $_SERVER['__CLI_ARGS'] = $cliAgs;
    $_SERVER['REQUEST_URI'] = $cliAgs[1] . ($cliAgs[3] ? '?'. $cliAgs[3] : '');
    $_SERVER['QUERY_STRING'] = $cliAgs[3];
    $_SERVER['SCRIPT_NAME'] = $cliAgs[0];
    $_GET = $cliAgs[2];
    $_POST = $cliAgs[2];
    define('PATH_INFO', $cliAgs[1]);
} else {
    define('PATH_INFO', isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '');
}

/**
 * EOL 和 SPACE
 */
define('QII_EOL', IS_CLI ? PHP_EOL : '<br />');
define('QII_SPACE', IS_CLI ? ' ' : '&nbsp;');

require QII_DIR . DS . 'Autoloader' . DS . 'Import.php';
Import::setFileLoaded(QII_DIR . DS . 'Autoloader' . DS . 'Import.php');

Import::requires(
    array(QII_DIR . DS . 'Config' . DS . 'Consts.php',
        QII_DIR . DS . 'Functions' . DS . 'Funcs.php',
        QII_DIR . DS . 'Autoloader' . DS . 'Factory.php',
        QII_DIR . DS . 'Application.php',
        QII_DIR . DS . 'Autoloader' . DS . 'Psr4.php',
        QII_DIR . DS . 'Config' . DS . 'Arrays.php',
    )
);

function QiiHandleCliArgs($parameter) {
    $fileName = array_shift($parameter);
    $uri = array_shift($parameter);
    if(substr($uri, 0, 1) != '/') {
        $uri = "/". $uri;
    }
    //解析parameter
    $params = array();
    $query = [];
    foreach ($parameter as $value) {
        preg_match("/\{(?P<name>(.*?))(\=|\:)(?P<value>(.*).+)\}/", $value, $matches);
        if($matches && isset($matches['name'])) {
            $params[$matches['name']] = $matches['value'];
            $query[] = $matches['name'] .'='. urlencode($matches['value']);
        }else {
            preg_match("/(?P<name>(.*?))(\=|\:)(?P<value>(.*).+)/", $value, $matches);
            if($matches && isset($matches['name'])) {
                $params[$matches['name']] = $matches['value'];
                $query[] = $matches['name'] . '=' . urlencode($matches['value']);
            }else{
                $parameter[$value] = '';
                $query[] = $value .'=';
            }
        }
    }
    return array($fileName, $uri, $params, join("&", $query));
}
class Qii extends Application
{
    public function __construct()
    {
        parent::__construct();
    }
    /**
     * Instance func
     *
     **/
    public static function getInstance()
    {
        if (func_num_args() > 0) {
            $args = func_get_args();
            return call_user_func_array(array('\Qii\Autoloader\Factory', 'getInstance'), $args);
        }
        return Factory::getInstance('\Qii');
    }

    /**
     * 设置private 属性
     *
     * @param String $name
     * @param Mix $value
     */
    public static function setPrivate($name, $value)
    {
        return Psr4::getInstance()->loadClassOnce('\Qii\Config\Arrays')->setPrivate($name, $value);
    }

    /**
     * 获取private属性
     *
     * @param String $name
     * @param String $key
     * @return Mix
     */
    public static function getPrivate($name, $key = '')
    {
        $private = Psr4::getInstance()->loadClassOnce('\Qii\Config\Arrays')->get($name);
        if (preg_match('/^\s*$/', $key)) {
            return $private;
        }
        if (isset($private[$key])) return $private[$key];
    }

    /**
     * 获取语言包内容指定的内容
     *
     * @return mixed
     */
    public static function i()
    {
        return call_user_func_array(array(
            Psr4::getInstance()->loadClassOnce('\Qii\Language\Loader'), 'i'),
            func_get_args()
        );
    }

    /**
     * 错误设置，如果满足给定的条件就直接返回false，否则在设置了错误页面的情况下返回true
     * 如果出错后要终止的话，需要自行处理，此方法不会停止不执行
     *
     * @param Bool $condition
     * @param int $line 出错的行数，这样以便轻松定位错误
     * @param String $msg
     * @param Int|String $code
     * @return Bool
     */
    public static function setError($condition, $line, $code = 0, $args = null, $msg = '')
    {
        return call_user_func_array(array('\Qii\Exceptions\Error', 'setError'), func_get_args());
    }

    /**
     * 抛出异常
     *
     * @return mixed
     */
    public static function e()
    {
        return call_user_func_array(array('\Qii\Exceptions\Errors', 'e'), func_get_args());
    }

    /**
     * 返回当前app的配置
     * @param string $key 如果需要返回单独的某一个key就指定一下这个值
     * @return mixed
     */
    public static function appConfigure($key = null)
    {
        return Register::getAppConfigure(\Qii::getInstance()->getAppIniFile(), $key);
    }

    /**
     * 当调用Qii不存在的方法的时候，试图通过Autoload去加载对应的类
     * 示例：
     * \Qii::getInstance()->Qii_Autoloader_Psr4('instance', 'Model\User')；
     *    此方法将调用：Qii_Autoloader_Psr4->instance('Model\User');
     */
    public function __call($className, $args)
    {
        return call_user_func_array(array(Psr4::getInstance(), 'loadClassOnce'), func_get_args());
    }

    /**
     * 当调用不存在的静态方法的时候会试图执行对应的类和静态方法
     * 斜线将会转换成下划线
     * 示例：
     * \Qii::Qii_Autoloader_Psr4('getInstance')
     *    此方法将调用：\Qii\Autoloader\Psr4::getInstance静态方法
     *    Qii::InstanceApp("App");
     *    此方法将调用：InstanceApp::App()静态方法
     */
    public static function __callStatic($className, $args)
    {
        $method = array_shift($args);
        $className = Psr4::getInstance()->getClassName($className);
        return call_user_func_array($className . '::' . $method, $args);
    }
}

if (!function_exists('catch_fatal_error')) {
    function catch_fatal_error()
    {
        // Getting Last Error
        $error = error_get_last();
        // Check if Last error is of type FATAL
        if (isset($error['type']) && $error['type'] == E_ERROR) {
            // Fatal Error Occurs
            $message = array();
            $message[] = 'Error file : ' . str_replace(Psr4::realpath($_SERVER['DOCUMENT_ROOT']), '', $error['file']);
            $message[] = 'Error line : ' . $error['line'] . ' on ' . \Qii\Exceptions\Errors::getLineMessage($error['file'], $error['line']);
            $message[] = 'Error description : ' . $error['message'];
            if (IS_CLI) {
                $cli = new \Qii\Response\Cli();
                return $cli->stdout(
                    str_replace("&nbsp;"
                        , " "
                        , strip_tags(join(PHP_EOL, preg_replace("/[\n|\r\n]/", PHP_EOL, $message)))
                    )
                );
            }
            \Qii\Exceptions\Error::showError($message);
        }
    }
}

//注册名称空间
$namespace = _include(QII_DIR . DS . 'Config' . DS . 'Namespace.php');
Psr4::getInstance()
    ->register()
    ->setUseNamespaces(isset($namespace['setUseNamespace']) ? $namespace['setUseNamespace']: [])
    ->addNamespaces(isset($namespace['addNamespace']) ? $namespace['addNamespace'] : []);

//加载默认语言包
Factory::getInstance('\Qii\Language\Loader')->load('error', QII_DIR . DS . 'Language');
Factory::getInstance('\Qii\Language\Loader')->load('exception', QII_DIR . DS . 'Language');
Factory::getInstance('\Qii\Language\Loader')->load('resource', QII_DIR . DS . 'Language');


//捕获FATAL错误，用户可以选择记录到日志，还是直接显示或者不显示错误
register_shutdown_function('catch_fatal_error');
set_exception_handler(array('\Qii\Exceptions\Errors', 'getError'));
set_error_handler(array('\Qii\Exceptions\Errors', 'getError'), E_USER_ERROR);
