<?php

namespace Api\PhpUtils\Redis;

use Api\PhpUtils\Http\Request;
use Redis;

class Codis
{
    const EXPIRE_AFTER_ONE_SECOND = 1;
    const EXPIRE_AFTER_FIVE_SECONDS = 5;
    const EXPIRE_AFTER_TEN_SECONDS = 10;
    const EXPIRE_AFTER_ONE_MINUTE = 60;
    const EXPIRE_AFTER_FIVE_MINUTES = 300;
    const EXPIRE_AFTER_TEN_MINUTES = 600;
    const EXPIRE_AFTER_HALF_HOUR = 1800;
    const EXPIRE_AFTER_ONE_HOUR = 3600;
    const EXPIRE_AFTER_SIX_HOURS = 21600;
    const EXPIRE_AFTER_TWELVE_HOURS = 43200;
    const EXPIRE_AFTER_ONE_DAY = 86400;
    const EXPIRE_AFTER_THREE_DAYS = 259200;
    const EXPIRE_AFTER_ONE_WEEK = 604800;
    const EXPIRE_AFTER_FIFTEEN_DAYS = 1296000;
    const EXPIRE_AFTER_ONE_MONTH = 2592000;

    private $server_name;
    private $server_list;
    private $connect_server;
    private $redis;

    public function __construct($server_name = 'main')
    {
        $this->server_name = $server_name;
        $this->connect();
    }

    public function connectServer()
    {
        return $this->connect_server;
    }

    public function serverList()
    {
        return $this->server_list;
    }

    public function getInstance(): Redis
    {
        return $this->redis;
    }

    /**
     * 获取 redis 操作实例.
     */
    private function connect(): bool
    {
        $ok = $this->getTopomServer();
        if (empty($ok)) {
            return false;
        }
        // 随机选取一个地址，若连接失败，重新选择地址，最多三次
        $flag = false;
        for ($i = 0; $i < 3; ++$i) {
            $index = array_rand($this->server_list);
            $connect_server = $this->server_list[$index];
            list($host, $port) = explode(':', $connect_server);
            try {
                $redis = new Base($host, $port);
            } catch (\Exception $e) {
                continue;
            }
            $flag = true;
            $this->redis = $redis->get();
            $this->connect_server = $connect_server;
            break;
        }
        return $flag;
    }

    /**
     * 从 topom 获取 server 列表.
     */
    private function getTopomServer(): bool
    {
        $conf = config('redis', 'codis');
        if (!isset($conf[$this->server_name]['topom']) || empty($conf[$this->server_name]['topom'])) {
            return false;
        }
        $url = $conf[$this->server_name]['topom'];
        $request = new Request();
        $res = $request->get($url);

        $res = $res["response"];
        if (empty($res) || !isset($res['stats']['proxy']['models']) || empty($res['stats']['proxy']['models'])) {
            return false;
        }

        $servers = $res['stats']['proxy']['models'];
        $server_list = [];
        foreach ($servers as $s) {
            $token = $s['token'];
            if (isset($res['stats']['proxy']['stats'][$token]['stats']['online']) && true === $res['stats']['proxy']['stats'][$token]['stats']['online']) {
                $server_list[] = $s['proxy_addr'];
            }
        }
        if (empty($server_list)) {
            return false;
        }
        $this->server_list = $server_list;
        return true;
    }
}
