/*******************************************************************************************
*
*   NetWorld basic viewer
*   Copyright (c) 2020-2020 Guillaume Lozenguez
*
********************************************************************************************/

#include "raylib.h"

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "networld.h"
#include "player.h"
#include "controlpanel.h"
#include "random-map.h"
#include "graphical-aspect.h"
#include "window-manager.h"
#include "main-menu.h"
#include "options-menu.h"

// Program attributes
//-------------------
const int screenWidth = 1700;
const int screenHeight = 800;
const int targetFPS = 60;

void game_update(NetWorld * world, Player * players, Font font, Panel * panel);

// Game attributes
//-----------------
bool game_end;

int main(int nbArg, char ** arg)
{
    int nodeCount = 10;
    int playerCount = 3;
    NetWorld * world = malloc(sizeof(NetWorld));
    Player * players = malloc(sizeof(Player));

    // Game Initialization
    //--------------------
    Panel * panel= Panel_new();
    Panel_initialize(panel, world, screenWidth, screenHeight);

    // Raylib Initialization
    //----------------------
    InitWindow(screenWidth, screenHeight, "NetWorld basic viewer");
    SetTargetFPS(targetFPS);
    
    Font gameFont = LoadFont("GAMERIA.ttf");
    
    // Main game loop

    //UI elements
    Main_Menu * menu = Main_Menu_init(screenWidth, screenHeight);
    Options_Menu * optionsMenu = Options_Menu_init(&playerCount, &nodeCount, screenWidth, screenHeight);
    Window_Manager * manager = Window_Manager_new(panel, menu, optionsMenu);

    while (!game_end && !WindowShouldClose())    // Detect window close button or ESC key
    {
        DrawFPS(10, 10);
        Window_Manager_display(manager);

        switch (manager->display)
        {
        case main_menu:
            if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON)){
                Vector2 mousePos = GetMousePosition();
                manager->display = Main_Menu_detect_click(menu, &mousePos);
                if(manager->display == game_ui){
                    //Initialising a new game with inputted parameters 
                    *world = *NetWorld_new(nodeCount, playerCount);
                    Random_map(world);
                    Color colors[] = {BLACK, RED, BLUE, GREEN, PURPLE, PINK, YELLOW};
                    players = Player_newArray(playerCount, colors);
                    //Distribute nodes to players evenly
                    for(int index = 0; index < world->size; index++){
                        Player_add_Node(&(players[index % playerCount]), &(world->nodes[index]));
                    }
                    world->currentPlayer = playerCount - 1;
                    game_end = false;
                }
            }
            break;
        case game_ui:
            Panel_control(panel);
            //Draw the hitboxes for each node
            for(int index = 0; index < world->size; index++){
                Vector2 screenPosition= Panel_pixelFromPosition(panel, &(world->nodes[index]).position);
                world->nodes[index].collisionHitbox.x = screenPosition.x - 24;
                world->nodes[index].collisionHitbox.y = screenPosition.y - 24;
            }
            game_update(world, players, gameFont, panel);
            break;
        case options:
            //Activate/Deactivate inputs on click and detect click on the save btn
            if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON)){
                Vector2 mousePos = GetMousePosition();
                if(Options_Menu_check_save_click(optionsMenu, &mousePos)){
                    manager->display = main_menu;
                    for(int index = 0; index < optionsMenu->inputCount; index++){
                        Int_Input_save_value(optionsMenu->inputs[index]);
                    }
                }
                Options_Menu_check_input_click(optionsMenu, &mousePos);
            }
            //Check key inputs for active input fields (only accepts numerical characters)
            for(int index = 0; index < optionsMenu->inputCount; index++){
                if(optionsMenu->inputs[index]->inputActive){
                    int key = GetKeyPressed();
                    while (key > 0){
                        if ((key >= 48) && (key <= 57) && (optionsMenu->inputCount < 3)){
                            Int_Input_add_char(optionsMenu->inputs[index], &key);
                        }
                        key = GetCharPressed();
                    }
                    if (IsKeyPressed(KEY_BACKSPACE)){
                        Int_Input_remove_char(optionsMenu->inputs[index]);
                    }
                }
            }
            break;
        default:
            break;
        }
    }

    // proper closing
    //---------------
    
    NetWorld_delete(world);
    Player_delete(players);
    Main_Menu_delete(menu);
    Options_Menu_delete(optionsMenu);
    Window_Manager_delete(manager);
    UnloadFont(gameFont); 
    CloseWindow();   // Close window and OpenGL context
 
    return 0;
}

void game_update(NetWorld * world, Player * players, Font font, Panel * panel)
{
    //Game frame init
    Vector2 mousePosition = GetMousePosition();
    Player * currentPlayer = &(players[world->currentPlayer]);
    Graphic_ShowPlayerInfo(currentPlayer, screenWidth, screenHeight, font);
    Graphic_WhoseTurnIsIt(currentPlayer, screenWidth, screenHeight, font);
    int playerCount = world->playerCount;

    switch(currentPlayer->turnPhase){            
        case recruitment:
            Graphic_RecrutementPhase(currentPlayer, screenWidth, screenHeight, font);   
            Graphic_MouseHoverNodeRecrutement(currentPlayer, mousePosition, panel);
            if(currentPlayer->soldiers > 0){
                if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)){
                    Player_add_soldier(currentPlayer, mousePosition);
                }
            }else{
                //Finish the recruitment phase
                Rectangle nextPhaseButton = Graphic_ConfirmButton(font);
                if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)){
                    if(CheckCollisionPointRec(mousePosition, nextPhaseButton)){
                        Player_confirm_recrutement(currentPlayer);
                        currentPlayer->turnPhase = attack;
                    }
                }
            }
            if(IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)){
                Player_remove_soldier(currentPlayer, mousePosition);
            }
            break;
        case attack:
            Graphic_AttackPhase(currentPlayer, screenWidth, screenHeight, font);
            Graphic_MouseHoverNodeChooseAttacker(currentPlayer, mousePosition, panel);
            if(currentPlayer->hasSelectedNode){
                Graphic_MouseHoverNodeChooseTarget(currentPlayer->selectedNode, mousePosition, panel);
                if(IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)){
                    Player_unselect_Node(currentPlayer, mousePosition);
                }
                if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)){
                    Node * originNode = currentPlayer->selectedNode;
                    //Detect if the player declared an attack
                    for(int nodeIndex = 0; nodeIndex < world->size; nodeIndex++){
                        Node* currentNode = &(world->nodes[nodeIndex]);
                        
                        if(CheckCollisionPointRec(mousePosition, currentNode->collisionHitbox)){
                            int nodePlayerID = currentNode->playerID;
                            if(nodePlayerID == currentPlayer->ID){
                                currentPlayer->selectedNode = currentNode;
                            }
                            else if(Node_are_connected(originNode, currentNode) && (originNode->soldiers > 1) && originNode->canAttack){
                                printf("Engagine attack on target Node\n");
                                int nbOfAttackers = Graphic_ChooseNumberOfAttackers(currentPlayer, &(players[nodePlayerID]), originNode, currentNode, font);
                                int * listOfDices = Player_attack_Node(currentPlayer, &(players[nodePlayerID]), originNode, currentNode, nbOfAttackers);
                                int defendersCount = currentNode->soldiers >= 3? 2:1;
                                diceRolling(currentPlayer, &(players[nodePlayerID]), originNode, currentNode, nbOfAttackers , listOfDices ,font);
                                free(listOfDices);
                            }else{
                            }
                        }
                    }
                }
            }else{
                if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)){
                    Player_select_Node(currentPlayer, mousePosition);
                }
            }
            //End turn btn
            Rectangle nextPhase = {200, 200, 270, 55};     
            DrawRectangleRec(nextPhase, GREEN);
            DrawTextEx(font, "Next Turn",(Vector2){220 , 210} , 40.0, 3.0, BLACK); 
            if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)){
                if(CheckCollisionPointRec(mousePosition, nextPhase)){
                    currentPlayer->turnPhase = init;
                }
            }
            break;
        case init :
            //Switch turns
            Player_end_turn(currentPlayer);
            world->currentPlayer = (world->currentPlayer + 1) % playerCount;
            Player_start_turn(&(players[world->currentPlayer]));
            break;
        default:;
    }
}
