#include <cstdio>
#include "common.hpp"
#include <cstring>
#include <iostream>

int NetworkingStart() 
{
    if (enet_initialize () < 0)
    {
        fprintf (stderr, "An error occurred while initializing ENet.\n");
        return EXIT_FAILURE;
    }
    return 0;
}

ENetHost* StartServer() {
    ENetAddress address;
    ENetHost * server;
    
    /* Bind the server to the default localhost.     */
    /* A specific host address can be specified by   */
    /* enet_address_set_host (& address, "x.x.x.x"); */
    
    address.host = ENET_HOST_ANY;
    /* Bind the server to port 1234. */
    address.port = PORT;
    
    server = enet_host_create(&address, 32, 1, 0, 0);
    if (server == NULL)
    {
        fprintf (stderr, 
                "An error occurred while trying to create an ENet server host.\n");
        exit (EXIT_FAILURE);
    }
    return server;
}

ENetHost* StartClient() {
    ENetHost * client;
 
    client = enet_host_create (NULL /* create a client host */,
                1 /* 1 channel*/,
                1 /* only allow 1 outgoing connection */,
                0 /* assume any amount of incoming bandwidth */,
                0);
    
    if (client == NULL)
    {
        fprintf (stderr, 
                "An error occurred while trying to create an ENet client host.\n");
        exit (EXIT_FAILURE);
    }

    return client;
}

void SendPacket(ENetPeer* peer, void* data, int len)
{
	ENetPacket* packet = enet_packet_create(data, len, ENET_PACKET_FLAG_UNSEQUENCED);
    std::cout << (packet == NULL) << std::endl;
	int c = enet_peer_send(peer, 0, packet);
    if(c!=0) {
        printf("Failed sending packet! ");
        printf("%d\n", c);
        enet_packet_destroy(packet);
    }
}

void SendPacketR(ENetPeer* peer, void* data, int len)
{
	ENetPacket* packet = enet_packet_create(data, len, ENET_PACKET_FLAG_RELIABLE);

	int c = enet_peer_send(peer, 0, packet);
    if(c!=0) {
        printf("Failed sending packet! ");
        printf("%d\n", c);
        enet_packet_destroy(packet);
    }
}

void BroadcastPacketR(ENetHost* server, void* data, int len)
{
	ENetPacket* packet = enet_packet_create(data, len, ENET_PACKET_FLAG_RELIABLE);

	enet_host_broadcast(server, 0, packet);
}

void SerializeFloat2Data(float v, void *target, int offset) {
    uint8_t *buf = (uint8_t*)target + offset;
    if (!isfinite(v)) { // handle NaN/Inf as zero (choose policy)
        buf[0] = 0;
        buf[1] = 0;
        return;
    }
    if (v < 0.0f) v = 0.0f;
    if (v > 255.0f) v = 255.0f; // clamp to representable range

    int intpart = (int)floorf(v);
    float frac = v - (float)intpart;
    int frac_byte = (int)floorf(frac * 255.0f + 0.5f); // round to nearest
    if (frac_byte < 0) frac_byte = 0;
    if (frac_byte > 255) frac_byte = 255;
    buf[0] = (uint8_t)intpart;
    buf[1] = (uint8_t)frac_byte;
}

float DeserializeFloat(int b0, int b1) {
    return (float)(uint8_t)b0 + (float)((uint8_t)b1) / 255.0f;
}