# -*- coding: utf-8 -*-
"""
-------------------------------------------------
   File Name：     RedisClient
   Description :  封装Redis相关操作
   Author :        JHao
   date：          2019/8/9
-------------------------------------------------
   Change Activity:
                   2019/8/9: 封装Redis相关操作
-------------------------------------------------
"""
__author__ = 'JHao'

from Config.setting import PY3

from redis.connection import BlockingConnectionPool
from redis import Redis


class RedisClient(object):
    """
    Redis client 和SSDB协议一致 数据结构一致, 但部分方法不通用

    Redis中代理存放的结构为hash：
        原始代理存放在name为raw_proxy的hash中, key为代理的ip:por, value为代理属性的字典;
        验证后的代理存放在name为useful_proxy的hash中, key为代理的ip:port, value为代理属性的字典;

    """

    def __init__(self, name, **kwargs):
        """
        init
        :param name: hash name
        :param host: host
        :param port: port
        :param password: password
        :return:
        """
        self.name = name
        self.__conn = Redis(connection_pool=BlockingConnectionPool(**kwargs))

    def get(self, proxy_str):
        """
        从hash中获取对应的proxy, 使用前需要调用changeTable()
        :param proxy_str: proxy str
        :return:
        """
        data = self.__conn.hget(name=self.name, key=proxy_str)
        if data:
            return data.decode('utf-8') if PY3 else data
        else:
            return None

    def put(self, proxy_obj):
        """
        将代理放入hash, 使用changeTable指定hash name
        :param proxy_obj: Proxy obj
        :return:
        """
        data = self.__conn.hset(self.name, proxy_obj.proxy, proxy_obj.info_json)
        return data

    def delete(self, proxy_str):
        """
        移除指定代理, 使用changeTable指定hash name
        :param proxy_str: proxy str
        :return:
        """
        self.__conn.hdel(self.name, proxy_str)

    def exists(self, proxy_str):
        """
        判断指定代理是否存在, 使用changeTable指定hash name
        :param proxy_str: proxy str
        :return:
        """
        return self.__conn.hexists(self.name, proxy_str)

    def update(self, proxy_obj):
        """
        更新 proxy 属性
        :param proxy_obj:
        :return:
        """
        self.__conn.hset(self.name, proxy_obj.proxy, proxy_obj.info_json)

    def pop(self):
        """
        弹出一个代理
        :return: dict {proxy: value}
        """
        # proxies = self.__conn.hkeys(self.name)
        # if proxies:
        #     proxy = random.choice(proxies)
        #     value = self.__conn.hget(self.name, proxy)
        #     self.delete(proxy)
        #     return {'proxy': proxy.decode('utf-8') if PY3 else proxy,
        #             'value': value.decode('utf-8') if PY3 and value else value}
        return None

    def getAll(self):
        """
        列表形式返回所有代理, 使用changeTable指定hash name
        :return:
        """
        item_dict = self.__conn.hgetall(self.name)
        if PY3:
            return [value.decode('utf8') for key, value in item_dict.items()]
        else:
            return item_dict.values()

    def clear(self):
        """
        清空所有代理, 使用changeTable指定hash name
        :return:
        """
        return self.__conn.delete(self.name)

    def getNumber(self):
        """
        返回代理数量
        :return:
        """
        return self.__conn.hlen(self.name)

    def changeTable(self, name):
        """
        切换操作对象
        :param name: raw_proxy/useful_proxy
        :return:
        """
        self.name = name
