#include <utility>

#include "network/Server.h"

Server::Client::Client(ENetPeer* peer, int id) : peer(peer), id(id) {
}

Server::Client::~Client() {
    if(peer != nullptr) {
        enet_peer_disconnect(peer, 0);
    }
}

Server::Client::Client(Client&& other) : Client(nullptr, -1) {
    std::swap(peer, other.peer);
    std::swap(id, other.id);
}

Server::Client& Server::Client::operator=(Client&& other) {
    std::swap(peer, other.peer);
    std::swap(id, other.id);
    return *this;
}

int Server::Client::getId() const {
    return id;
}

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

Server::Server(Port port, int maxClients) : server(nullptr), idCounter(1) {
    ENetAddress address;
    address.host = ENET_HOST_ANY;
    address.port = port;

    server = enet_host_create(&address, maxClients, 3, 0, 0);
    if(server == nullptr) {
        error.clear().append("cannot create ENet server host");
    }
}

Server::~Server() {
    for(auto& client : clients) {
        enet_peer_reset(client.value.peer);
    }
    enet_host_destroy(server);
}

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

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

void Server::send(OutPacket& p) {
    if(p.packet != nullptr) {
        enet_host_broadcast(server, p.channel, p.packet);
        p.packet = nullptr;
    }
}

void Server::disconnect(Client& client) {
    enet_peer_reset(client.peer);
    clients.remove(client.getId());
}