#include "global.h"
#include "main.h"
#include "battle.h"
#include "bg.h"
#include "contest_effect.h"
#include "data2.h"
#include "event_data.h"
#include "field_screen.h"
#include "gpu_regs.h"
#include "learn_move.h"
#include "list_menu.h"
#include "malloc.h"
#include "menu.h"
#include "menu_helpers.h"
#include "overworld.h"
#include "palette.h"
#include "pokemon_summary_screen.h"
#include "pokenav.h"
#include "script.h"
#include "sound.h"
#include "sprite.h"
#include "string_util.h"
#include "strings.h"
#include "task.h"
#include "constants/rgb.h"
#include "constants/songs.h"

static EWRAM_DATA struct
{
    u8 state;
    u8 spriteIds[16];                   /*0x001*/
    u16 movesToLearn[4];                /*0x012*/
    u8 filler1A[0x44 - 0x1A];           /*0x01A*/
    u8 partyMon;                        /*0x044*/
    u8 moveSlot;                        /*0x045*/
    struct ListMenuItem menuItems[20];  /*0x048*/
    u8 fillerE8[0x110 - 0xE8];          /*0x0E8*/
    u8 numMenuChoices;                  /*0x110*/
    u8 numToShowAtOnce;                 /*0x111*/
    u8 listMenuTask;                    /*0x112*/
    u8 scrollArrowTaskId1;              /*0x113*/
    u8 scrollArrowTaskId2;              /*0x114*/
    u16 scrollOffset;                   /*0x116*/
} *sLearnMoveStruct = {0};

static EWRAM_DATA struct {
    u16 listOffset;
    u16 listRow;
    u8 showContestInfo;
} sLearnMoveStruct2 = {0};

const u16 gUnknown_085CE9F8[] = INCBIN_U16("graphics/interface/ui_learn_move.gbapal");
const u8 gUnknown_085CEA18[] = INCBIN_U8("graphics/interface/ui_learn_move.4bpp");

const struct OamData gUnknown_085CEB98 = 
{
    .y = 0,
    .affineMode = 0,
    .objMode = ST_OAM_OBJ_NORMAL,
    .mosaic = 0,
    .bpp = ST_OAM_4BPP,
    .shape = ST_OAM_SQUARE,
    .x = 0,
    .matrixNum = 0,
    .size = 0,
    .tileNum = 0,
    .priority = 0,
    .paletteNum = 0,
    .affineParam = 0,
};

const struct OamData gUnknown_085CEBA0 = 
{
    .y = 0,
    .affineMode = 0,
    .objMode = ST_OAM_OBJ_NORMAL,
    .mosaic = 0,
    .bpp = ST_OAM_4BPP,
    .shape = ST_OAM_V_RECTANGLE,
    .x = 0,
    .matrixNum = 0,
    .size = 0,
    .tileNum = 0,
    .priority = 0,
    .paletteNum = 0,
    .affineParam = 0,
};

const struct OamData gUnknown_085CEBA8 = 
{
    .y = 0,
    .affineMode = 0,
    .objMode = ST_OAM_OBJ_NORMAL,
    .mosaic = 0,
    .bpp = ST_OAM_4BPP,
    .shape = ST_OAM_H_RECTANGLE,
    .x = 0,
    .matrixNum = 0,
    .size = 0,
    .tileNum = 0,
    .priority = 0,
    .paletteNum = 0,
    .affineParam = 0,
};

const struct SpriteSheet gUnknown_085CEBB0 = 
{
    .data = gUnknown_085CEA18,
    .size = 0x180,
    .tag = 5525
};

const struct SpritePalette gUnknown_085CEBB8 = 
{
    .data = gUnknown_085CE9F8,
    .tag = 5526
};

const struct ScrollArrowsTemplate gUnknown_085CEBC0 = 
{
    .firstArrowType = 0,
    .firstX = 27,
    .firstY = 16,
    .secondArrowType = 1,
    .secondX = 117,
    .secondY = 16,
    .fullyUpThreshold = -1,
    .fullyDownThreshold = -1,
    .tileTag = 5325,
    .palTag = 5325,
    .palNum = 0,
};

const struct ScrollArrowsTemplate gUnknown_085CEBD0 = 
{
    .firstArrowType = 2,
    .firstX = 192,
    .firstY = 8,
    .secondArrowType = 3,
    .secondX = 192,
    .secondY = 104,
    .fullyUpThreshold = 0,
    .fullyDownThreshold = 0,
    .tileTag = 5425,
    .palTag = 5425,
    .palNum = 0,
};

const union AnimCmd gUnknown_085CEBE0[] = 
{
    ANIMCMD_FRAME(8, 5, FALSE, FALSE),
    ANIMCMD_END
};

const union AnimCmd gUnknown_085CEBE8[] = 
{
    ANIMCMD_FRAME(9, 5, FALSE, FALSE),
    ANIMCMD_END
};

const union AnimCmd gUnknown_085CEBF0[] = 
{
    ANIMCMD_FRAME(10, 5, FALSE, FALSE),
    ANIMCMD_END
};

const union AnimCmd gUnknown_085CEBF8[] = 
{
    ANIMCMD_FRAME(11, 5, FALSE, FALSE),
    ANIMCMD_END
};

const union AnimCmd *const gUnknown_085CEC00[] = 
{
    gUnknown_085CEBE0,
    gUnknown_085CEBE8,
    gUnknown_085CEBF0,
    gUnknown_085CEBF8,
};

const struct SpriteTemplate gUnknown_085CEC10 = 
{
    .tileTag = 5525,
    .paletteTag = 5526,
    .oam = &gUnknown_085CEB98,
    .anims = gUnknown_085CEC00,
    .images = NULL,
    .affineAnims = gDummySpriteAffineAnimTable,
    .callback = SpriteCallbackDummy
};

const struct BgTemplate gUnknown_085CEC28[] =
{
    {
        .bg = 0,
        .charBaseIndex = 0,
        .mapBaseIndex = 31,
        .screenSize = 0,
        .paletteMode = 0,
        .priority = 0,
        .baseTile = 0,
    },
    {
        .bg = 1,
        .charBaseIndex = 0,
        .mapBaseIndex = 30,
        .screenSize = 0,
        .paletteMode = 0,
        .priority = 1,
        .baseTile = 0,
    },
};

static void LearnMoveMain(void);
static void CreateMenuItemsList(void);
static void CreateHearts(void);
static void CB2_Main(void);
static void Task_WaitForFadeOut(u8 taskId);
static void CB2_InitLearnMove(void);
static void CB2_InitLearnMoveReturnFromSelectMove(void);
static void InitBGs(void);
static void AddScrollArrows(void);
static void HandleInput(u8);
static void ShowTeachMoveText(u8);
static s32 GetCurrentItemId(void);
static void FreeListMenuResources(void);
static void RemoveScrollArrows(void);
static void HideSpritesAndPrintTeachText(bool8);

static void VBlankCB_LearnMove(void)
{
    LoadOam();
    ProcessSpriteCopyRequests();
    TransferPlttBuffer();
}

void TeachMoveTutorMove(void)
{
    ScriptContext2_Enable();
    CreateTask(Task_WaitForFadeOut, 0xA);
    BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, 0);
}

static void Task_WaitForFadeOut(u8 taskId)
{
    if (!gPaletteFade.active)
    {
        SetMainCallback2(CB2_InitLearnMove);
        gFieldCallback = sub_80AF168;
        DestroyTask(taskId);
    }
}

static void CB2_InitLearnMove(void)
{
    ResetSpriteData();
    FreeAllSpritePalettes();
    ResetTasks();
    clear_scheduled_bg_copies_to_vram();
    sLearnMoveStruct = AllocZeroed(sizeof(*sLearnMoveStruct));
    sLearnMoveStruct->partyMon = gSpecialVar_0x8004;
    SetVBlankCallback(VBlankCB_LearnMove);

    InitBGs();
    sub_81D2824(0);

    sLearnMoveStruct2.listOffset = 0;
    sLearnMoveStruct2.listRow = 0;
    sLearnMoveStruct2.showContestInfo = FALSE;

    CreateMenuItemsList();

    LoadSpriteSheet(&gUnknown_085CEBB0);
    LoadSpritePalette(&gUnknown_085CEBB8);
    CreateHearts();

    sLearnMoveStruct->listMenuTask = ListMenuInit(&gMultiuseListMenuTemplate, sLearnMoveStruct2.listOffset, sLearnMoveStruct2.listRow);
    FillPalette(RGB_BLACK, 0, 2);
    SetMainCallback2(CB2_Main);
}

static void CB2_InitLearnMoveReturnFromSelectMove(void)
{
    ResetSpriteData();
    FreeAllSpritePalettes();
    ResetTasks();
    clear_scheduled_bg_copies_to_vram();
    sLearnMoveStruct = AllocZeroed(sizeof(*sLearnMoveStruct));
    sLearnMoveStruct->state = 28;
    sLearnMoveStruct->partyMon = gSpecialVar_0x8004;
    sLearnMoveStruct->moveSlot = gSpecialVar_0x8005;
    SetVBlankCallback(VBlankCB_LearnMove);

    InitBGs();
    sub_81D2824(sLearnMoveStruct2.showContestInfo);
    CreateMenuItemsList();

    LoadSpriteSheet(&gUnknown_085CEBB0);
    LoadSpritePalette(&gUnknown_085CEBB8);
    CreateHearts();

    sLearnMoveStruct->listMenuTask = ListMenuInit(&gMultiuseListMenuTemplate, sLearnMoveStruct2.listOffset, sLearnMoveStruct2.listRow);
    FillPalette(RGB_BLACK, 0, 2);
    SetMainCallback2(CB2_Main);
}

static void InitBGs(void)
{
    ResetVramOamAndBgCntRegs();
    ResetBgsAndClearDma3BusyFlags(0);
    InitBgsFromTemplates(0, gUnknown_085CEC28, 2);
    ResetAllBgsCoordinates();
    SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 |
                                  DISPCNT_OBJ_1D_MAP |
                                  DISPCNT_OBJ_ON);
    ShowBg(0);
    ShowBg(1);
    SetGpuReg(REG_OFFSET_BLDCNT, 0);
}

static void CB2_Main(void)
{
    LearnMoveMain();
    RunTasks();
    AnimateSprites();
    BuildOamBuffer();
    do_scheduled_bg_tilemap_copies_to_vram();
    UpdatePaletteFade();
}

static void sub_816084C(const u8 *src)
{
    StringExpandPlaceholders(gStringVar4, src);
    sub_81D2BF4(gStringVar4);
}

static void LearnMoveMain(void)
{
    switch (sLearnMoveStruct->state)
    {
    case 0:
        sLearnMoveStruct->state++;
        HideSpritesAndPrintTeachText(FALSE);
        BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK);
        break;
    case 1:
        if (!gPaletteFade.active)
        {
            sLearnMoveStruct->state = 4;
        }
        break;
    case 2:
        sLearnMoveStruct->state++;
        break;
    case 3:
        HideSpritesAndPrintTeachText(FALSE);
        sLearnMoveStruct->state++;
        AddScrollArrows();
        break;
    case 4:
        HandleInput(FALSE);
        return;
    case 5:
        ShowTeachMoveText(FALSE);
        sLearnMoveStruct->state++;
        AddScrollArrows();
        break;
    case 6:
        HandleInput(TRUE);
        break;
    case 8:
        if (!sub_81D2C3C())
        {
            sub_81D2C50();
            sLearnMoveStruct->state++;
        }
        break;
    case 9:
        {
            s8 selection = Menu_ProcessInputNoWrap_();

            if (selection == 0)
            {
                if (GiveMoveToMon(&gPlayerParty[sLearnMoveStruct->partyMon], GetCurrentItemId()) != 0xFFFF)
                {
                    sub_816084C(gText_PkmnLearnedMove4);
                    gSpecialVar_0x8004 = 1;
                    sLearnMoveStruct->state = 31;
                }
                else
                {
                    sLearnMoveStruct->state = 16;
                }
            }
            else if (selection == -1 || selection == 1)
            {
                if (sLearnMoveStruct2.showContestInfo == FALSE)
                {
                    sLearnMoveStruct->state = 3;
                }
                else if (sLearnMoveStruct2.showContestInfo == TRUE)
                {
                    sLearnMoveStruct->state = 5;
                }
            }
        }
        break;
    case 12:
        if (!sub_81D2C3C())
        {
            sub_81D2C50();
            sLearnMoveStruct->state++;
        }
        break;
    case 13:
        {
            s8 selection = Menu_ProcessInputNoWrap_();

            if (selection == 0)
            {
                gSpecialVar_0x8004 = selection;
                sLearnMoveStruct->state = 14;
            }
            else if (selection == -1 || selection == 1)
            {
                if (sLearnMoveStruct2.showContestInfo == FALSE)
                {
                    sLearnMoveStruct->state = 3;
                }
                else if (sLearnMoveStruct2.showContestInfo == TRUE)
                {
                    sLearnMoveStruct->state = 5;
                }
            }
        }
        break;
    case 16:
        sub_816084C(gText_PkmnTryingToLearnMove);
        sLearnMoveStruct->state++;
        break;
    case 17:
        if (!sub_81D2C3C())
        {
            sub_81D2C50();
            sLearnMoveStruct->state = 18;
        }
        break;
    case 18:
        {
            s8 var = Menu_ProcessInputNoWrap_();

            if (var == 0)
            {
                sub_816084C(gText_WhichMoveToForget2);
                sLearnMoveStruct->state = 19;
            }
            else if (var == -1 || var == 1)
            {
                sLearnMoveStruct->state = 24;
            }
        }
        break;
    case 24:
        StringCopy(gStringVar2, gMoveNames[GetCurrentItemId()]);
        sub_816084C(gText_StopTryingToTeachMove);
        sLearnMoveStruct->state++;
        break;
    case 25:
        if (!sub_81D2C3C())
        {
            sub_81D2C50();
            sLearnMoveStruct->state++;
        }
        break;
    case 26:
        {
            s8 var = Menu_ProcessInputNoWrap_();

            if (var == 0)
            {
                sLearnMoveStruct->state = 27;
            }
            else if (var == -1 || var == 1)
            {
                // What's the point? It gets set to 16, anyway.
                if (sLearnMoveStruct2.showContestInfo == FALSE)
                {
                    sLearnMoveStruct->state = 3;
                }
                else if (sLearnMoveStruct2.showContestInfo == TRUE)
                {
                    sLearnMoveStruct->state = 5;
                }
                sLearnMoveStruct->state = 16;
            }
        }
        break;
    case 27:
        if (!sub_81D2C3C())
        {
            FillWindowPixelBuffer(3, 0x11);
            if (sLearnMoveStruct2.showContestInfo == FALSE)
            {
                sLearnMoveStruct->state = 3;
            }
            else if (sLearnMoveStruct2.showContestInfo == TRUE)
            {
                sLearnMoveStruct->state = 5;
            }
        }
        break;
    case 19:
        if (!sub_81D2C3C())
        {
            sLearnMoveStruct->state = 20;
            BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK);
        }
        break;
    case 20:
        if (!gPaletteFade.active)
        {
            ShowSelectMovePokemonSummaryScreen(gPlayerParty, sLearnMoveStruct->partyMon, gPlayerPartyCount - 1, CB2_InitLearnMoveReturnFromSelectMove, GetCurrentItemId());
            FreeListMenuResources();
        }
        break;
    case 21:
        if (!sub_81D2C3C())
        {
            sLearnMoveStruct->state = 14;
        }
        break;
    case 22:
        BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK);
        break;
    case 14:
        BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK);
        sLearnMoveStruct->state++;
        break;
    case 15:
        if (!gPaletteFade.active)
        {
            FreeListMenuResources();
            SetMainCallback2(CB2_ReturnToField);
        }
        break;
    case 28:
        BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK);
        sLearnMoveStruct->state++;
        if (sLearnMoveStruct2.showContestInfo == FALSE)
        {
            HideSpritesAndPrintTeachText(TRUE);
        }
        else if (sLearnMoveStruct2.showContestInfo == TRUE)
        {
            ShowTeachMoveText(TRUE);
        }
        RemoveScrollArrows();
        CopyWindowToVram(3, 2);
        break;
    case 29:
        if (!gPaletteFade.active)
        {
            if (sLearnMoveStruct->moveSlot == MAX_MON_MOVES)
            {
                sLearnMoveStruct->state = 24;
            }
            else
            {
                u16 moveId = GetMonData(&gPlayerParty[sLearnMoveStruct->partyMon], MON_DATA_MOVE1 + sLearnMoveStruct->moveSlot);

                StringCopy(gStringVar3, gMoveNames[moveId]);
                RemoveMonPPBonus(&gPlayerParty[sLearnMoveStruct->partyMon], sLearnMoveStruct->moveSlot);
                SetMonMoveSlot(&gPlayerParty[sLearnMoveStruct->partyMon], GetCurrentItemId(), sLearnMoveStruct->moveSlot);
                StringCopy(gStringVar2, gMoveNames[GetCurrentItemId()]);
                sub_816084C(gText_12AndPoof);
                sLearnMoveStruct->state = 30;
                gSpecialVar_0x8004 = 1;
            }
        }
        break;
    case 30:
        if (!sub_81D2C3C())
        {
            sub_816084C(gText_PkmnForgotMoveAndLearnedNew);
            sLearnMoveStruct->state = 31;
            PlayFanfare(MUS_FANFA1);
        }
        break;
    case 31:
        if (!sub_81D2C3C())
        {
            PlayFanfare(MUS_FANFA1);
            sLearnMoveStruct->state = 32;
        }
        break;
    case 32:
        if (IsFanfareTaskInactive())
        {
            sLearnMoveStruct->state = 33;
        }
        break;
    case 33:
        if (gMain.newKeys & A_BUTTON)
        {
            PlaySE(SE_SELECT);
            sLearnMoveStruct->state = 14;
        }
        break;
    }
}

static void FreeListMenuResources(void)
{
    RemoveScrollArrows();
    DestroyListMenuTask(sLearnMoveStruct->listMenuTask, &sLearnMoveStruct2.listOffset, &sLearnMoveStruct2.listRow);
    FreeAllWindowBuffers();
    FREE_AND_SET_NULL(sLearnMoveStruct);
    ResetSpriteData();
    FreeAllSpritePalettes();
}

static void HideSpritesAndPrintTeachText(bool8 a)
{
    s32 i;

    for (i = 0; i < 16; i++)
    {
        gSprites[sLearnMoveStruct->spriteIds[i]].invisible = TRUE;
    }

    if (!a)
    {
        StringExpandPlaceholders(gStringVar4, gText_TeachWhichMoveToPkmn);
        FillWindowPixelBuffer(3, 0x11);
        AddTextPrinterParameterized(3, 1, gStringVar4, 0, 1, 0, NULL);
    }
}

static void HandleInput(bool8 showContest)
{
    s32 itemId = ListMenuHandleInputGetItemId(sLearnMoveStruct->listMenuTask);
    ListMenuGetScrollAndRow(sLearnMoveStruct->listMenuTask, &sLearnMoveStruct2.listOffset, &sLearnMoveStruct2.listRow);

    switch (itemId)
    {
    case LIST_NOTHING_CHOSEN:
        if (!(gMain.newKeys & (DPAD_LEFT | DPAD_RIGHT)) && !GetLRKeysState())
        {
            break;
        }

        PlaySE(SE_SELECT);

        if (showContest == FALSE)
        {
            PutWindowTilemap(1);
            sLearnMoveStruct->state = 5;
            sLearnMoveStruct2.showContestInfo = TRUE;
        }
        else
        {
            PutWindowTilemap(0);
            sLearnMoveStruct->state = 3;
            sLearnMoveStruct2.showContestInfo = FALSE;
        }

        schedule_bg_copy_tilemap_to_vram(1);
        ShowHideHearts(GetCurrentItemId());
        break;
    case LIST_B_PRESSED:
        PlaySE(SE_SELECT);
        RemoveScrollArrows();
        sLearnMoveStruct->state = 12;
        StringExpandPlaceholders(gStringVar4, gText_GiveUpTeachingNewMove);
        sub_81D2BF4(gStringVar4);
        break;
    default:
        PlaySE(SE_SELECT);
        RemoveScrollArrows();
        sLearnMoveStruct->state = 8;
        StringCopy(gStringVar2, gMoveNames[itemId]);
        StringExpandPlaceholders(gStringVar4, gText_TeachX);
        sub_81D2BF4(gStringVar4);
        break;
    }
}

static s32 GetCurrentItemId(void)
{
    return sLearnMoveStruct->menuItems[sLearnMoveStruct2.listRow + sLearnMoveStruct2.listOffset].id;
}

static void ShowTeachMoveText(bool8 showContest)
{
    if (showContest == FALSE)
    {
        StringExpandPlaceholders(gStringVar4, gText_TeachWhichMoveToPkmn);
        FillWindowPixelBuffer(3, 0x11);
        AddTextPrinterParameterized(3, 1, gStringVar4, 0, 1, 0, NULL);
    }
}

static void CreateHearts(void)
{
    int i;

    sLearnMoveStruct->scrollArrowTaskId2 = -1;
    sLearnMoveStruct->scrollArrowTaskId1 = -1;
    AddScrollArrows();
    
    for (i = 0; i < 8; i++)
    {
        sLearnMoveStruct->spriteIds[i] = CreateSprite(&gUnknown_085CEC10, (i - (i / 4) * 4) * 8 + 104, (i / 4) * 8 + 36, 0);
    }

    for (i = 0; i < 8; i++)
    {
        sLearnMoveStruct->spriteIds[i + 8] = CreateSprite(&gUnknown_085CEC10, (i - (i / 4) * 4) * 8 + 104, (i / 4) * 8 + 52, 0);
        StartSpriteAnim(&gSprites[sLearnMoveStruct->spriteIds[i + 8]], 2);
    }

    for (i = 0; i < 16; i++)
    {
        gSprites[sLearnMoveStruct->spriteIds[i]].invisible = TRUE;
    }
}

static void AddScrollArrows(void)
{
    if (sLearnMoveStruct->scrollArrowTaskId2 == 0xFF)
    {
        sLearnMoveStruct->scrollArrowTaskId2 = AddScrollIndicatorArrowPair(&gUnknown_085CEBC0, &sLearnMoveStruct->scrollOffset);
    }

    if (sLearnMoveStruct->scrollArrowTaskId1 == 0xFF)
    {
        gTempScrollArrowTemplate = gUnknown_085CEBD0;
        gTempScrollArrowTemplate.fullyDownThreshold = sLearnMoveStruct->numMenuChoices - sLearnMoveStruct->numToShowAtOnce;
        sLearnMoveStruct->scrollArrowTaskId1 = AddScrollIndicatorArrowPair(&gTempScrollArrowTemplate, &sLearnMoveStruct2.listOffset);
    }
}

static void RemoveScrollArrows(void)
{
    if (sLearnMoveStruct->scrollArrowTaskId2 != 0xFF)
    {
        RemoveScrollIndicatorArrowPair(sLearnMoveStruct->scrollArrowTaskId2);
        sLearnMoveStruct->scrollArrowTaskId2 = 0xFF;
    }

    if (sLearnMoveStruct->scrollArrowTaskId1 != 0xFF)
    {
        RemoveScrollIndicatorArrowPair(sLearnMoveStruct->scrollArrowTaskId1);
        sLearnMoveStruct->scrollArrowTaskId1 = 0xFF;
    }
}

static void CreateMenuItemsList(void)
{
    s32 i;
    u8 nickname[POKEMON_NAME_LENGTH + 1];

    sLearnMoveStruct->numMenuChoices = GetMoveRelearnerMoves(&gPlayerParty[sLearnMoveStruct->partyMon], sLearnMoveStruct->movesToLearn);

    for (i = 0; i < sLearnMoveStruct->numMenuChoices; i++)
    {
        sLearnMoveStruct->menuItems[i].name = gMoveNames[sLearnMoveStruct->movesToLearn[i]];
        sLearnMoveStruct->menuItems[i].id = sLearnMoveStruct->movesToLearn[i];
    }

    GetMonData(&gPlayerParty[sLearnMoveStruct->partyMon], MON_DATA_NICKNAME, nickname);
    StringCopy10(gStringVar1, nickname);
    sLearnMoveStruct->menuItems[sLearnMoveStruct->numMenuChoices].name = gText_Cancel;
    sLearnMoveStruct->menuItems[sLearnMoveStruct->numMenuChoices].id = LIST_B_PRESSED;
    sLearnMoveStruct->numMenuChoices++;
    sLearnMoveStruct->numToShowAtOnce = sub_81D28C8(sLearnMoveStruct->menuItems, sLearnMoveStruct->numMenuChoices);
}

void ShowHideHearts(s32 item)
{
    u16 numHearts;
    u16 i;

    if (!sLearnMoveStruct2.showContestInfo || item == LIST_B_PRESSED)
    {
        for (i = 0; i < 16; i++)
        {
            gSprites[sLearnMoveStruct->spriteIds[i]].invisible = TRUE;
        }
    }
    else
    {
        numHearts = (u8)(gContestEffects[gContestMoves[item].effect].appeal / 10);
        
        if (numHearts == 0xFF)
        {
            numHearts = 0;
        }

        for (i = 0; i < 8; i++)
        {
            if (i < numHearts)
            {
                StartSpriteAnim(&gSprites[sLearnMoveStruct->spriteIds[i]], 1);
            }
            else
            {
                StartSpriteAnim(&gSprites[sLearnMoveStruct->spriteIds[i]], 0);
            }
            gSprites[sLearnMoveStruct->spriteIds[i]].invisible = FALSE;
        }

        numHearts = (u8)(gContestEffects[gContestMoves[item].effect].jam / 10);
        
        if (numHearts == 0xFF)
        {
            numHearts = 0;
        }

        for (i = 0; i < 8; i++)
        {
            if (i < numHearts)
            {
                StartSpriteAnim(&gSprites[sLearnMoveStruct->spriteIds[i + 8]], 3);
            }
            else
            {
                StartSpriteAnim(&gSprites[sLearnMoveStruct->spriteIds[i + 8]], 2);
            }
            gSprites[sLearnMoveStruct->spriteIds[i + 8]].invisible = FALSE;
        }
    }
}
