// NAME: Buy Baby Bowser Star
// GAMES: MP3_USA
// EXECUTION: Direct
// PARAM: Number|STAR_COST_MIN
// PARAM: Number|STAR_COST_MAX
// PARAM: Number|STAR_COST_STEP

// This is a shameless copy of the Buy a Start event
// https://github.com/PartyPlanner64/events/blob/master/C/Buy%20Star%20(Custom)%20(MP3).c

#define BBOWSER_PICTURE 5
#define MAX_STARS 99

#include "ultra64.h"

struct player {
    s8 unk0;
    s8 cpu_difficulty;
    s8 controller;
    u8 character;
    /**
     * Miscellaneous flags.
     * 1: Is CPU player
     */
    u8 flags;
    s8 pad0[5];
    /**
     * Current coin count.
     */
    s16 coins; // 10
    /**
     * Coins obtained during a Mini-Game.
     */
    s16 minigame_coins; // 12
    s8 stars; // 14

    u8 cur_chain_index; // 15
    u8 cur_space_index; // 16
    u8 next_chain_index; // 17
    u8 next_space_index; // 18
    u8 unk1_chain_index; // 19
    u8 unk1_space_index; // 20
    u8 reverse_chain_index; // 21
    u8 reverse_space_index; // 22

    u8 flags2; // 23
    u8 items[3]; // 24
    u8 bowser_suit_flag; // 27
    u8 turn_color_status; // 28

    s8 pad1[7]; // 29 - 35

    void *obj; // 36 // struct object *
    s16 minigame_star; // 40
    s16 coin_star; // 42
    s8 happening_space_count; // 44
    s8 red_space_count;
    s8 blue_space_count;
    s8 chance_space_count;
    s8 bowser_space_count; // 48
    s8 battle_space_count;
    s8 item_space_count;
    s8 bank_space_count;
    s8 game_guy_space_count; // 52

    // s8 pad2[3];
}; // sizeof == 56

extern struct player *GetPlayerStruct(s32 player_index);

// This is the address where we will store the toll amount.
// This is one of a few available addresses that get copied into EEPROM.
extern u32 D_800CD098;

char price[16];

char *not_enough_coins_msg =
    "\x1A\x1A\x1A\x1A" // Standard padding for picture
    "Sorry "
    "\x11" // Player Character's Name
    "\x82" // ,
    "I can"
    "\0x5C" // '
    "t"
    "\x0A" // New line
    "\x1A\x1A\x1A\x1A"
    "give "
    "\x07" // Yellow Font
    "shiny"
    "\x08" // White Font
    "\x85" // .
    "Come back when"
    "\x0A" // New line
    "\x1A\x1A\x1A\x1A"
    "you"
    "\0x5C" // '
    "re a little"
    "\x85\x85" // ..
    " MMMM"
    "\x0A" // New line
    "\x1A\x1A\x1A\x1A"
    " richer"
    "\xC2" // !
    "\xFF";

char *too_many_stars_msg =
    "\x1A\x1A\x1A\x1A" // Standard padding for picture
    "Nice to see y"
    "\x3D" // -
    "\x0A" // New line
    "\x1A\x1A\x1A\x1A"
    "Whoa"
    "\xC2\xC2\xC2" // !!!
    " You can\x5Ct carry any more stars\xC2"
    "\x0A"
    "\x1A\x1A\x1A\x1A"
    "I guess I\x5Cll see you later"
    "\xC3" // ?
    "\xFF";

char *declined_msg =
    "\x1A\x1A\x1A\x1A" // Standard padding for picture
    "No way dude"
    "\x85" // .
    "\x0A" // New line
    "\x1A\x1A\x1A\x1A"
    "Get outta here"
    "\xC2" // !
    "\xFF";

char *prompt_msg = 
    "\x0B" // Start the message
    "\x1A\x1A\x1A\x1A" // Standard padding for picture
    "Hey there "
    "\x11" // Player Character's Name
    "\xC2" // !
    "\x0A" // Newline
    "\x1A\x1A\x1A\x1A"
    "I found this "
    "\x07" // Yellow Font
    "shiny"
    "\x08" // White Font
    " thing lying "
    "\x0A" // Newline
    "\x1A\x1A\x1A\x1A"
    "around"
    "\x85" // .
    " You wanna make a deal"
    "\xC3" // "?"
    "\x0A" // Newline
    "\x1A\x1A\x1A\x1A\x1A\x1A" // Little more for option indent
    "\x0C" // Start option
    "\0xC0" // “
    "Slide him "
    "\x06" // Blue font
    "\x12" // Star Price
    " Coins"
    "\x08" // White Font
    "\0xC1" // ”
    "\x0D" // End option
    "\x0A" // Newline
    "\x1A\x1A\x1A\x1A\x1A\x1A"
    "\x0C" // Start option
    "Could I have it for free"
    "\xC3" // "?"
    "\x0D" // End option
    "\x0A" // Newline
    "\x1A\x1A\x1A\x1A\x1A\x1A"
    "\x0C" // Start option
    "View Map"
    "\x0D"; // End option

void main() {
    s32 player_index = GetCurrentPlayerIndex();

    struct player *player = GetPlayerStruct(player_index);

    s32 character_str = 0x1C00 + player->character;

    if (D_800CD098 == 0) {
        D_800CD098 = STAR_COST_MIN;
    }
    s32 proposed_payment = D_800CD098;

    // Check for sufficient coins.
    if (PlayerHasCoins(player_index, proposed_payment) == 0) {
        PlaySound(0x11D); // Baby Bowser

        ShowMessage(BBOWSER_PICTURE, not_enough_coins_msg, character_str, 0, 0, 0, 0);
        func_800EC9DC();
        CloseMessage();
        func_800EC6EC();
        return;
    }

    // Edge case: check if the player has too many stars.
    if (player->stars >= MAX_STARS) {
        PlaySound(0x11D); // Baby Bowser

        ShowMessage(BBOWSER_PICTURE, too_many_stars_msg, 0, 0, 0, 0, 0);
        func_800EC9DC();
        CloseMessage();
        func_800EC6EC();
        return;
    }

    sprintf(price, "%d", proposed_payment);

    while (1) {
        // Prompt the player to buy.
        ShowMessage(
            BBOWSER_PICTURE,
            prompt_msg,
            character_str, price, 0, 0, 0
        );

        // Get the selection, either from the player or CPU.
        // If A0 is a pointer to AI data, AI logic is ran to pick for CPUs.
        // If A0 is 0 or 1, the 0th or 1st option is chosen by CPUs.
        // If A0 is 2, the value of A1 is the CPUs option index choice.
        // In this case, we have CPUs always pick Yes (0)
        s32 choice = GetBasicPromptSelection(2, 0);

        CloseMessage();
        func_800EC6EC();

        switch (choice) {
            case 0:
                // Take coins
                AdjustPlayerCoinsGradual(player_index, -proposed_payment);
                ShowPlayerCoinChange(player_index, -proposed_payment);
                SleepProcess(35);

                // Celebration
                func_8004A520(111); // Play star jingle
                player->stars++;
                func_800F2304(-1, 6, 0);
                func_8004ACE0(610, player_index);
                SleepProcess(60);
                SleepProcess(50);

                if (proposed_payment >= STAR_COST_MAX) {
                	D_800CD098 = STAR_COST_MIN;
                }
                else if (proposed_payment + STAR_COST_STEP <= STAR_COST_MAX) {
                	D_800CD098 = (proposed_payment + STAR_COST_STEP);
                }

                // Restore board music
                func_8004A520(GetBoardAudioIndex());
                return;

            case 1:
                // Show decline message and exit
                ShowMessage(BBOWSER_PICTURE, declined_msg, 0, 0, 0, 0, 0);
                func_800EC9DC();
                CloseMessage();
                func_800EC6EC();
                return;

            case 2:
                // Let player view the map, then repeat the loop to pick again.
                ViewBoardMap();
                break;
        }
    }
}