// ============================================================================
// MONOPOLY GAME IMPLEMENTATION (for custom console)
// ============================================================================
// Refactored from console version to use Game interface and rendering/input system

#include "monopoly_game.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "player.h"
#ifdef __cplusplus
}
#endif


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include "DiceModalGame.h"
#include "PropertyModalGame.h"
#include "BoardModalGame.h"
#include "ChanceModalGame.h"
#include "CommunityChestModalGame.h"
#include "TurnModalGame.h"
#include "PaymentModalGame.h"
#include "ModalButtonHelper.h"
#include "sprites.h"
#include "MonopolyBoardRenderer.h"


// --- Constructor ---
MonopolyGame::MonopolyGame(uint16_t width, uint16_t height, LowLevelRenderer* renderer, LowLevelGUI* gui, InputManager* input_manager)
    : Game(width, height, renderer, gui, input_manager) {
    players_count = 2;
    current_player_idx = 0;
    has_rolled = false;
    double_rolls = 0;
    just_sent_to_jail = false;
}

// --- Initialize game state ---
void MonopolyGame::init() {
    // Initialize regions for touch buttons
    ModalButtonHelper::set_monopoly_regions(input_manager, width, height);

    // Hardcoded 2 players for minimal version
    init_player(&players[0], 0, "Elias", "Top Hat");
    init_player(&players[1], 1, "Adolfo", "Racecar");
    players_count = 2;
    current_player_idx = 0;
    has_rolled = false;
    double_rolls = 0;
    just_sent_to_jail = false;
    selected_action = -1;
    srand(time(NULL));
    shuffle_chance_deck();
    shuffle_community_deck();
    //renderer->set_font(&font_tama_mini02_obj);
    if (active_modal) { delete active_modal; active_modal = nullptr; }
    active_modal = new TurnModalGame(width, height, renderer, gui, input_manager, &players[current_player_idx]);
    // TODO: Reset all board state, property ownership, etc.
}

void MonopolyGame::shuffle_chance_deck() {
    for (int i = 0; i < CHANCE_DECK_SIZE; i++) {
        chance_deck[i] = i;
    }
    for (int i = CHANCE_DECK_SIZE - 1; i > 0; i--) {
        int j = rand() % (i + 1);
        int temp = chance_deck[i];
        chance_deck[i] = chance_deck[j];
        chance_deck[j] = temp;
    }
    current_chance_idx = 0;
}

void MonopolyGame::shuffle_community_deck() {
    for (int i = 0; i < COMMUNITY_DECK_SIZE; i++) {
        community_deck[i] = i;
    }
    for (int i = COMMUNITY_DECK_SIZE - 1; i > 0; i--) {
        int j = rand() % (i + 1);
        int temp = community_deck[i];
        community_deck[i] = community_deck[j];
        community_deck[j] = temp;
    }
    current_community_idx = 0;
}

// --- Handle input events (minimal: roll, buy, end turn) ---
bool MonopolyGame::update(const InputEvent& event) {
    Player* p = &players[current_player_idx];
    bool needs_redraw = false;

    // Calculate available actions
    int menu_count = 0;
    if (!has_rolled) {
        menu_count++; // Roll Dice
        if (p->is_in_jail) menu_count++; // Pay $50
    } else {
        menu_count++; // End Turn
    }
    menu_count++; // View Board

    // If a modal is active, delegate input and check for dismissal
    if (active_modal) {
        bool modal_redraw = active_modal->update(event);
        if (modal_redraw) needs_redraw = true;
        
        // Check for specific modal types to handle their results using custom get_type()
        DiceModalGame* dice_modal = (active_modal->get_type() == Game::Type::MONOPOLY_DICE) ? static_cast<DiceModalGame*>(active_modal) : nullptr;
        PropertyModalGame* prop_modal = (active_modal->get_type() == Game::Type::MONOPOLY_PROPERTY) ? static_cast<PropertyModalGame*>(active_modal) : nullptr;
        BoardModalGame* board_modal = (active_modal->get_type() == Game::Type::MONOPOLY_BOARD) ? static_cast<BoardModalGame*>(active_modal) : nullptr;
        ChanceModalGame* chance_modal = (active_modal->get_type() == Game::Type::MONOPOLY_CHANCE) ? static_cast<ChanceModalGame*>(active_modal) : nullptr;
        CommunityChestModalGame* community_modal = (active_modal->get_type() == Game::Type::MONOPOLY_COMMUNITY_CHEST) ? static_cast<CommunityChestModalGame*>(active_modal) : nullptr;
        TurnModalGame* turn_modal = (active_modal->get_type() == Game::Type::MONOPOLY_TURN) ? static_cast<TurnModalGame*>(active_modal) : nullptr;
        PaymentModalGame* pay_modal = (active_modal->get_type() == Game::Type::MONOPOLY_PAYMENT) ? static_cast<PaymentModalGame*>(active_modal) : nullptr;

        if (pay_modal && pay_modal->is_dismissed()) {
            delete active_modal;
            active_modal = nullptr;
            selected_action = -1;
            needs_redraw = true;
            ModalButtonHelper::set_monopoly_regions(input_manager, width, height);
            return needs_redraw;
        }

        if (dice_modal && dice_modal->is_dismissed()) {
            delete active_modal;
            active_modal = nullptr;
            needs_redraw = true;
            ModalButtonHelper::set_monopoly_regions(input_manager, width, height);

            // Immediately check if we need to show a property modal
            if (modal_property_index >= 0) {
                bool is_owned = false;
                const char* owner_name = nullptr;
                int owner_id = -1;
                for (int i = 0; i < players_count; ++i) {
                    for (int j = 0; j < players[i].property_count; ++j) {
                        if (players[i].properties_owned[j] == modal_property_index) {
                            is_owned = true;
                            owner_name = players[i].name;
                            owner_id = i;
                            break;
                        }
                    }
                    if (is_owned) break;
                }
                bool can_afford = (p->balance >= MONOPOLY_BOARD[modal_property_index].cost);
                active_modal = new PropertyModalGame(width, height, renderer, gui, input_manager, &MONOPOLY_BOARD[modal_property_index], is_owned, owner_name, owner_id, can_afford, players, players_count, current_player_idx);
                modal_property_index = -1;
            } else if (last_drawn_chance_idx >= 0) {
                active_modal = new ChanceModalGame(width, height, renderer, gui, input_manager, &CHANCE_DECK[last_drawn_chance_idx], players, players_count, p->position);
                // We'll apply the effect when ChanceModal is dismissed
            } else if (last_drawn_community_idx >= 0) {
                active_modal = new CommunityChestModalGame(width, height, renderer, gui, input_manager, &COMMUNITY_DECK[last_drawn_community_idx], players, players_count, p->position);
                // We'll apply the effect when CommunityChestModal is dismissed
            }
            if (active_modal) active_modal->init();
            else selected_action = -1;
            return needs_redraw;
        } else if (chance_modal && chance_modal->is_dismissed()) {
            const ChanceCard* card = &CHANCE_DECK[last_drawn_chance_idx];
            last_drawn_chance_idx = -1;
            delete active_modal;
            active_modal = nullptr;
            ModalButtonHelper::set_monopoly_regions(input_manager, width, height);
            
            // Apply card effects
            bool position_changed = false;
            int old_pos = p->position;

            switch (card->type) {
                case CHANCE_EARN:
                    p->balance += card->value;
                    break;
                case CHANCE_SPEND:
                    active_modal = new PaymentModalGame(width, height, renderer, gui, input_manager, p, nullptr, card->value, "CHANCE CARD");
                    if (active_modal) active_modal->init();
                    break;
                case CHANCE_ADVANCE: {
                    int target = card->value;
                    if (target == TARGET_NEAREST_UTILITY) {
                        target = (p->position + 1) % BOARD_SIZE;
                        while (MONOPOLY_BOARD[target].type != TILE_UTILITY) {
                            target = (target + 1) % BOARD_SIZE;
                        }
                        force_utility_10x = true;
                    } else if (target == TARGET_NEAREST_RAILROAD) {
                        target = (p->position + 1) % BOARD_SIZE;
                        while (MONOPOLY_BOARD[target].type != TILE_RAILROAD) {
                            target = (target + 1) % BOARD_SIZE;
                        }
                        rent_multiplier = 2;
                    }
                    p->position = target;
                    if (p->position < old_pos) p->balance += 200;
                    position_changed = true;
                    break;
                }
                case CHANCE_BACK:
                    p->position = (p->position - card->value + BOARD_SIZE) % BOARD_SIZE;
                    position_changed = true;
                    break;
                case CHANCE_JAIL:
                    p->position = 10; // Jail
                    p->is_in_jail = true;
                    break;
                case CHANCE_JAIL_FREE:
                    p->jail_free_cards++;
                    break;
                case CHANCE_SPEND_EACH_PLAYER:
                    for (int i = 0; i < players_count; i++) {
                        if (i != (int)current_player_idx) {
                            p->balance -= card->value;
                            players[i].balance += card->value;
                        }
                    }
                    break;
                case CHANCE_REPAIRS:
                    // For now, simplify or implement if houses are tracked
                    break;
            }

            needs_redraw = true;
            ModalButtonHelper::set_monopoly_regions(input_manager, width, height);

            if (active_modal) {
                active_modal->init();
            } else if (position_changed) {
                // If we moved, check if we landed on a property
                const BoardTile* landed = &MONOPOLY_BOARD[p->position];
                if (landed->type == TILE_PROPERTY || landed->type == TILE_RAILROAD || landed->type == TILE_UTILITY) {
                    bool is_owned = false;
                    const char* owner_name = nullptr;
                    int owner_id = -1;
                    for (int i = 0; i < players_count; ++i) {
                        for (int j = 0; j < players[i].property_count; ++j) {
                            if (players[i].properties_owned[j] == p->position) {
                                is_owned = true;
                                owner_name = players[i].name;
                                owner_id = i;
                                break;
                            }
                        }
                    }
                    bool can_afford = (p->balance >= landed->cost);
                    active_modal = new PropertyModalGame(width, height, renderer, gui, input_manager, landed, is_owned, owner_name, owner_id, can_afford, players, players_count, current_player_idx);
                    if (active_modal) active_modal->init();
                }
            }
        } else if (community_modal && community_modal->is_dismissed()) {
            const CommunityCard* card = &COMMUNITY_DECK[last_drawn_community_idx];
            last_drawn_community_idx = -1;
            
            bool position_changed = false;
            int old_pos = p->position;

            switch (card->type) {
                case COMMUNITY_EARN:
                    p->balance += card->value;
                    break;
                case COMMUNITY_SPEND:
                    active_modal = new PaymentModalGame(width, height, renderer, gui, input_manager, p, nullptr, card->value, "COMMUNITY CHEST");
                    if (active_modal) active_modal->init();
                    break;
                case COMMUNITY_ADVANCE:
                    p->position = card->value;
                    if (p->position < old_pos) p->balance += 200;
                    position_changed = true;
                    break;
                case COMMUNITY_JAIL:
                    p->position = 10;
                    p->is_in_jail = true;
                    break;
                case COMMUNITY_JAIL_FREE:
                    p->jail_free_cards++;
                    break;
                case COMMUNITY_EARN_EACH_PLAYER:
                    for (int i = 0; i < players_count; i++) {
                        if (i != (int)current_player_idx) {
                            p->balance += card->value;
                            players[i].balance -= card->value;
                        }
                    }
                    break;
                case COMMUNITY_REPAIRS:
                    // p->balance -= (houses * card->value) + (hotels * card->value2);
                    break;
            }

            needs_redraw = true;
            ModalButtonHelper::set_monopoly_regions(input_manager, width, height);

            if (active_modal) {
                active_modal->init();
            } else if (position_changed) {
                const BoardTile* landed = &MONOPOLY_BOARD[p->position];
                if (landed->type == TILE_PROPERTY || landed->type == TILE_RAILROAD || landed->type == TILE_UTILITY) {
                    bool is_owned = false;
                    const char* owner_name = nullptr;
                    int owner_id = -1;
                    for (int i = 0; i < players_count; ++i) {
                        for (int j = 0; j < players[i].property_count; ++j) {
                            if (players[i].properties_owned[j] == p->position) {
                                is_owned = true;
                                owner_name = players[i].name;
                                owner_id = i;
                                break;
                            }
                        }
                    }
                    bool can_afford = (p->balance >= landed->cost);
                    active_modal = new PropertyModalGame(width, height, renderer, gui, input_manager, landed, is_owned, owner_name, owner_id, can_afford, players, players_count, current_player_idx);
                    if (active_modal) active_modal->init();
                }
            }
        } else if (prop_modal && prop_modal->is_dismissed()) {
            bool wants_buy = prop_modal->wants_to_buy();
            bool wants_rent = prop_modal->wants_to_pay_rent();
            int owner_id_from_modal = prop_modal->get_owner_id();
            
            delete active_modal;
            active_modal = nullptr;

            if (wants_buy) {
                const BoardTile* tile = &MONOPOLY_BOARD[p->position];
                if (p->balance >= tile->cost) {
                    active_modal = new PaymentModalGame(width, height, renderer, gui, input_manager, p, nullptr, tile->cost, "BUY PROPERTY");
                    p->properties_owned[p->property_count++] = p->position;
                }
            } else if (wants_rent) {
                const BoardTile* tile = &MONOPOLY_BOARD[p->position];
                int rent = 0;
                if (tile->type == TILE_PROPERTY) {
                    rent = tile->rent[0];
                }
                else if (tile->type == TILE_RAILROAD) {
                    int rr_count = 0;
                    if (owner_id_from_modal != -1) {
                        for (int i = 0; i < players[owner_id_from_modal].property_count; ++i) {
                            if (MONOPOLY_BOARD[players[owner_id_from_modal].properties_owned[i]].type == TILE_RAILROAD) {
                                rr_count++;
                            }
                        }
                    }
                    if (rr_count == 1) rent = 25;
                    else if (rr_count == 2) rent = 50;
                    else if (rr_count == 3) rent = 100;
                    else if (rr_count == 4) rent = 200;
                    else rent = 25;
                }
                else if (tile->type == TILE_UTILITY) {
                    int total_dice = last_dice1 + last_dice2;
                    int utility_count = 0;
                    if (owner_id_from_modal != -1) {
                        for (int i = 0; i < players[owner_id_from_modal].property_count; ++i) {
                            if (MONOPOLY_BOARD[players[owner_id_from_modal].properties_owned[i]].type == TILE_UTILITY) {
                                utility_count++;
                            }
                        }
                    }
                    if (force_utility_10x) {
                        rent = total_dice * 10;
                    } else {
                        rent = (utility_count == 2) ? (total_dice * 10) : (total_dice * 4);
                    }
                }

                rent *= rent_multiplier;

                if (owner_id_from_modal != -1 && (int)current_player_idx != owner_id_from_modal) {
                    active_modal = new PaymentModalGame(width, height, renderer, gui, input_manager, p, &players[owner_id_from_modal], rent, "RENT");
                }
            }
            // Reset multipliers
            rent_multiplier = 1;
            force_utility_10x = false;

            needs_redraw = true;
            ModalButtonHelper::set_monopoly_regions(input_manager, width, height);
            if (active_modal) active_modal->init();
        } else if (board_modal && board_modal->is_dismissed()) {
            delete active_modal;
            active_modal = nullptr;
            needs_redraw = true;
            ModalButtonHelper::set_monopoly_regions(input_manager, width, height);
        } else if (turn_modal && turn_modal->is_dismissed()) {
            delete active_modal;
            active_modal = nullptr;
            needs_redraw = true;
            ModalButtonHelper::set_monopoly_regions(input_manager, width, height);
        }
        
        if (active_modal == nullptr && needs_redraw) {
            selected_action = -1;
        }
        return needs_redraw;
    }

    switch (event.type) {
        case INPUT_BUTTON_0:
            selected_action = (selected_action + 1) % menu_count;
            needs_redraw = true;
            break;
        case INPUT_BUTTON_1:
            if (selected_action == -1) return false;
            
            if (p->is_in_jail && !has_rolled && selected_action == 1) {
                active_modal = new PaymentModalGame(width, height, renderer, gui, input_manager, p, nullptr, 50, "JAIL BAIL");
                if (active_modal) active_modal->init();
                p->is_in_jail = false;
                p->jail_turns = 0;
                selected_action = -1;
                needs_redraw = true;
                return true;
            }
            if (active_modal) delete active_modal;
            if (selected_action == (menu_count - 1)) {
                active_modal = new BoardModalGame(width, height, renderer, gui, input_manager, players, players_count, current_player_idx);
                needs_redraw = true;
            } else if (!has_rolled) {
roll_dice_logic:
                int d1 = (rand() % 6) + 1;
                int d2 = (rand() % 6) + 1;
                bool is_db = (d1 == d2);
                int old_pos = p->position;
                if (p->is_in_jail) {
                    if (is_db) {
                        p->is_in_jail = false; p->jail_turns = 0;
                    } else {
                        p->jail_turns++;
                        if (p->jail_turns >= 3) {
                            active_modal = new PaymentModalGame(width, height, renderer, gui, input_manager, p, nullptr, 50, "JAIL BAIL (FORCED)");
                            if (active_modal) active_modal->init();
                            p->is_in_jail = false; p->jail_turns = 0;
                        } else {
                            has_rolled = true;
                            last_dice1 = d1; last_dice2 = d2;
                            active_modal = new DiceModalGame(width, height, renderer, gui, input_manager, d1, d2, &MONOPOLY_BOARD[old_pos], &MONOPOLY_BOARD[old_pos], players, players_count);
                            needs_redraw = true;
                            return true;
                        }
                    }
                } else if (is_db) {
                    double_rolls++;
                    if (double_rolls >= 3) {
                        p->position = 10; p->is_in_jail = true; p->jail_turns = 0;
                        has_rolled = true; double_rolls = 0;
                        last_dice1 = d1; last_dice2 = d2;
                        active_modal = new DiceModalGame(width, height, renderer, gui, input_manager, d1, d2, &MONOPOLY_BOARD[old_pos], &MONOPOLY_BOARD[10], players, players_count);
                        needs_redraw = true;
                        return true;
                    }
                } else {
                    double_rolls = 0;
                }
                
                int total = d1 + d2;
                p->position = (p->position + total) % BOARD_SIZE;
                if (p->position < old_pos) p->balance += 200;
                has_rolled = !is_db;
                last_dice1 = d1; last_dice2 = d2;
                active_modal = new DiceModalGame(width, height, renderer, gui, input_manager, d1, d2, &MONOPOLY_BOARD[old_pos], &MONOPOLY_BOARD[p->position], players, players_count);
                
                const BoardTile* lnd = &MONOPOLY_BOARD[p->position];
                if (lnd->type == TILE_GO_TO_JAIL) {
                    p->position = 10; p->is_in_jail = true; p->jail_turns = 0;
                    has_rolled = true; double_rolls = 0;
                } else if (lnd->type == TILE_PROPERTY || lnd->type == TILE_RAILROAD || lnd->type == TILE_UTILITY) {
                    modal_property_index = p->position;
                } else if (lnd->type == TILE_CHANCE) {
                    last_drawn_chance_idx = chance_deck[current_chance_idx];
                    current_chance_idx = (current_chance_idx + 1) % CHANCE_DECK_SIZE;
                    if (current_chance_idx == 0) shuffle_chance_deck();
                } else if (lnd->type == TILE_COMMUNITY_CHEST) {
                    last_drawn_community_idx = community_deck[current_community_idx];
                    current_community_idx = (current_community_idx + 1) % COMMUNITY_DECK_SIZE;
                    if (current_community_idx == 0) shuffle_community_deck();
                } else if (lnd->type == TILE_TAX) {
                    active_modal = new PaymentModalGame(width, height, renderer, gui, input_manager, p, nullptr, lnd->cost, "TAXES");
                    if (active_modal) active_modal->init();
                }
                needs_redraw = true;
            } else {
                current_player_idx = (current_player_idx + 1) % players_count;
                has_rolled = false; double_rolls = 0; just_sent_to_jail = false; selected_action = -1;
                active_modal = new TurnModalGame(width, height, renderer, gui, input_manager, &players[current_player_idx]);
                needs_redraw = true;
            }
            break;
        default: break;
    }
    return needs_redraw;
}

// --- Draw game state (minimal: player info, current tile, actions) ---
void MonopolyGame::draw() {
    // If a modal is active, draw it and return
    if (active_modal) {
        active_modal->draw();
        return;
    }
    
    renderer->clear_buffer();

    Player* p = &players[current_player_idx];
    const BoardTile* tile = &MONOPOLY_BOARD[p->position];

    // --- Draw Board Perimeter ---
    MonopolyBoardRenderer::draw_board_perimeter(renderer, width, height, players, players_count, p->position);

    // --- Inner Dashboard (Center Area) ---
    int cw = width / 7;
    int ch = height / 7;
    int ix = cw + 2, iy = ch + 2;
    int iw = width - 2 * cw - 4, ih = height - 2 * ch - 4;

    // --- Inner Dashboard UI ---
    // Window Border
    renderer->draw_rectangle(ix, iy, iw, ih, true, 2);
    renderer->draw_rectangle(ix + 3, iy + 3, iw - 6, ih - 6, true, 1);

    // Header Title Bar (Player Name)
    char buf[128];
    renderer->draw_filled_rectangle(ix + 4, iy + 4, iw - 8, 35, true, 1);
    renderer->set_text_color(false); // White text
    snprintf(buf, sizeof(buf), "%s'S TURN", p->name);
    renderer->draw_string_scaled(ix + (iw - (int)strlen(buf) * 12) / 2, iy + 12, buf, 2);
    renderer->set_text_color(true);

    renderer->draw_string_scaled(ix + (iw - 8 * 18) / 2, iy + ih - 35, "Monopoly", 3);
    
    int content_y = iy + 50;
    
    snprintf(buf, sizeof(buf), "BALANCE: $%d", p->balance);
    renderer->draw_string_scaled(ix + 10, content_y, buf, 2);
    content_y += 25;

    snprintf(buf, sizeof(buf), "TILE: %s", tile->name);
    renderer->draw_string_scaled(ix + 10, content_y, buf, 1);
    content_y += 20;

    // Draw special tile sprite
    const unsigned char* sprite = nullptr;
    if (tile->type == TILE_COMMUNITY_CHEST) sprite = epd_bitmap_CommunityChest;
    else if (tile->type == TILE_CHANCE) sprite = epd_bitmap_Chance;
    else if (tile->type == TILE_FREE_PARKING) sprite = epd_bitmap_FreeParking;
    else if (tile->type == TILE_GO_TO_JAIL) sprite = epd_bitmap_GoToJail;
    else if (tile->type == TILE_UTILITY) {
        if (strstr(tile->name, "Electric")) sprite = epd_bitmap_ElectricCompany;
        else if (strstr(tile->name, "Water")) sprite = epd_bitmap_WaterWorks;
    }

    if (sprite) {
        // Draw at bottom right of dashboard
        renderer->draw_bitmap(sprite, ix + iw - 105, iy + ih - 105, 100, 100, true);
    }

    // Separator line
    renderer->draw_line(ix + 10, content_y, ix + iw - 10, content_y, true);
    content_y += 15;
    // Draw action menu
    const char* actions[3];
    int menu_count = 0;
    if (!has_rolled) {
        actions[menu_count++] = "Roll Dice";
        if (p->is_in_jail) actions[menu_count++] = "Pay $50";
    } else {
        actions[menu_count++] = "End Turn";
    }
    actions[menu_count++] = "View Board";

    for (int i = 0; i < menu_count; ++i) {
        snprintf(buf, sizeof(buf), "%s%s", (i == selected_action) ? "> " : "  ", actions[i]);
        renderer->draw_string_scaled(ix + 15, content_y, buf, 2);
        content_y += 25;
    }

    ModalButtonHelper::draw_virtual_buttons(renderer, input_manager);
}
