<?php
defined( 'IN_WEB') or die( 'Include Error!');
class oo {
	static $oo = array();
	static $config = array();
	static $aConfigLang = array();
	static $aConfigLangActivity = array();
	static $aConfigLangActImg = array();
	static $aConfigLangActBtnName = array();
	static $configOnoff = array();
    /**@var $objRedis muredis[]*/
	static $objRedis = array();
    /**@var $objDb DB[]*/
	static $objDb = array();
	static $objModel = array();
	/**@var $objCache mucache[]*/
    static $objCache = array();
    static $configLang = array();
    static $objNsq =array();
//    public $versionShineUpon = [];
	/**
	 * 设置全局配置变量
	 */
	static function setConfig($config){
		self::$config = $config;
	}

	/**
	 * 错误输出
	 * @return ModelError
	 */
	public static function error(){
		if (!is_object( self::$oo['error'])) {
			include_once PATH_MOD . 'error.php';
			self::$oo['error'] = new ModelError();
		}
		return self::$oo['error'];
	}


	/**
	 * @return ModelLogs
	 */
	public static function logs(){
		if( ! is_object( self::$oo['logs'])){
			include_once PATH_MOD . 'logs.php';
			self::$oo['logs'] = new ModelLogs();
		}
		return self::$oo['logs'];
	}


	/**
	 * @return functions
	 */
	static function functions(){
		if (!is_object( self::$oo['functions'])) {
			include_once PATH_LIB . 'class.functions.php';
			self::$oo['functions'] = new functions();
		}
		return self::$oo['functions'];
	}
	/**
	 * 返回创建好的facebook对象
	 * @return facebooksdk4
	 */
	static public function facebooksdk4(){
		if (!is_object( self::$oo['facebooksdk4'])) {
			if( is_file( PATH_LIB . 'class.boyaa.php' )){
				include PATH_LIB . 'class.boyaa.php';
				Boyaa::init();
			}
			include_once PATH_LIB . 'class.facebooksdk4.php';
			self::$oo['facebooksdk4'] = new facebooksdk4();
		}
		return self::$oo['facebooksdk4'];
	}
	/**
	 * make新版的cserver对象
	 * @return IDataServer
	 */
	public static function cserver() {
		if( ! is_object( self::$oo[__METHOD__])){
			include_once PATH_LIB . 'cserver/cserver.php';
			self::$oo[__METHOD__] = new IDataServer();
		}
		return self::$oo[__METHOD__];
	}


    /**
     * 越南支付
     * @return mixed
     */
	public static function vnpt() {
        if( ! is_object( self::$oo[__METHOD__])){
            include_once PATH_LIB . 'VNPT_V2/VNPT.php';
            self::$oo[__METHOD__] = new VNPT();
        }
        return self::$oo[__METHOD__];
    }

	/**
	 * 广播SERVER
	 * @return IBroadCastServer
	 */
	public static function broadCastServer(){
		if( ! is_object( self::$oo[__METHOD__])){
			include_once PATH_LIB . 'cserver/IBroadCastServer.php';
			self::$oo[__METHOD__] = new IBroadCastServer();
		}
		return self::$oo[__METHOD__];
	}
	/**
	 * ESPacket
	 * @return ESPacket
	 * @author JasonZhou
	 */
	public static function ESPacketServer(){
		if( ! is_object( self::$oo[__METHOD__])){
			include_once PATH_LIB . 'cserver/ESPacket.php';
			self::$oo[__METHOD__] = new ESPacket();
		}
		return self::$oo[__METHOD__];
	}




	/**
	 * 分页
	 * @return Pager
	 */
	public static function pager(){
		if( ! is_object( self::$oo[__METHOD__])){
			include_once PATH_LIB . 'class.pager.php';
			self::$oo[__METHOD__] = new Pager();
		}
		return self::$oo[__METHOD__];
	}

	/**
	 * 操作库
	 * @param $table string 表名兼配置文件名称
     * @return DB
	 */
	static public function commonOprDb($table = ''){
		if( !$table ) return -1;
		$table = strtolower($table);
		if( ! is_object(self::$objDb[$table])){
			include_once PATH_LIB . 'class.db.php';
			self::$objDb[$table] = new DB( oo::$config['db_'.$table]);
		}
		return self::$objDb[$table];
	}

	/**
	 * 通用操作redis
	 * @param $configname string key名称
     * @return muredis
	 */
	static public function commonOprRedis($configname = '')
	{
		if( !$configname ) return -1;
        $configname = strtolower($configname);
		$confName = ucfirst($configname);
        if(empty(oo::$config['redis'.$confName])){
            var_dump($confName);
        }
		if (!is_object(self::$objRedis[$configname])) {
			include_once PATH_LIB . 'class.muredis.php';
			self::$objRedis[$configname] = new muredis(oo::$config['redis'.$confName]);
			self::$objRedis[$configname]->seria = false;
		}
		return self::$objRedis[$configname];
	}

    /**
     * Notes:nsq
     * User: wsc
     * Time: 2021/11/2 15:12
     */
    static public function commonOprNsq($nsqdAddr){
        if (!is_object(self::$objNsq[$nsqdAddr])) {
            include_once PATH_LIB . 'class.muredis.php';
            $nsq = new Nsq();
            $isTrue = $nsq->connectNsqd($nsqdAddr);
            if($isTrue){
                self::$objNsq[$nsqdAddr] =$nsq;
            }
        }
        return self::$objNsq[$nsqdAddr];
    }
    /**
     * 通用操作Model方法
     * @param string $modelname
     * @return object|int
     */
	static public function commonOprModel($modelname = ''){
	    if( !$modelname ) return -1;
	    $modelname = strtolower($modelname);
	    $className = 'Model'.ucfirst($modelname);
        if (!is_object( self::$objModel[$modelname])) {
            include_once PATH_MOD . $modelname.'.php';
            if(!class_exists($className)){ //排查不存在的实例化对象
                self::logs()->debug3(['class' => $className, 'modelname' => $modelname], 'oo_class_notfound.log');
            }
            self::$objModel[$modelname] = new $className();

        }

        return self::$objModel[$modelname];
    }

    /**
     * 通用memcache缓存
     * @param string $keyname
     * @return mucache
     */
    static public function commonOprCache($configname = ''){
        if( !$configname ) return -1;
        $configname = strtolower($configname);
        if (!is_object( self::$objCache[$configname])) {
            include_once PATH_LIB . 'class.mucache.php';
            self::$objCache[$configname] = new mucache(oo::$config[$configname]);
        }
        return self::$objCache[$configname];
    }

    /**
	 * 验证是否有这个全局变量
	 * @param unknown $constName
	 * @return mixed|boolean
	 */
	public static function flag($constName)
	{
		if (defined($constName))
		{
			return constant($constName);
		}
		return false;
	}

	////////////////////////
	//	lang
	////////////////////////
    /**
     * 获取语言配置文档
     * @return array
     */
    static public function getLang($value='')
    {
        if (empty(self::$aConfigLang)){
            $lConf = include_once PATH_LNG;
            self::$aConfigLang = $lConf;
        }
        return self::$aConfigLang[$value];
    }


    /**
     * 获取当前sid
     * @param int $uid
     * @return int
     */
    static public function getDefinedSid($uid = 0) {
//        if(!defined('WORKERNAME') || empty($uid)){
//            return defined('SGSID') ? SGSID : 1;
//        }
        $sid = (int)self::commonOprRedis('Userinfo')->hGet(okeys::userDefinedInfo($uid), 'sid');
        return empty($sid) ? 1 : $sid;
    }

    /**
     * 获取当前lid
     * @param int $uid
     * @return int
     */
    static public function getDefinedLid($uid = 0) {
        if(!defined('WORKERNAME') || empty($uid)){
            return defined('SGLID') ? SGLID : 2;
        }
        $lid = (int)self::commonOprRedis('Userinfo')->hGet(okeys::userDefinedInfo($uid), 'lid');
        return empty($lid) ? 1 : $lid;
    }

    /**
     * 获取当前deviceid
     * @param int $uid
     * @return int
     */
    static public function getDefinedDeviceId($uid = 0, $sid = 0) {
        if(empty($sid)){
            if(!defined('WORKERNAME') || empty($uid)){
                return defined('DEVICEID') ? DEVICEID : 2;
            }
            $sid = self::getDefinedSid($uid);
        }
        if(isset(self::$configs['device'])){
            $configs = self::$configs['device'];
        }else{
            $configs = [ 1	=>	1, 2	=>	2, 3	=>	1 ];
        }
        if(!isset($configs[$sid])){
            return 2;
        }
        return !isset($configs[$sid]) ? 2 : $configs[$sid];
    }

    /**
     * 获取当前lang
     * @param int $uid
     * @return int
     */
    static public function getDefinedLang($uid = 0) {
        //if(!defined('WORKERNAME') || empty($uid)){
        //    return defined('LANG') ? LANG : 'en';
        //}
        $lang = self::commonOprRedis('Userinfo')->hGet(okeys::userDefinedInfo($uid), 'lang');
        if(empty($lang)){
            return '';
        }
        return $lang;
    }

    /**
     * 获取当前PATH_LNG
     * @param int $uid
     * @return int
     */
    static public function getPathLang($uid = 0) {
        if(!defined('WORKERNAME') || empty($uid)){
            return defined('PATH_LNG') ? PATH_LNG : WWWROOT . 'lang/cc_lang.en.php';
        }
        $lang = self::commonOprRedis('Userinfo')->hGet(okeys::userDefinedInfo($uid), 'lang');
        if(empty($lang)){
            return WWWROOT . 'lang/cc_lang.en.php';
        }
        $fileLang = WWWROOT . 'lang/cc_lang.'.$lang.'.php';
        if(file_exists($fileLang)) {
            return $fileLang;
        }
        return $fileLang;
    }

	/**
	 * 获取配置通用接口
	 * @param string $key
	 * @return array
	 */
	public static function cfg($key) {
		$cacheKey = 'CFG_'.$key;
		if (!isset(self::$oo[$cacheKey])) {
			$file = COM_CFG . sprintf("config.%s.php", $key);
			if (!file_exists($file)) {
				$file = COM_CFG . sprintf("%s.php", $key);
				if (!file_exists($file)) return array();
			}
			self::$oo[$cacheKey] = include_once($file);
		}
		return self::$oo[$cacheKey];
	}
    /**
     * 获取tl配置接口
     * @param string $key
     * @return array
     */
    public static function cfgs($key) {
        $cacheKey = 'TL_CFG_'.$key;
        if (!isset(self::$oo[$cacheKey])) {
            $file = PATH_CFG . sprintf("config.%s.php", $key);
            if (!file_exists($file)) {
                $file = PATH_CFG . sprintf("%s.php", $key);
                if (!file_exists($file)) return array();
            }
            self::$oo[$cacheKey] = include_once($file);
        }
        return self::$oo[$cacheKey];
    }
	/**
	 * 登录
	 * @return login
	 */
	public static function login($uid = 0){
		$cacheKey = __METHOD__ . $uid;
		if( ! is_object( self::$oo[$cacheKey])){
			include_once PATH_MOD . 'login.php';
			self::$oo[$cacheKey] = new ModelLogin($uid);
		}
		return self::$oo[$cacheKey];
	}

	/**
	 * 版本比较大小
	 * @return version
	 */
	public static function version(){
		if( ! is_object( self::$oo[__METHOD__])){
			include_once PATH_LIB . 'version.php';
			self::$oo[__METHOD__] = new version();
		}
		return self::$oo[__METHOD__];
	}


    /**
     * 统一输出返回json内容
     *
     * @access public
     * @date   2016-08-16
     * @param int    $code  状态码,0成功
     * @param string $msg  错误信息
     * @param array  $data 返回数据内容
     * @param bool  $checkNum 返回數字
     * @return string;
     */
    public static function response($code,$data = [],$msg = '',$checkNum = false){
        $result = [
            'code' => $code,
            'msg'  => $msg,
            'data' => $data,
        ];
        return json_encode($result,JSON_NUMERIC_CHECK);
    }

    /**
     *
     * @param $code
     * @return array
     */
    public static function res($code) {
        return ['code'=>$code];
    }


    /**
     * 使用CI框架的数据库操作类, 来实现ORM操作
     */
    public static function ormdb(){
        if (!is_object(self::$objDb[__METHOD__])){
            include_once PATH_LIB . 'ormdb/DB_driver.php';
            include_once PATH_LIB . 'ormdb/DB_query_builder.php';
            include_once PATH_LIB . 'ormdb/mysqli_driver.php';

            $mysqlInfo = array(
                'dsn'	=> '',
                'hostname' => '127.0.0.1',
                'port'     => '3306',
                'username' => 'root',
                'password' => '123456',
                'database' => '',
                'dbdriver' => 'mysqli',
                'dbprefix' => '',
                'pconnect' => FALSE,
                'db_debug' => (PRODUCTION_SERVER !== 'production'),
                'cache_on' => FALSE,
                'cachedir' => '',
                'char_set' => 'utf8',
                'dbcollat' => 'utf8_general_ci',
                'swap_pre' => '',
                'encrypt' => FALSE,
                'compress' => FALSE,
                'stricton' => FALSE,
                'failover' => array(),
                'save_queries' => TRUE
            );
            self::$objDb[__METHOD__] = new CI_DB_mysqli_driver($mysqlInfo);
            self::$objDb[__METHOD__]->initialize();
        }
        return self::$objDb[__METHOD__];
    }

    /**
     * 前端展示用的uid
     * 默认加10000
    */
    public static function En_VirtualUid($uid)
    {
        $uid = self::functions()->uint($uid);

        $uid += 10000;

        return (int)$uid;

    }

    /**
     * 还原一下uid
     * 默认加10000
     */
    public static function De_VirtualUid($uid)
    {
        $uid = self::functions()->uint($uid);

        $uid -= 10000;

        return (int)$uid;

    }

    /**
     * 金币千分位后面抹零
    */
    public static function Thousand($num = 0){

        $num = self::functions()->uint($num);
        if($num < 1000){
            return $num;
        }

        $new_num =  ($num / 1000) ;
        return intval(floor($new_num)*1000);
    }

	/**
     * 比较版本
     * @param $v1
     * @param $v2
     * @param bool $equ
     * @return bool
     * Created by: Owen
     * Created on: 2019/8/29 10:57
     * Description:
     * 默认比较大于等于，成立返回true,否则返回false;
     * $equ = false 时比较大于，成立返回true,否则返回false;
     */
    public static function compareVersion($v1,$v2,$equ = true){
        $v1 = explode('.',$v1);
        $v2 = explode('.',$v2);
        $len = max(count($v1), count($v2));
        while (count($v1) < $len) {
            array_push($v1,0);
        }
        while (count($v2) < $len) {
            array_push($v2,0);
        }
        for ($i = 0; $i < $len; $i++) {
            $num1 = intval($v1[$i]);
            $num2 = intval($v2[$i]);
            if ($num1 > $num2) {
                return true;
            } else if ($num1 < $num2) {
                return false;
            }
        }
        if($equ) {
            return true;
        }else{
            return false;
        }
    }

    /**
     * 版本映射
     * @param $version
     * @return string
     * Created by: Owen
     * Created on: 2020/3/31 17:37
     */
//    static function versionShineUpon($version){
//        $versionArr = explode(".",$version);
//        $len = count($versionArr);
//        if(4-$len > 0){
//            for($i=0;$i<4-$len;$i++){
//                $versionArr[] = 0;
//            }
//            $version = implode('.',$versionArr);
//        }
//        $version = intval(str_replace('.','',$version));
//        $versionConfig = include PATH_CFG . 'config.version.php';
//        $versionConfig = $versionConfig[SGSID];
//        $returnVersion = "";
//        foreach ($versionConfig as $key=>$row){
//            $tempKey = intval(str_replace('.','',$key));
//            if($tempKey <= $version){
//                $returnVersion = $row;
//            }else{
//                return $returnVersion;
//            }
//        }
//        return $returnVersion;
//    }


  	/**
     * 获取IP
     * @return mixed|null
     * Created by: Owen
     * Created on: 2019/9/23 20:15
     */
    public static function getIp()
    {
        $ip = '';
        if ($_SERVER['HTTP_CLIENT_IP'] && strcasecmp($_SERVER['HTTP_CLIENT_IP'], 'unknown')) {
            $ip = $_SERVER['HTTP_CLIENT_IP'];
        } elseif ($_SERVER['HTTP_X_FORWARDED_FOR'] && strcasecmp($_SERVER['HTTP_X_FORWARDED_FOR'], 'unknown')) {
            $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        } elseif (isset($_SERVER['REMOTE_ADDR']) && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
            $ip = $_SERVER['REMOTE_ADDR'];
        } elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
        preg_match('/^((?:\d{1,3}\.){3}\d{1,3})/', $ip, $match);
        return $match ? $match[0] : null;
    }

    /**
     * Notes:获取毫秒时间搓
     * User: wsc
     * Time: 2019/12/28 11:52
     * @return float
     */
    public  static function getMsectime() {
          list($msec, $sec) = explode(' ', microtime());
          return (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
      }
  	/**
     * 今日剩余时间
     * @return false|int
     * Created by: Owen
     * Created on: 2019/11/29 20:09
     */
    public static function todayDeadline(){
        return strtotime('23:59:59') - time();
    }
  	
  	/**
     * 本周剩余时间 -- 周日第一天
     * @return false|int
     * Created by: Owen
     * Created on: 2019/11/30 12:17
     */
    public static function weekDeadline(){
        return mktime(23,59,59,date('m'),date('d')-date('w')+6,date('Y')) - time();
    }

    /**
     * Notes:异步任务处理类
     * User : wsc
     * Date : 2020/1/10 11:28
     * @return  async
     */
    public static function  async(){
        $key = 'lib_async';
        if (!isset(self::$oo[$key]) || !is_object(self::$oo[$key])) {
            include_once PATH_LIB . 'async.php';
            $obj = new async();
            self::$oo[$key] = $obj;
        }
        return self::$oo[$key];
    }
    /**
     * Notes:清理内存
     * User : wsc
     * Date : 2020/1/9 19:06
     * @return bool
     */
    public static function destroy(){
        self::$oo = [];
        self::$objModel = [];
//        self::$config = [];
        return true;
    }

    /**
     * Notes:清理链接
     * User : wsc
     * Date : 2020/1/10 10:46
     * @return bool
     */
    public static function closeDbAndNosql(){
        //清理mysql链接
        if(isset(self::$objDb)&&!empty(self::$objDb)&&is_array(self::$objDb)){
            foreach (self::$objDb as $db){
//                self::logs()->commlog( date('H:i:s').'close to db\n', 'async/closedb' );
                $db->close();
            }
        }
        self::$objDb = [];
        //清理redis链接
        if(isset(self::$objRedis)&&!empty(self::$objRedis)&&is_array(self::$objRedis)){
            foreach (self::$objRedis as $redis){
                $redis->close();
            }
        }
        self::$objRedis = [];
        //清理memcached链接
        if(isset(self::$objCache)&&!empty(self::$objCache)&&is_array(self::$objCache)){
            foreach (self::$objCache as $k=> $cache){
                $cache->close($k);
            }
        }
        self::$objCache = [];
        return true;
    }

    /**
     * Notes:接口路由
     * User: wsc
     * Time: 2020/4/30 12:05
     * @return router
     */
    public static function router(){
        $key = 'lib_router';
        if (!isset(self::$oo[$key]) || !is_object(self::$oo[$key])) {
            include_once PATH_LIB . 'router.php';
            $obj = new router();
            self::$oo[$key] = $obj;
        }
        return self::$oo[$key];
    }

    /**
     * Notes:
     * User: wsc
     * Time: 2020/5/21 18:07
     * @return Ip2Region
     */
    public static function ipAlg(){
        $key = 'lib_Ip2Region';
        if (!isset(self::$oo[$key]) || !is_object(self::$oo[$key])) {
            include_once PATH_LIB . 'Ip2Region.class.php';
            $dbfile = PATH_LIB."ipdb/ip2region.db";
            $obj = new Ip2Region($dbfile);
            self::$oo[$key] = $obj;
        }
        return self::$oo[$key];
    }

    /**
     * Notes:偷打等级区间
     * User: wsc
     * Time: 2020/6/29 11:36
     * @param $name
     * @param $levelId
     * @return mixed
     */
    public static function getActionLevel($name,$levelId){
        $cfg = oo::cfg('stealattack')[$name];
        $L   = max(1,$cfg['lvInterval']['L']);
        $UN  = max(5,$cfg['lvInterval']['UN']);
        $actionLevel['min'] = max(4,$cfg['minLv']);
        if($name=='steal'){
            $DN   = max(5,$cfg['lvInterval']['DN']);
            $actionLevel['min'] = max($cfg['minLv'],$levelId - intval((intval($levelId/$L) +1) ) * $DN);
        }else if($name=='attack' && $levelId <= 20){
            $UN = 3;
        }
        $actionLevel['max']= max(4,$levelId + intval((intval($levelId/$L) +1)) * $UN);
        return $actionLevel;
    }

    /**
     * Notes:设置当日过去累计值
     * User: wsc
     * Time: 2020/8/3 16:05
     * @param $id
     * @param $subkey   4:当日获得体力累计值  5:今日粉丝页面开启体力加速次数 6:今日是否粉丝页面开启crrazy_bet次数
     * @param int $incr
     * @return false|int
     */
    public static  function limit($id, $subkey, $incr = 0){
        $incr2 = $incr;
        $key = okeys::teDayLimit($id, $subkey);
        if($incr==0){
            $incr = self::commonOprRedis('common')->get($key);
            $incr = $incr?$incr:0;
            return intval($incr);
        }else{
            $incr = self::commonOprRedis('common')->incrBy($key, $incr);
        }
        // 初次设置时，设置过期时间点为第二天0点
        if($incr==$incr2){
            $time = strtotime(date("Y-m-d")) + 3600*24;
            self::commonOprRedis('common')->expireAt($key, $time);
        }
        return intval($incr);
    }

    /**
     * 消耗时间
     * @param float $start
     * @return float
     */
    public static function timeReleased($start = 0) {
        if(empty($start)){ //开始时间
            $tmp = explode(' ', microtime());
            $start = $tmp[0] + $tmp[1];
            return $start;
        }
        $tmp = explode(' ', microtime());
        $end = $tmp[0] + $tmp[1];
        return $end - $start;
    }

    /**
     * redis过期时间添加一个随机值
     * @param int $time
     * @return int
     */
    public static function redisRandomExpire($time = 0) {
        return $time + rand(0, 600); //10分钟内的随机值
    }
}
