<?php
namespace Gm\Core;
use Framework\Log\LogMark;
use Game\Config\GameConfig;
use Gm\Config\Config;
use Gm\Config\RedisConfig;
use Redis;
use RedisCluster;
use RedisClusterException;
use Gm\Model\Servers;
use Gm\Comm\CommFunc;

class RedisLib {
    use CommFunc;
    private $host;
    private $port;
    private $cluster;
    private Redis $db_single ;
    private RedisCluster $db_cluster;

    private static $instance;

    // 私有构造
    private function __construct(int $serverID) {
        if(!$this->initParam($serverID)) {
            $this->ReturnErr(400, '服务器配置错误！');
            exit;
        }
        $this->initConnect();
    }

    // 私有clone
    private function __clone(){}

    // 获取单例
    public static function GetInstance($serverID = Config::DEFAULT_GAME_SERVER_ID)
    {
        if(!isset(self::$instance[$serverID]) || is_null(self::$instance[$serverID]) || empty
            (self::$instance[$serverID])) {
            self::$instance[$serverID] = new self($serverID);
        }
        return self::$instance[$serverID];
    }

    private function initParam(int $serverID): bool {
        //
//        $url = Servers::GetServerByServerId($serverID)['game_url'];
//        $urlArr = explode('/', $url);
//        $path = "";
//        foreach($urlArr as $k => $v) {
//            if($v === 'Zone') {
//                $path = $urlArr[$k+1];
//            }
//        }
//        if(empty($path)) {
//            return false;
//        }
//        //查找GameConfig位置是否存在
//        $rootPath = dirname(dirname(__FILE__) . '/');
//        $zonePatch = $rootPath. "/../Zone/".$path."/";
//        $gameConfigPatch = $zonePatch."GameConfig.php";
//        //检查是否存在
//        if (!file_exists($gameConfigPatch)) {
//            echo "argv error!,not found Zone GameConfig!";
//            exit;
//        }

//        require_once $gameConfigPatch;

        $this->host     =  RedisConfig::DEFAULT_HOST_NAME;
        $this->port     =  RedisConfig::DEFAULT_PORT;
        $this->cluster  = RedisConfig::cluster_nodes ?? RedisConfig::DEFAULT_CLUSTER;  // 暂时不用

        LogMark::getInstance()->markInfo("host: ". RedisConfig::DEFAULT_HOST_NAME . "port: " . RedisConfig::DEFAULT_PORT);
        return true;
    }

    private function initConnect() {
        $cluster = RedisConfig::IS_CLUSTER;
        if($cluster) {
            try {
                $this->db_cluster = new RedisCluster(null, $this->cluster);
            } catch (RedisClusterException $e) {
                throw new \Exception('redis cluster connect failed!');
            }
        } else {
            $this->db_single = new Redis();
            if(!$this->db_single->pconnect($this->host, $this->port)) {
                throw new \Exception('redis single connect failed!');
            }
        }
    }

    public function hSet($key, $field, $value) {
        if(!RedisConfig::IS_CLUSTER) {
            return $this->db_single->hSet($key, $field, $value);
        }
        return $this->db_cluster->hSet($key, $field, $value);
    }

    public function hGet($key, $field) {
        if(!RedisConfig::IS_CLUSTER) {
            return $this->db_single->hGet($key, $field);
        }
        return $this->db_cluster->hGet($key, $field);
    }

    public function hDel($key, $field) {
        if(!RedisConfig::IS_CLUSTER) {
            return $this->db_single->hDel($key, $field);
        }
        return $this->db_cluster->hDel($key, $field);
    }

    public function del($key) {
        if(!RedisConfig::IS_CLUSTER) {
            return $this->db_single->del($key);
        }
        return $this->db_cluster->del($key);
    }

    public function rPush($key, $field) {
        if(!RedisConfig::IS_CLUSTER) {
            return $this->db_single->rPush($key, $field);
        }
        return $this->db_cluster->rPush($key, $field);
    }

    public function bLPop($key, $timeout): array
    {
        if(!RedisConfig::IS_CLUSTER) {
            return $this->db_single->blPop($key, $timeout);
        }
        return $this->db_cluster->blPop($key, $timeout);
    }

    public function zAdd($key, $score, $value) {
        if(!RedisConfig::IS_CLUSTER) {
            return $this->db_single->zAdd($key, $score, $value);
        }
        return $this->db_cluster->zAdd($key, $score, $value);
    }

    public function zRem($key, $member) {
        if(!RedisConfig::IS_CLUSTER) {
            return $this->db_single->zRem($key, $member);
        }
        return $this->db_cluster->zRem($key, $member);
    }

    public function zRangeByScore($key, $start, $end) {
        if(!RedisConfig::IS_CLUSTER) {
            return $this->db_single->zRangeByScore($key, $start, $end);
        }
        return $this->db_cluster->zRangeByScore($key, $start, $end);
    }
}
