/*******************************************************************************************
*
*   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"

// 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= NetWorld_new(nodeCount, playerCount);
    Random_map(world);

    // Game Initialization
    //--------------------
    game_end= false;

    Panel * panel= Panel_new();
    Panel_initialize(panel, world, screenWidth, screenHeight);

    Color colors[] = {BLACK, RED, BLUE};
    Player * players = Player_newArray(playerCount, colors);
    for(int index = 0; index < world->size; index++){
        Player_add_Node(&(players[index % playerCount]), &(world->nodes[index]));
    }

    // Raylib Initialization
    //----------------------
    InitWindow(screenWidth, screenHeight, "NetWorld basic viewer");
    SetTargetFPS(targetFPS);
    
    Font font = LoadFont("GAMERIA.ttf");
    
    // Main game loop
    Main_Menu * menu = Main_Menu_init(screenWidth, screenHeight);
    Window_Manager * manager = Window_Manager_new(panel, menu);
    world->currentPlayer = playerCount - 1;
    
    while (!game_end && !WindowShouldClose())    // Detect window close button or ESC key
    {
        DrawFPS(10, 10);
        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;
        }
        Panel_control(panel);
        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);
            }
            break;
        case game_ui:
            BeginDrawing();
            game_update(world, players, font, panel);
            EndDrawing();
        default:
            break;
        }
    }

    // proper closing
    //---------------
    
    NetWorld_delete(world);
    Player_delete(players);
    UnloadFont(font); 
    CloseWindow();   // Close window and OpenGL context
 
    return 0;
}

void game_update(NetWorld * world, Player * players, Font font, Panel * panel)
{
    Vector2 mousePosition = { 0.0f, 0.0f };
    mousePosition = GetMousePosition();
    Player * currentPlayer = &(players[world->currentPlayer]);
    Graphic_ShowPlayerInfo(currentPlayer, screenWidth, screenHeight, font);
    Graphic_WhoseTurnIsIt(currentPlayer, screenWidth, screenHeight, font);
    int playerCount = world->playerCount;
    //Player * newPlayers = malloc(sizeof(Player)); 

    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{
                Rectangle nextPhaseButton = Graphic_ConfirmButton(font);
                if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)){
                    if(CheckCollisionPointRec(mousePosition, nextPhaseButton)){
                        Player_confirm_recrutement(currentPlayer);
                        printf("Recrutement confirmed\n");
                        currentPlayer->turnPhase = attack;
                        printf("Attack phase\n");
                    }
                }
            }
            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;
                    
                    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){
                                printf("Selected target Node\n");
                                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{
                                printf("Failed to attack target : Origin has already attacked, nodes aren't connected or origin node has too few soldiers\n");
                            }
                        }
                    }
                }
            }else{
                if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)){
                    Player_select_Node(currentPlayer, mousePosition);
                }
            }
            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)){
                    printf("Attack phase ended\n");
                    currentPlayer->turnPhase = init;
                }
            }
            break;
        case init :
            Player_end_turn(currentPlayer);
            printf("Turn ended\n");
            world->currentPlayer = (world->currentPlayer + 1) % playerCount;
            printf("Player changed\n");
            Player_start_turn(&(players[world->currentPlayer]));
            printf("Turn started\n");
            printf("Recrutement phase\n");
            break;
        default:;
    }
}
