<?php
require_once dirname(dirname(__FILE__)).'/util/HttpClient.php';
require_once dirname(dirname(__FILE__)).'/util/LoggerHelper.php';
require_once dirname(dirname(__FILE__)).'/util/Block.php';
require_once dirname(dirname(__FILE__)).'/util/FileCache.php';
require_once dirname(dirname(__FILE__)).'/util/ConfigHelper.php';
require_once dirname(dirname(__FILE__)).'/model/DomainInfo.php';
require_once dirname(dirname(__FILE__)).'/constant/ServiceName.php';

/**
 * 后羿系统服务类
 */
class DomainServerService{

    private $domain_server = array();

    private $expireTime = 300;//秒

    private $expireTimeHy = 86400;//秒，24小时

    private $hy_url = "http://hy.9game.cn:8080/v2/m";

    function get_cache_id($dn) {
        // maintain list of caches here
        $id=array(
            ServiceName::$DOMAINSERVER_REQ_DN => 6559,
            ServiceName::$DOMAINSERVER_GAMEDATA_DN => 6560,
            ServiceName::$DOMAINSERVER_REALNAME_DN => 6561,
            ServiceName::$ACCOUNT_ID => 6562
        );
        return $id[$dn];
    }

    public function getHyInfoByCache($accountId) {
        if (extension_loaded('shmop')) {
            $saveCache = false;
            $memory = new Block(self::get_cache_id($accountId));
            $hyInfoStr = $memory->read();
            if (empty($hyInfoStr)) {
                $saveCache = true;
            } else {
                $hyInfoArray = json_decode($hyInfoStr,true);
                if(time() - $hyInfoArray['ctime'] > $this->expireTimeHy){
                    $saveCache = true;
                } else {
                    LoggerHelper::info("缓存中的后羿系统的IP缓存有效，从缓存直接获取的信息为：".$hyInfoStr);
                    return $hyInfoArray;
                }
            }
            if ($saveCache) {
                $hyInfo = HttpClient::quickPost($this->hy_url, "account_id=".$accountId);
                if ($hyInfo) {
                    $hyInfoArray['urls'] = $this->getHyUrlList(json_decode($hyInfo,true));
                    if (! empty($hyInfoArray['urls'])) {
                        $hyInfoArray['ctime'] = time();
                        //新数据，存储到共享区
                        $memory->write(json_encode($hyInfoArray));
                        LoggerHelper::info("缓存后羿系统的IP成功，数据：".json_encode($hyInfoArray));
                        return $hyInfoArray;
                    }
                }
            }
        } else if ($this->fileCacheOpen()) {
            $fileCache = new FileCache($this->getFileCachePath());
            $hyInfoStr = $fileCache->get(self::get_cache_id($accountId));
            if (empty($hyInfoStr)) {
                $hyInfo = HttpClient::quickPost($this->hy_url, "account_id=".$accountId);
                if ($hyInfo) {
                    $hyInfoArray['urls'] = $this->getHyUrlList(json_decode($hyInfo,true));
                    if (! empty($hyInfoArray['urls'])) {
                        $hyInfoArray['ctime'] = time();
                        $fileCache->set(self::get_cache_id($accountId), json_encode($hyInfoArray), $this->expireTimeHy);
                        return $hyInfoArray;
                    }
                }
            } else {
                $hyInfoArray = json_decode($hyInfoStr,true);
                LoggerHelper::info("缓存中的智能域名解析系统的IP缓存有效，从缓存直接获取的信息为：".$hyInfoStr);
                return $hyInfoArray;
            }
        }
        return false;
    }

    private function getHyInfoByServer($accountId){
        $hyInfoArray = $this->getHyInfoByCache($accountId);
        if (! $hyInfoArray) {
            $hyInfo = HttpClient::quickPost($this->hy_url, "account_id=".$accountId);

            if ($hyInfo) {
                $hyInfoArray['urls'] = $this->getHyUrlList(json_decode($hyInfo,true));
                if (! empty($hyInfoArray['urls'])) {
                    $hyInfoArray['ctime'] = time();
                }
            }
        }
        return $hyInfoArray;
    }


    public function getDomainByServer($accountId, $dn, $domainServerReqBody, $refCache = false){
        $domainInfo = array();
        if (extension_loaded('shmop')) {
            $memory = new Block(self::get_cache_id($dn));
            $domainStr = $memory->read();
            if (empty($domainStr)) {
                $saveCache = true;
            } else {
                $domainInfo = json_decode($domainStr,true);
                if (time() - $domainInfo['ctime'] > $this->expireTime) {
                    $saveCache = true;
                } else {
                    LoggerHelper::info("缓存中的智能域名解析系统的IP缓存有效，从缓存直接获取的信息为：".$domainStr);
                    return $domainInfo;
                }
            }
            if ($saveCache || $refCache) {
                $domainInfo = self::getDomainInfoByMutiThread($accountId, $domainServerReqBody);
                if (!empty($domainInfo)) {
                    $memory->write(json_encode($domainInfo));
                    LoggerHelper::info("缓存中的智能域名解析系统的IP缓存已过期，再次请求智能域名解析系统。");
                    return $domainInfo;
                }
            }
        } else if ($this->fileCacheOpen()) {
            $fileCache = new FileCache($this->getFileCachePath());
            $domainStr = $fileCache->get(self::get_cache_id($dn));
            if (empty($domainStr) || $refCache) {
                $domainInfo =  self::getDomainInfoByMutiThread($accountId, $domainServerReqBody);
                if (!empty($domainInfo)) {
                    $fileCache->set(self::get_cache_id($dn), json_encode($domainInfo), $this->expireTime);
                    LoggerHelper::info("从后羿服务器获取域名IP成功，获取的信息为：".json_encode($domainInfo));
                    return $domainInfo;
                }
            } else {
                $domainInfo = json_decode($domainStr,true);
                LoggerHelper::info("缓存中的智能域名解析系统的IP缓存有效，从缓存直接获取的信息为：".$domainStr);
                return $domainInfo;
            }
        } else {
            LoggerHelper::info("未开启内存读取shmop模块且缓存目录不可以写,直接请求智能域名解析系统。");
            $domainInfo = self::getDomainInfoByMutiThread($accountId, $domainServerReqBody);
            return $domainInfo;
        }
    }

    public function getDomainByCache($dn){
        $domainInfo = array();
        if (extension_loaded('shmop')) {
            $memory = new Block(self::get_cache_id($dn));
            $domainStr = $memory->read();
            if (empty($domainStr)) {
                LoggerHelper::info("缓存中不存在智能域名解析系统的IP缓存，直接请求域名.");
                return false;
            } else {
                $domainInfo = json_decode($domainStr,true);
                if (time() - $domainInfo['ctime'] > $this->expireTime) {
                    //已过期,删除
                    $memory->delete();
                    LoggerHelper::info("缓存中的智能域名解析系统的IP缓存已过期，直接请求域名。");
                    return false;
                } else {
                    LoggerHelper::info("缓存中的智能域名解析系统的IP缓存有效，从缓存直接获取的信息为：".$domainStr);
                    return $domainInfo;
                }
            }
        } else if ($this->fileCacheOpen()) {
            $fileCache = new FileCache($this->getFileCachePath());
            $domainStr = $fileCache->get(self::get_cache_id($dn));
            if (empty($domainStr)) {
                LoggerHelper::info("缓存中不存在智能域名解析系统的IP缓存，直接请求域名.");
                return false;
            } else {
                $domainInfo = json_decode($domainStr,true);
                LoggerHelper::info("缓存中的智能域名解析系统的IP缓存有效，从缓存直接获取的信息为：".$domainStr);
                return $domainInfo;
            }
        } else {
            LoggerHelper::info("未开启内存读取shmop模块且缓存目录不可以写，无缓存设置。");
            return false;
        }
    }

    private function getDomainInfoByMutiThread($accountId, $domainServerReqBody){
        $hyUrls = $this->getHyInfoByServer($accountId);
        if (!$hyUrls || !isset($hyUrls['urls'])) {
            return false;
        }
        $resp_data = $this->curlMuti($hyUrls['urls'], $domainServerReqBody);

        $mutiServer = json_decode($resp_data,true);
        if (empty($mutiServer) || !isset($mutiServer['res'])) {
            LoggerHelper::info("获取到智能域名解析服务端接口返回的IP地址为空。");
            return false;
        }

        $domainInfo = array();
        $domainInfo['domain'] = isset($mutiServer['res'][0]['dn']) ? $mutiServer['res'][0]['dn'] : "";
        $domainInfo['ipAddress'] = isset($mutiServer['res'][0]['ips']) ? $mutiServer['res'][0]['ips'] : "";
        $domainInfo['ctime'] = time();

        return $domainInfo;
    }




    private function curlMuti($urls, $domainServerReqBody){
        $mh = curl_multi_init();
        $conn = array();
        foreach ($urls as $i => $url) {
            $conn[$i] = curl_init($url);
            curl_setopt($conn[$i], CURLOPT_USERAGENT, "UCSDK");
            curl_setopt($conn[$i], CURLOPT_POST, true);
            curl_setopt($conn[$i], CURLOPT_HEADER, false);
            curl_setopt($conn[$i], CURLOPT_RETURNTRANSFER, true);
            curl_setopt($conn[$i], CURLOPT_POSTFIELDS, $domainServerReqBody);
            curl_setopt($conn[$i], CURLOPT_CONNECTTIMEOUT,3);
            curl_setopt($conn[$i], CURLOPT_TIMEOUT, 3);//设置超时时间
            curl_setopt($conn[$i], CURLOPT_RETURNTRANSFER,true);  // 设置不将爬取代码写到浏览器，而是转化为字符串
            curl_multi_add_handle ($mh,$conn[$i]);
        }
        do {
            curl_multi_exec($mh,$active);
        } while ($active);

        $resp_data = "";
        foreach ($urls as $i => $url) {
            $resp_data = curl_multi_getcontent($conn[$i]); // 获得返回值
            if($resp_data != null){
                break; //终止循环
            }
        }

        foreach ($urls as $i => $url) {
            curl_multi_remove_handle($mh,$conn[$i]);
            curl_close($conn[$i]);
        }
        curl_multi_close($mh);
        return $resp_data;
    }

    /**
     * 获取毫秒级的时间参数
     *
     */
     private function getMillisecond() {
        $time = explode ( " ", microtime () );
        $time = $time [1] . ($time [0] * 1000);
        $time2 = explode ( ".", $time );
        $time = $time2 [0];
        return $time;
    }

    private function getHyUrlList($hyInfo) {
        if (! is_array($hyInfo)) {
            return false;
        }
        if (!isset($hyInfo['res']) || !isset($hyInfo['res']['network'])) {
            return false;
        }
        $network = $hyInfo['res']['network'];
        if (!is_array($network)) {
            return false;
        }
        $hyUrls = array();
        foreach ($network as $val) {
            if (isset($val['item']) && is_array($val['item'])) {
                foreach ($val['item'] as $value) {
                    $hyUrls[] = $value['protocol']."://".$value['ip'].":".$value['port'].ServiceName::$SERVER_PATH;
                }
            }
        }
        return $hyUrls;
    }

    public function cacheOpen() {
        if (extension_loaded('shmop') || $this->fileCacheOpen()) {
            return true;
        }
        return false;
    }

    private function fileCacheOpen() {
        if (is_writable($this->getFileCachePath())) {
            return true;
        }
        return false;
    }

    private function getFileCachePath() {
        return ConfigHelper::getStrVal("sdkserver.file.cache.path");
    }
}