//
//  ZWRedisTool.h
//
//  Created by 杨净 on 2018/7/18.
//  Copyright © 2018年 杨净. All rights reserved.
//
//  email: 1026397500@qq.com
//

#ifndef _ZWREDISTOOL_H_
#define _ZWREDISTOOL_H_

#include "MFSPublic.h"
#include <hiredis/hiredis.h>
#include <hiredis/async.h>

extern std::pair<std::string, int> redisParam;

namespace mfs
{
    class ZWRedisTool
    {
    public:
        enum TaskType
        {
            TaskType_Verify = 0,
            TaskType_Select,
            TaskType_Client,
        };

        struct ITaskClient
        {
            virtual void RedisCommandCallback(const std::string& key, redisReply* reply)=0;
        };

        struct TaskData
        {
            TaskData(const std::string& key, TaskType type, std::weak_ptr<ITaskClient> client): _type(type), _client(client), _key(key)
            {
                _id = NOW_ID++;
                _requestTime = std::chrono::system_clock::now();
            }
            TaskData(const std::string& key, TaskType type): _type(type), _key(key)
            {
                _id = NOW_ID++;
                _requestTime = std::chrono::system_clock::now();
            }

            std::chrono::system_clock::time_point _requestTime;
            std::string _key;
            TaskType _type;
            std::weak_ptr<ITaskClient> _client;
            inline uint32_t id(){return _id;}
        private:
            uint32_t _id;
            static uint32_t NOW_ID;
        };

    public:
        ZWRedisTool(){}

        static std::shared_ptr<ZWRedisTool> RedisTool();
        
        int connectRedis();
        void SetUVLoop(uv_loop_t *loop){_loop=loop;}

        void checkConnect();

        int getValueAsync(const std::string& key, time_t currentTime, std::weak_ptr<ITaskClient> client);


        int getInvalidValue()
        {
            return _invalid;
        }

    private:
        std::chrono::system_clock::time_point _initTime;
        int _invalid = 1;                               // 1:未初始化 2:初始化未切换数据库 0:完成可用
        uv_loop_t* _loop = nullptr;

        redisAsyncContext* _ac = nullptr;

        void cleanTask();

        std::map<uint32_t, std::shared_ptr<TaskData>> taskList;



        static void commandCallback(redisAsyncContext* ac, void* r, void* data);

        static void connectCallback(const redisAsyncContext* ac, int status);

        static void disconnectCallback(const redisAsyncContext* ac, int status)
        {
            LOG_ERROR << "disconnect" << LOG_ENDL;
            ZWRedisTool* redisTool = reinterpret_cast<ZWRedisTool*>(ac -> data);
            redisTool -> cleanTask();
            redisTool -> _invalid = 1;
        }

    };

}

#endif // _ZWREDISTOOL_H_
