#ifndef HM_DEVICE_H
#define HM_DEVICE_H

#include <string>
#include <mutex>
#include <memory>
#include "items.h"
#include "dhnetsdk.h"

namespace hm {
    class Device {
    private:
        std::mutex uMtx, cwMtx, cbMtx;
        bool inited, running;
        int port, reset;
        std::string mac, ip, local;
        std::vector<User> faceUserList;
        std::vector<Plate> carWhiteList, carBlackList;

        void init();

        bool login();

        void logout();

        bool subscribe();

        void unsubscribe();

        void varUserInsert(const User &user);

        void varUserDelete(const std::string &uid);

        bool varUserExists(const std::string &uid);

        bool addUserFace(const std::string &uid, const std::string &face, std::string &msg);

        bool removeUserOnly(const std::string &uid, std::string &msg);

        bool removeUserFace(const std::string &uid, std::string &msg);

        void varCarWoBInsert(const bool &isBlack, const Plate &plate);

        void varCarWoBDelete(const bool &isBlack, const int &cid);

        bool varCarWoBExists(const bool &isBlack, const int &cid);

        bool varCarWoBExists(const bool &isBlack, const std::string &plate);

        bool insertOneCarWoBList(const bool &isBlack, Plate &plateInfo, std::string &msg);

        bool removeOneCarWoBList(const bool &isBlack, const int &cid, std::string &msg);

        Plate *getPlateByCNo(const std::string &cno);

    public:
        LLONG loginId, subId;
        bool online, isFaceDevice;
        std::string seq;

        explicit Device(DEVICE_NET_INFO_EX2 *info);

        Device(const Device &) = delete;

        Device(Device &&) = delete;

        ~Device();

        void queryFaceUsers();

        void queryCarWoBList(const bool &isBlack);

        void Start();

        void onAccessCtlEvent(DEV_EVENT_ACCESS_CTL_INFO *info, BYTE *imgBuf, DWORD bufSize);

        void onTrafficJunctionEvent(DEV_EVENT_TRAFFICJUNCTION_INFO *info, BYTE *imgBuf, DWORD bufSize);

        std::string getJsonStr();

        bool getFaceUsers(std::vector<std::string> &users, std::string &msg);

        bool insertFaceUser(const User &user, std::string &msg);

        bool removeFaceUser(const std::string &uid, std::string &msg);

        bool getCarWoBList(const bool &isBlack, std::vector<std::string> &list, std::string &msg);

        bool insertCarWoBList(const bool &isBlack, std::vector<Plate> &list, std::string &msg);

        bool removeCarWoBList(const bool &isBlack, const std::vector<int> &cids, std::string &msg);
    };

    // global vars
    extern std::mutex gDeviceMtx;
    extern std::vector<std::unique_ptr<Device>> gDevicesVec;
}


#endif //HM_DEVICE_H
