<?php
 /**
 * ============================================================================
 * Copyright 2014 大秦科技，并保留所有权利。
 * 网站地址: http://www.qintech.net；
 * ----------------------------------------------------------------------------
 * 未获商业授权之前，不得将Magic CMS用于商业用途（包括但不限于企业网站、经营性网站
 * 以营利为目的或实现盈利的网站）未经官方许可，禁止在Magic CMS的整体或任何部分基础
 * 上以发展任何派生版本、修改版本或第三方版本用于重新分发。如果您未能遵守本协议的
 * 条款，您的授权将被终止，所被许可的权利将被收回，并承担相应法律责任。
 * ============================================================================
 * Author: Shiang.Chin
 * Date:2014/12/31
**/
if (!defined('KERNEL_PATH'))exit('No direct script access allowed');
class App {

	 /**
     * 初始化应用
     */
    private function init() {
		date_default_timezone_set(C('DEFAULT_TIME_ZONE'));
        @ini_set('memory_limit',                   '128M');
        @ini_set('register_globals',               'off');
        @ini_set('magic_quotes_runtime',           0);
		define('IS_GET',         request_type('get'));
		define('IS_POST',        request_type('post'));
		define('IS_AJAX',        request_type('ajax'));
		defined('DEBUG')        or define('DEBUG',C('DEBUG'));//调试模式
		defined('DEBUG_TOOL')   or define('DEBUG_TOOL',C('DEBUG_TOOL'));//调试模式
		defined('MODULE_PATH')  or define('MODULE_PATH',APP_PATH.C('MODULE_PATH').'/');//模块路径
		//session处理
        session(C('SESSION_OPTIONS'));
		define('PHPSESSID',session_id());
		//注册自动载入函数
        spl_autoload_register(array(__CLASS__,     'autoload'));
		set_error_handler(array(__CLASS__,         'error'), E_ALL);
        set_exception_handler(array(__CLASS__,     'exception'));
        register_shutdown_function(array(__CLASS__,'fatalError'));

		//检查移动设备
		self::MobileDetect();
		//解析路由
        Route::parseUrl();
	}
	/**
     * 应用入口
     */
	public function run() {
		//加载核心文件
		self::loadCoreFile();
		//加载基本配置
        self::loadConfig();
		 //应用初始化
        self::init();
		self::install();
		//开始运行
        DEBUG and Debug::start('APP_BEGIN');

		self::start();

		self::install();

		//Debug End
        DEBUG and DEBUG_TOOL and Debug::show('APP_BEGIN', 'APP_END');
        //日志记录
        !DEBUG and C('LOG_RECORD') and Log::save();

	}

	/**
     * 加载基本配置
     * @access private
     */
    static private function loadConfig(){
		//加载默认配置
		require(CONFIG_PATH . 'Config.class.php' );
		$de_config = $config;
		//加载应用配置
		is_file(DATA_PATH. 'Config/config.php') AND require(DATA_PATH . 'Config/config.php');
		$app_config = $config;

        is_file(DATA_PATH. 'Config/config.php') AND $config = array_merge($de_config ,$app_config);

		//加载数据库配置
        is_file(ROOT_PATH. 'Config.php') AND $config = array_merge($config ,C(require(ROOT_PATH . 'Config.php')));
		return C($config);
	}

	/**
     * 安装检测
     * @access private
     */
	static private function install(){
		if (!C('INSTALL_LOCK') && MODULE !=='Install')
			redirect('/?r=install');
	}


	/**
     * 检查移动设备//定义模板目录
     * @access private
     */
    static private function MobileDetect(){
		if (C('MOBILE_SITE')){
			$Mobile = new Mobile();
			if($Mobile->isMobile() || $Mobile->isiOS() || $Mobile->isTablet() || $Mobile->isAndroidOS() || $Mobile->isWindowsPhoneOS()) {
				$tpl_mobile = '/'.C('TPL_MOBILE');
			}else{
				$tpl_mobile='';
			}
		}
		//模板风格
		define('TPL_STYLE', C('TPL_STYLE') . $tpl_mobile);

		//模板路径
		define('TPL_PATH',  C('TPL_PATH')  .TPL_STYLE);
	}



	/**
     * 加载核心文件
     * @access private
     * @return void
     */
    static private function loadCoreFile(){
        $files = array(
			CORE_PATH .'Route'.EXT,         //路由处理类
			CORE_PATH .'Error'.EXT,         //异常处理类
			CORE_PATH .'Log'.EXT,           //日志处理类
			CORE_PATH .'Debug'.EXT,         //debug调式处理类
			FUNCTION_PATH.'Function.php',   //应用函数
        );
        foreach ($files as $value) {
            require_once($value);
        }
    }

	/**
     * 运行应用
     * @access private
     */
    static private function start(){

		//当控制器或者插件或者空控制器存在时则实例化控制器
		if (require_cache(MODULE_PATH.MODULE.'/'.CONTROLLER.C('MODULE_SUFFIX').EXT) && class_exists(CONTROLLER.C('MODULE_SUFFIX'))){

			$class = CONTROLLER.C('MODULE_SUFFIX'); //完整的模块名称

		}elseif($suffix = require_array(C('MODULE_EXT'),MODULE)){

			$class = CONTROLLER.$suffix; //插件或扩展模块

		}elseif(require_cache(MODULE_PATH .C('MODULE_EMPTY').C('MODULE_SUFFIX').EXT) && class_exists(C('MODULE_EMPTY').C('MODULE_SUFFIX'))){

			$class = C('MODULE_EMPTY').C('MODULE_SUFFIX');	//空模块

		}else{
			_404(MODULE.'模块的'.CONTROLLER.'类不存在');
		}

		$object = new $class(); //实例化控制器

		//构造函数
		if (method_exists($object, '__init')) {
            $object->__init();
        }

		//检测模块的方法
		if(ACTION && !method_exists($object,ACTION)){
			_404(CONTROLLER.C('MODULE_SUFFIX').EXT.'类的'.ACTION.'方法不存在');
		}

        //执行动作
        try {
            $action = new ReflectionMethod($object,ACTION);
            if ($action->isPublic()) {
                $action->invoke($object);
            } else {
                throw new ReflectionException;
            }
			//构造函数模块执行完运行
			if (method_exists($object, '__end')) {
				$object->__end();
			}
        } catch (ReflectionException $e) {
            $action = new ReflectionMethod($object, '__call');
            $action->invokeArgs($object, array(ACTION, ''));

        }
    }

	/**
     * 实现类的自动加载
     * @param $e
     */
	static public function autoload($classname){
		$dirarray = array(
		    DRIVER_PATH.'Cache/',  //加载缓存驱动
			DRIVER_PATH.'View/',   //加载视图驱动
			DRIVER_PATH.'Db/',     //加载数据库驱动
			DRIVER_PATH.'Model/',  //加载数据模型驱动
			MODULE_PATH.'Common/', //加载公共模块
			MODULE_PATH,           //加载模块文件
			LIBRARY_PATH,          //扩展类库

		);
		$dirarray = array_merge($dirarray,C('AUTOLOAD_FILE'),C('MODULE_EXT'));
		foreach($dirarray as $value) {
			$file = $value.ucfirst($classname).EXT;
			if (is_file($file) ) {
				require_cache($file);
				return true;
			}
		}
		return false;
	}

	/**
     * 错误处理
     * @param $e
     */
    static public function error($errno, $error, $file, $line){
			switch ($errno) {
				case E_ERROR:
				case E_PARSE:
				case E_CORE_ERROR:
				case E_COMPILE_ERROR:
				case E_USER_ERROR:
						ob_end_clean();
						$msg = $error.' '. $file . " 第 $line 行.";
						if(C('LOG_RECORD')) Log::write("[$errno] " . $msg, Log::ERROR);
						function_exists('error') ? error($msg) : exit('ERROR:' . $msg);
						break;

				default:
					$errorStr = "[$errno] $error " . $file . " 第 $line 行.";
					trace($errorStr, 'NOTICE', true);
					//SHUT_NOTICE关闭提示信息
					if (DEBUG && C('SHOW_NOTICE'))
						require KERNEL_PATH . 'Tpl/notice.html';
					break;
			}
    }

	/**
     * 致命错误处理
     * @param $e
     */
    static public function fatalError(){
        if(function_exists('error_get_last')){
            if ( $e = error_get_last()) {
                self::error($e['type'], $e['message'], $e['file'], $e['line']);
            }
        }
    }

	/**
     * 自定义异常理
     * @param $e
     */
    static public function exception($e){
        error($e->__toString());
    }

}

