//
// Created by WJG on 2020-5-7.
//

#ifndef NEWCOSS_DEVTREE_H
#define NEWCOSS_DEVTREE_H

#include <mutex>
#include <unordered_map>
#include <unordered_set>
#include <qlibc/StringUtils.hpp>
#include <qlibc/QData.hpp>
#include "json/json.h"
#include "DeviceInfo.h"
#include "../CossCore/FileWriteWorker.h"
#include "../CossCore/coss_comm.h"

class DevTree{
public:
    static DevTree& GetInstance()
    {
        if ( m_pInstance == nullptr )
            m_pInstance = new DevTree();
        return *m_pInstance;
    };

    ~DevTree();

    static std::string config_file_dir;
    static std::string config_file_dir_init;

    int initDevTree(const std::string &file_dir, const std::string& init_dir);
    Json::Value getAllDev();
    string getDevInfo(const std::string &device_id, const std::string &key);
    void getDevInfoAsJsonValue(Json::Value &val, const string &device_id, const string &key);
    Json::Value getDevAllInfo(const std::string &device_id);
    void getDevAllInfo(Json::Value &ret, const string &device_id);
    int updateDeviceInfo(const std::string &device_id, const Json::Value &info);
    int updateDeviceInfo(const std::string &device_id, const std::string &key, const std::string &value);
    int cacheDeviceInfo(const std::string &device_id, const Json::Value &info);
    bool cachesaveDeviceInfo(const std::string &device_id, const Json::Value &info);
    int addUserLocation(const Json::Value &location);
    int deleteUserLocation(const Json::Value &location);
    // void printGroupInfo();

    std::vector<std::string> getDevbyGroup(const std::string &nick_name, const std::string &device_type,const std::string &device_location);
    Json::Value getDevbyLocation(const std::string &location);
    Json::Value getDevBaseInfo(const std::string &device_id);
    int rmLocationDev(const std::string &device_id, const std::string &location_name);
    std::string getDevbyAddress(const std::string &device_addr);
    std::string getDevbyUuid(const std::string &device_uuid);
    bool hasDevice(const std::string &device_id);
    int deleteDevice(const std::string &device_id);
    int addNewDevice(const std::string &device_id, const Json::Value &info);
    int deleteDeviceInfo(const std::string &device_id, const std::string &key);
    Json::Value getGroupDevice();
    int deleteGroupDevice(const std::string& device_id);
    int cacheOtherDevice(const std::string &device_id, const Json::Value &info);
    std::vector<std::string> getDevbyNickName(const std::string &nick_name);
    int updateNickNameMap(const std::string &device_id, const std::string &nick_name, const std::string &old_name);
    void saveDeviceInfo(const std::string& device_id);
//    int saveDefaultGroupAddrDev(const std::string& gpadr, const Json::Value& dev);
//    Json::Value getDefaultGroupAddrDev();
//    void delDefaultGroupAddrDev();
    int updatePanelName(const std::string& nick_name);
    int updatePanelUUID(const std::string& uuid);
    int updatePanelMac(const std::string& mac);
    std::string getPanelName();
    std::string getPanelUUID();
    std::string getPanelMac();
    bool hasDefaultGroupId(const std::string &gp_id);

    void setDefaultGroupId(const std::string &groupAddr);

    //获取所有原始设备的短地址列表，不包含组地址
    void getAtomDevShortAddrList(QStringList& list, const std::string& type = "", const std::string& devClass = "");

    DeviceInfo* getDevInfoByAddress(const std::string &device_address);

    void removeDuplicatedWired();
    void upgradeGroupIdFormmat();

private:
    static DevTree* m_pInstance;
    std::recursive_mutex treeMutex;
    FileWriteWorker *filewriteWorker;
    unordered_map<std::string, DeviceInfo> allDevice;
    //unordered_map<分组类型名，unordered_map<分组名,unordered_set<设备id>>
    unordered_map<std::string, unordered_map<std::string,unordered_set<std::string>>> groupInfo;
    unordered_map<std::string, std::string> devAddrIdMap;
    unordered_map<std::string, std::string> devUuidIdMap;
    unordered_set<std::string> groupDevices;
    unordered_map<std::string,unordered_set<std::string>> devNickNameMap;

    DevTree();
    int initGroupInfoKey();
    int updateLocationKey(int opt, const Json::Value &value);
    int updateDeviceLocation(const unordered_set<std::string> &device_set, const std::string &location);

    int updateGroupInfo(const std::string &device_id, const Json::Value &value);
    int CreatDeviceInfo(const std::string &file_dir);

    std::mutex devFileMutex;
    std::string defaultLightGroupId;
    qlibc::QData mCossConfig;

    unordered_set<std::string> defaultGroupAddress_set;

#ifdef DEVICE_FILE_TEST
Json::Value parseFromFile(const string &fn);
#endif

};

#endif //NEWCOSS_DEVTREE_H
