#include "game.h"

#include <stdio.h>

#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/socket.h>
// #include <signal.h>
typedef int socket_t;

const char* nombrePalo(uint8_t palo) {
    switch(palo) {
        case PALO_ESPADA:
            return "Espada";

        case PALO_BASTO:
            return "Basto";

        case PALO_ORO:
            return "Oro";

        case PALO_COPA:
            return "Copa";
    }
    return "?";
}

const char* nombreCanto(uint8_t canto) {
    switch(canto) {
        case ESTADO_TRUCO:
            return "Truco";

        case ESTADO_RETRUCO:
            return "Quiero Retruco";

        case ESTADO_VALE_CUATRO:
            return "Quiero Vale Cuatro";
        case CANTO_QUIERO:
            return "Quiero";
        case CANTO_NO_QUIERO:
            return "No Quiero";
    }

    return "?";
}

const char* jugador_o_equipo(uint8_t jugadores) {
    switch(jugadores) {
        case 2:
            return "Jugador";
    }

    return "Equipo";
}

int main(){

    socket_t tcp_fd = -1;

    int opt = 1;
    tcp_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (tcp_fd == -1) {
        perror("socket");
        return -1;
    }

    setsockopt(tcp_fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt));

    struct sockaddr_in addr = {0};
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(27193);

    if (bind(tcp_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
        perror("bind");
        return -1;
    }

    if (listen(tcp_fd, 8) < 0) {
        perror("listen");
        return -1;
    }


    fd_set master, readfds;

    FD_ZERO(&master);
    FD_SET(tcp_fd, &master);

    printf("Listening on port 27016\n");

    socket_t fd;

    for (u_int i = 0; i < readfds.fd_count; i++){
        for ((fd) = readfds.fd_array[i]; (fd) != -1; (fd) = -1){
            char ip[16];
            inet_ntop(AF_INET, &client_addr.sin_addr, ip, sizeof(ip));
            printf("Cliente intentando conectar desde %s\n", ip);
        }
        FD_SET(client_fd, &master);

        if (client_fd > tcp_fd) maxfd = client_fd;

        //logica de conexion
        if(fd == tcp_fd){

        }
        //lo otro
        else{

        }
    }
        

    uint8_t jugadores = 2;

    printf("\nInserte número de jugadores: ");
    scanf("%u", &jugadores);

    EstadoPartida partida;

    if(!iniciar_partida(&partida, jugadores, 14)){
        printf("Número inválido de jugadores.\n");
        return 1;
    }

    while(1){
        uint8_t jugador = partida.jugador_turno_canto == JUGADOR_INVALIDO ? partida.jugador_turno_actual : partida.jugador_turno_canto;
        uint8_t equipo_jugador = jugador % 2;
        uint8_t numero_jugador = jugador + 1;

        uint8_t truco_disponible = CANTO_INVALIDO;

        if(!IS_BIT_SET(partida.flags_ronda, ESTADO_TRUCO) && partida.canto_ofrecido != ESTADO_TRUCO){
            truco_disponible = ESTADO_TRUCO;
        }else{
            if(IS_BIT_SET(partida.flags_ronda, ESTADO_TIENE_RETRUCO) == equipo_jugador){
                if(partida.canto_ofrecido >= ESTADO_TRUCO && partida.canto_ofrecido < ESTADO_VALE_CUATRO){
                    truco_disponible = partida.canto_ofrecido+1;
                }else if(partida.canto_ofrecido != ESTADO_VALE_CUATRO){
                    if(!IS_BIT_SET(partida.flags_ronda, ESTADO_VALE_CUATRO)){
                        if(IS_BIT_SET(partida.flags_ronda, ESTADO_RETRUCO)){
                            truco_disponible = ESTADO_VALE_CUATRO;
                        } 
                        else{
                            truco_disponible = ESTADO_RETRUCO;
                        }
                    }
                }
            }
        }

        if(partida.jugador_turno_canto != JUGADOR_INVALIDO){
            printf("\nResponde jugador %d \n", numero_jugador);

            if(partida.canto_ofrecido >= ESTADO_TRUCO && partida.canto_ofrecido <= ESTADO_VALE_CUATRO){
                if(truco_disponible != CANTO_INVALIDO) printf("\n\n3: %s!", nombreCanto(truco_disponible));
                printf("\n4: Quiero");
                printf("\n5: No Quiero");
            }
        }else{

            printf("\nTurno de jugador %d \n", numero_jugador);

            for(uint8_t carta_i = 0; carta_i < 3; carta_i++){
                uint8_t carta = partida.jugadores_cartas[partida.jugador_turno_actual][carta_i];
                if(carta == CARTA_INVALIDA) continue;
                printf("%u: %u de %s\n",
                    carta_i,
                    cartas[carta].valor_carta,
                    nombrePalo(cartas[carta].palo)
                );
            }

            if(truco_disponible != CANTO_INVALIDO) printf("\n3: %s!", nombreCanto(truco_disponible));
        }
        

        printf("\nAcción: ");

        uint8_t accion = 0;

        scanf("%u", &accion);

        ResultadoJugada resultado_jugada;

        if(accion >= 0 && accion <= 2) resultado_jugada = jugar_baza(&partida, jugador, accion);
        else if(accion == 3 && truco_disponible != CANTO_INVALIDO) resultado_jugada = cantar(&partida, jugador, truco_disponible);
        else if(partida.canto_ofrecido != CANTO_INVALIDO){
            if(accion == 4) resultado_jugada = cantar(&partida, jugador, CANTO_QUIERO);
            else if(accion == 5) resultado_jugada = cantar(&partida, jugador, CANTO_NO_QUIERO);
        }
        else{
            printf("\nAcción inválida");
            continue;
        }

        if(!resultado_jugada.eventos){
            printf("\nJugada inválida");
            continue;
        } 

        if(IS_BIT_SET(resultado_jugada.eventos, EVENTO_CARTA_JUGADA)){
            uint8_t carta_jugada_i = resultado_jugada.carta;
            if(carta_jugada_i == CARTA_INVALIDA){
                printf("Carta inválida\n\n");
                continue;
            }
            printf("Jugador %u jugó: %u de %s\n\n", numero_jugador, cartas[carta_jugada_i].valor_carta, 
            nombrePalo(cartas[carta_jugada_i].palo));
        }else if(IS_BIT_SET(resultado_jugada.eventos, EVENTO_CANTO)){
            printf("Jugador %u cantó: %s\n", numero_jugador, nombreCanto(resultado_jugada.canto));
        }


        if(IS_BIT_SET(resultado_jugada.eventos, EVENTO_RONDA_TERMINADA)){
            printf("%s %u gana la ronda.\n\n", jugador_o_equipo(jugadores), resultado_jugada.equipo_ganador+1);
            
            printf("%s 1: %u puntos === %s 2: %u puntos\n\n", jugador_o_equipo(jugadores), partida.equipos_puntos[0],
            jugador_o_equipo(jugadores), partida.equipos_puntos[1]);
        }

        if(IS_BIT_SET(resultado_jugada.eventos, EVENTO_VICTORIA)){
            printf("%s %u gana la partida.\n\n", jugador_o_equipo(jugadores), resultado_jugada.equipo_ganador+1);
        }
                
    }

    return 0;
}