#include "network/Client.h"

Client::Client()
    : client(enet_host_create(nullptr, 1, 2, 0, 0)), connection(nullptr) {
    if(client == nullptr) {
        error.clear().append("cannot crate ENet client host");
    }
}

Client::~Client() {
    disconnect();
    enet_host_destroy(client);
}

bool Client::hasError() const {
    return error.getLength() > 0;
}

const Client::Error& Client::getError() const {
    return error;
}

bool Client::connect(const char* server, Port port, int timeout) {
    ENetAddress address;
    ENetEvent event;
    enet_address_set_host(&address, server);
    address.port = port;

    connection = enet_host_connect(client, &address, 2, 0);
    if(connection == nullptr) {
        error.clear().append("server is not available");
        return true;
    }

    if(enet_host_service(client, &event, timeout) <= 0 ||
       event.type != ENET_EVENT_TYPE_CONNECT) {
        error.clear().append("connection failed");
        disconnect();
        return true;
    }
    return false;
}

void Client::disconnect() {
    if(connection == nullptr) {
        return;
    }
    ENetEvent e;
    enet_peer_disconnect(connection, 0);
    while(enet_host_service(client, &e, 3000) > 0) {
        switch(e.type) {
            case ENET_EVENT_TYPE_RECEIVE: enet_packet_destroy(e.packet); break;
            case ENET_EVENT_TYPE_DISCONNECT: connection = nullptr; return;
            default: break;
        }
    }
    enet_peer_reset(connection);
    connection = nullptr;
}

void Client::send(OutPacket& p) {
    if(p.packet != nullptr) {
        enet_peer_send(connection, 0, p.packet);
        p.packet = nullptr;
    }
}