<?php
/**
 * Created by PhpStorm.
 * User: dongdx
 * Date: 2017/6/21
 * Time: 10:25
 */

namespace Heanup\Library;

use Heanup\Config\Redis\Core;
use Heanup\Frame\Logger;

class Redis
{

    private $cfg;
    private $w_redis;
    private $r_redis;

    public static $instance;

    public function __construct()
    {
        $this->cfg = Core::getData();
    }

    public static function instance(): Redis
    {
        if (!isset(self::$instance)) {
            $instance = new self();
            self::$instance = $instance;
        } else {
            $instance = self::$instance;
        }
        return $instance;
    }

    public function get($key)
    {
        $redis = $this->connect(true);
        if (empty($key)) {
            return '';
        } else {
            $res = $redis->get($key);
            $row = json_decode($res, true);
            if ($res == '[]') $res = array();
            return $row ?: $res;
        }
    }

    public function set($key, $value, $life_time_limit = 0)
    {
        $redis = $this->connect(false);
        if (is_array($value)) {
            $value = json_encode($value);
        }
        if ($life_time_limit) {
            return $redis->setex($key, $life_time_limit, $value);
        } else {
            return $redis->set($key, $value);
        }
    }

    public function del($key)
    {
        $redis = $this->connect(false);
        return $redis->del($key);
    }

    public function hExists($key, $hashkey)
    {
        $redis = $this->connect(true);
        return boolval($redis->hExists($key, $hashkey));
    }

    public function hSet($key, $hashkey, $value)
    {
        $redis = $this->connect(false);
        if (is_array($value)) {
            $value = json_encode($value);
        }
        return $redis->hSet($key, $hashkey, $value);
    }
    public function hDel($key, $hashkey)
    {
        $redis = $this->connect(false);
        return $redis->hDel($key, $hashkey);
    }

    public function hGet($key, $hashkey)
    {
        $redis = $this->connect(true);
        $res = $redis->hGet($key, $hashkey);
        $row = json_decode($res, true);
        if ($res == '[]') $res = array();
        return $row ?: $res;
    }

    public function hLen($key)
    {
        $redis = $this->connect(true);
        $res = $redis->hLen($key);
        return intval($res);
    }

    public function sAdd($key, $values)
    {
        $redis = $this->connect(false);
        if (is_array($values)) {
            $res = $redis->sAddArray($key,$values);
        } else if(is_scalar($values)) {
            $res = $redis->sAdd($key, $values);
        }
        return $res;
    }

    public function sRem($key,$value)
    {
        $redis = $this->connect(false);
        return $redis->sRem($key,$value);
    }

    public function sMembers($key)
    {
        $redis = $this->connect(true);
        return $redis->sMembers($key);
    }

    public function hMGet($key, $hashkey)
    {
        $redis = $this->connect(true);
        return $redis->hMGet($key, $hashkey);
    }

    public function hGetAll($key)
    {
        $redis = $this->connect(true);
        return $redis->hGetAll($key);
    }

    public function hVals($key)
    {
        $redis = $this->connect(true);
        return $redis->hVals($key);
    }

    public function delete($key)
    {
        $redis = $this->connect(false);
        return $redis->delete($key);
    }

    public function incr($key)
    {
        $redis = $this->connect(false);
        return $redis->incr($key);
    }

    public function multi()
    {
        $redis = $this->connect(false);
        $redis ->multi();
    }

    public function exec()
    {
        $redis = $this->connect(false);
        try {
            $result = $redis ->exec();
            return $result;
        } catch (\Exception $ex) {
            Logger::error($ex->getMessage()."-".$ex->getTraceAsString()."(".$ex->getFile().":".$ex->getFile().")");
//            return false;
        }

    }

    /**
     * @param bool $is_read
     * @return bool|\Redis
     */
    public function connect($is_read = false)
    {
        try {
            if ($is_read) {
                //获取redis读连接
                if ($this->r_redis) {
                    return $this->r_redis;
                }
                $this->r_redis = new \Redis();
                $config = $this->cfg['slave_list'][0];
                if (isset($config['pconnect']) && $config['pconnect'] == 1) {
                    $this->r_redis->pconnect($config['host'], $config['port'], $config['timeout']);
                } else {
                    $this->r_redis->connect($config['host'], $config['port'], $config['timeout']);
                }
                if (isset($config['password']) && $config['password']) {
                    $this->r_redis->auth($config['password']);
                }

                //选择redis-db  -by edison
                if (isset($config['db']))
                    $this->r_redis->select(intval($config['db']));
                return $this->r_redis;
            } else {
                //获取redis写连接
                if ($this->w_redis) {
                    return $this->w_redis;
                }
                $this->w_redis = new \Redis();
                $config = $this->cfg['master'];
                if (isset($config['pconnect']) && $config['pconnect'] == 1) {
                    $this->w_redis->pconnect($config['host'], $config['port'], $config['timeout']);
                } else {
                    $this->w_redis->connect($config['host'], $config['port'], $config['timeout']);
                }
                if (isset($config['password']) && $config['password']) {
                    $this->w_redis->auth($config['password']);
                }
                //选择redis-db  -by edison
                if (isset($config['db']))
                    $this->w_redis->select(intval($config['db']));
                return $this->w_redis;
            }
        } catch (\Exception $ex) {
            $message = "Redis connection failed : [" . $config['host'] . ';' . $config['port'] . ']' . $ex->getMessage();
            Logger::error($message);
//            return false;
        }
    }
}
