//
// Created by gamer on 14.12.2025.
//
#include "gamecube.h"
#include <algorithm>
#include <ctime>
#include <iostream>

// -----------------------------------------------------------
// GameState – Zustandsmaschine
// -----------------------------------------------------------
enum class GameState
{
    Idle,          // kein Würfel offen
    OneFlipped,    // ein Würfel offen
    LockInput,     // Animation läuft
    CheckingMatch  // Vergleich
};

// -----------------------------------------------------------
// Initialisierung
// -----------------------------------------------------------
void innitGame(int pairCount,
               std::vector<gamecube> &cubes,
               std::vector<Vec3> &positions)
{
    cubes.clear();
    positions.clear();

    int total = pairCount * 2;
    int cols = ceil(sqrt(total));
    int rows = (total + cols - 1) / cols;
    float spacing = 2.2f;

    for (int r = 0; r < rows; r++)
        for (int c = 0; c < cols; c++)
            if ((int)positions.size() < total)
                positions.push_back({
                    (c - cols / 2.0f) * spacing,
                    0,
                    (r - rows / 2.0f) * spacing
                });

    std::vector<Color> colorPool;
    for (int i = 0; i < pairCount; i++)
    {
        Color col = {
            (unsigned char)(rand() % 256),
            (unsigned char)(rand() % 256),
            (unsigned char)(rand() % 256),
            255
        };
        colorPool.push_back(col);
        colorPool.push_back(col);
    }

    for (int i = total - 1; i > 0; --i)
        std::swap(colorPool[i], colorPool[rand() % (i + 1)]);

    for (int i = 0; i < total; i++)
        cubes.emplace_back(positions[i], colorPool[i]);
}

// -----------------------------------------------------------
// MAIN
// -----------------------------------------------------------
int main()
{
    srand(time(NULL));
    InitWindow(800, 600, "3D Memory Game – Stable Version");
    SetTargetFPS(60);

    Camera3D camera{};
    camera.position = {6, 6, 6};
    camera.target = {0, 0, 0};
    camera.up = {0, 1, 0};
    camera.fovy = 45;
    camera.projection = CAMERA_PERSPECTIVE;

    int pairCount = 2;
    std::vector<Vec3> positions;
    std::vector<gamecube> cubes;
    innitGame(pairCount, cubes, positions);

    gamecube *first = nullptr;
    gamecube *second = nullptr;

    float flipSpeed = 5.0f;
    bool gameWon = false;
    int counter = 0;

    GameState state = GameState::Idle;

    // -----------------------------------------------------------
    // GAME LOOP
    // -----------------------------------------------------------
    while (!WindowShouldClose())
    {
        // -----------------------------
        // INPUT (nur wenn erlaubt)
        // -----------------------------
        if (!gameWon &&
            (state == GameState::Idle || state == GameState::OneFlipped) &&
            IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
        {
            Vector2 mouse = GetMousePosition();

            for (auto &c : cubes)
            {
                if (!c.IsFlipped() && !c.IsMatched())
                {
                    Vector2 screenPos = GetWorldToScreen(
                        {c.GetPosition().x, c.GetPosition().y, c.GetPosition().z},
                        camera);

                    if (fabs(mouse.x - screenPos.x) < 40 &&
                        fabs(mouse.y - screenPos.y) < 40)
                    {
                        c.FlipForward();
                        counter++;

                        if (state == GameState::Idle)
                            state = GameState::OneFlipped;
                        else
                            state = GameState::LockInput;

                        break; // 🔒 nur EIN Würfel pro Klick
                    }
                }
            }
        }

        // -----------------------------
        // UPDATE – Animation
        // -----------------------------
        for (auto &c : cubes)
        {
            c.Update(flipSpeed);

            if (c.IsFlipped() && !c.IsMatched())
            {
                if (!first)
                    first = &c;
                else if (!second && &c != first)
                    second = &c;
            }
        }

        // -----------------------------
        // Animation beendet → Vergleich
        // -----------------------------
        if (state == GameState::LockInput && first && second)
            state = GameState::CheckingMatch;

        // -----------------------------
        // MATCHING
        // -----------------------------
        if (state == GameState::CheckingMatch)
        {
            Color a = first->GetColor();
            Color b = second->GetColor();

            if (a.r == b.r && a.g == b.g && a.b == b.b)
            {
                first->SetMatched(true);
                second->SetMatched(true);
            }
            else
            {
                first->FlipBackward();
                second->FlipBackward();
            }

            first = second = nullptr;
            state = GameState::Idle;
        }

        // -----------------------------
        // WIN CHECK
        // -----------------------------
        if (!gameWon)
            gameWon = std::all_of(
                cubes.begin(),
                cubes.end(),
                [](const gamecube &c)
                { return c.IsMatched(); });

        // -----------------------------
        // DRAW
        // -----------------------------
        BeginDrawing();
        ClearBackground(RAYWHITE);
        BeginMode3D(camera);

        for (auto &c : cubes)
            c.Draw();

        EndMode3D();

        if (gameWon)
            DrawText("Congrats! You found all pairs!", 140, 260, 30, DARKBLUE);
        else
            DrawText("Flip 2 cubes - find matching pairs!", 10, 10, 20, DARKGRAY);

        DrawText(TextFormat("Moves: %i", counter / 2), 10, 40, 20, DARKGRAY);
        EndDrawing();
    }

    CloseWindow();
    return 0;
}
