#ifndef CLIENTCORE_H
#define CLIENTCORE_H

#include <InfoClient.hpp>
#include <InfoCommunicate.hpp>
#include <InfoDirFile.hpp>
#include <array>
#include <cstdint>
#include <memory>
#include <vector>
#include <thread>
#include <functional>
#include <wx/socket.h>

#include <Communicate.h>
#include <Util.h>

class ClientCore : public wxEvtHandler
{
public:
    ClientCore();
    ~ClientCore();

public:
    bool Connect(const wxString& host, uint16_t port);
    void Disconnect();

public:
    wxString GetErr() const;
    bool IsOk();
    void SetLogCallback(const std::function<void(const wxString&)>& callback);
    bool ReqOnline();
    void ReqOnlineCallback(const std::function<void(const InfoClientVec&)>& callback);
    bool AskDirectory(const wxString& id, const wxString& path, DirFileInfoVec& dirInfoVec);

private:
    void UseFrame(FrameBuffer* buf);

private:
    void OnSocketEvent(wxSocketEvent& event);

private:
    void HeartBeat();
    void Recv();
    template <typename T> bool Send(const T& info, FrameBufferType type)
    {
        std::stringstream ss;
        cereal::BinaryOutputArchive archive(ss);
        archive(info);

        auto buf = std::make_shared<FrameBuffer>();
        buf->dataConst = ss.view().data();
        buf->len = ss.str().size();
        buf->dataType = type;

        return Send(buf.get());
    }
    bool Send(FrameBuffer* buf);

private:
    wxString id_;
    bool thRun_;
    MutBuffer buffer_;
    wxString err_;
    std::thread recvThread_;
    std::array<char, GBUFFER_SIZE> buf_;
    wxSocketClient* socket_;

private:
    std::function<void(const InfoClientVec&)> onlineCallback_;
    std::function<void(const wxString&)> logCall_;
};

#endif   // CLIENTCORE_H