#include "ClientCore.h"
#include <InfoEnhance.hpp>

ClientCore::ClientCore()
{
    socket_ = std::make_shared<wxSocketClient>();
}

bool ClientCore::Connect(const wxString& host, uint16_t port)
{
    wxIPV4address addr;
    addr.Hostname(host);
    addr.Service(port);

    socket_->SetEventHandler(*this, wxID_ANY);
    socket_->SetNotify(wxSOCKET_INPUT | wxSOCKET_LOST_FLAG);
    socket_->Notify(true);
    socket_->SetFlags(wxSOCKET_BLOCK);

    if (!socket_->Connect(addr)) {
        return false;
    }
    return true;
}

void ClientCore::Disconnect()
{
}

bool ClientCore::GetOnlineList(InfoClientVec& infoClientVec)
{
    InfoCommunicate infoCommunicate;
    if (!Send<InfoCommunicate>(infoCommunicate, FBT_SER_MSG_ASKCLIENTS)) {
        return false;
    }
    return false;
}

bool ClientCore::AskDirectory(const wxString& id, const wxString& path, DirFileInfoVec& dirInfoVec)
{
    return false;
}

void ClientCore::OnSocketEvent(wxSocketEvent& event)
{
    auto* sock = event.GetSocket();
    switch (event.GetSocketEvent()) {
    case wxSOCKET_CONNECTION: {
        wxLogMessage(_("Client connected."));
        break;
    }
    case wxSOCKET_INPUT: {
        sock->Read(buf_.data(), GBUFFER_SIZE);
        auto size = sock->LastCount();
        if (size > 0) {
            buffer_.Push(buf_.data(), size);
            while (thRun_) {
                auto* frame = Communicate::ParseBuffer(buffer_);
                if (!frame) {
                    break;
                }
                UseFrame(frame);
                delete frame;
            }
        } else {
            wxLogError(_("Read error: %s"), sock->LastError());
        }
        break;
    }
    case wxSOCKET_LOST: {
        break;
    }
    default:
        break;
    }
}

void ClientCore::UseFrame(FrameBuffer* buf)
{
    std::stringstream ss;
    switch (buf->dataType) {
    case FBT_SER_MSG_ASKCLIENTS: {
        InfoClientVec vec;
        ZeroCopyInput input(buf->dataMut, buf->len);
        input.archive() >> vec;
        break;
    }
    default:
        break;
    }
}

void ClientCore::HeartBeat()
{
}

bool ClientCore::Send(FrameBuffer* buf)
{
    if (buf == nullptr) {
        return false;
    }
    char* od = nullptr;
    int odLen = 0;
    if (!Communicate::PackBuffer(buf, &od, odLen)) {
        return false;
    }

    socket_->Write(od, odLen);
    if (socket_->Error()) {
        delete[] od;
        wxLogError(wxT("Send error: %s"), socket_->LastError());
        return false;
    }
    delete[] od;
    return true;
}