#include "global.h"
#include "data.h"
#include "decompress.h"
#include "main.h"
#include "menu_specialized.h"
#include "mon_markings.h"
#include "pokenav.h"
#include "pokemon.h"
#include "pokemon_storage_system.h"
#include "sound.h"
#include "string_util.h"
#include "strings.h"
#include "text.h"
#include "constants/songs.h"

struct PokenavSub11
{
    u32 monPal[3][0x20];
    u8 fill[0x180];
    u32 monPicGfx[3][0x800];
    u8 searchMode;
    s16 monIndex;
    u32 (*callback)(struct PokenavSub11 *);
    u8 fill2[0x6320 - 0x6308];
    u8 searchLocBuffer[3][24];
    u8 nameBuffer[3][64];
    struct ConditionGraph conditionData;
    u8 sheen[3];
    u8 monMarks[3];
    s8 mark;
    s8 unk6787;
    s8 unk6788;
    s8 unk6789;
    u8 state;
};

void InitPartyConditionListParameters(void);
void sub_81CD9F8(void);
u32 HandlePartyConditionInput(struct PokenavSub11 *structPtr);
u32 GetConditionReturnCallback(struct PokenavSub11 *structPtr);
u32 ConditionMenu_OpenMarkingsMenu(struct PokenavSub11 *structPtr);
u8 ConditionGraphHandleDpadInput(struct PokenavSub11 *structPtr);
u8 SwitchConditionSummaryIndex(u8 moveUp);
void CopyMonNameGenderLocation(s16 id, u8 arg1);
void GetMonConditionGraphData(s16 id, u8 arg1);
void ConditionGraphDrawMonPic(s16 id, u8 arg1);

// code
bool32 PokenavCallback_Init_PartyCondition(void)
{
    struct PokenavSub11 *structPtr = AllocSubstruct(POKENAV_SUBSTRUCT_CONDITION_GRAPH, sizeof(struct PokenavSub11));

    if (structPtr == NULL)
        return FALSE;

    InitConditionGraphData(&structPtr->conditionData);
    InitPartyConditionListParameters();
    gKeyRepeatStartDelay = 20;
    structPtr->callback = HandlePartyConditionInput;
    return TRUE;
}

bool32 PokenavCallback_Init_ConditionGraphFromSearch(void)
{
    struct PokenavSub11 *structPtr = AllocSubstruct(POKENAV_SUBSTRUCT_CONDITION_GRAPH, sizeof(struct PokenavSub11));

    if (structPtr == NULL)
        return FALSE;

    InitConditionGraphData(&structPtr->conditionData);
    sub_81CD9F8();
    gKeyRepeatStartDelay = 20;
    structPtr->callback = HandlePartyConditionInput;
    return TRUE;
}

u32 GetPartyConditionCallback(void)
{
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);

    return structPtr->callback(structPtr);
}

u32 HandlePartyConditionInput(struct PokenavSub11 *structPtr)
{
    struct PokenavSub18 *monListPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_MON_LIST);
    u32 ret = ConditionGraphHandleDpadInput(structPtr);

    if (ret == PARTY_CONDITION_FUNC_NONE)
    {
        if (JOY_NEW(B_BUTTON))
        {
            PlaySE(SE_SELECT);
            structPtr->callback = GetConditionReturnCallback;
            ret = PARTY_CONDITION_FUNC_RETURN;
        }
        else if (JOY_NEW(A_BUTTON))
        {
            if (structPtr->searchMode == 0)
            {
                if (monListPtr->currIndex == monListPtr->listCount - 1)
                {
                    PlaySE(SE_SELECT);
                    structPtr->callback = GetConditionReturnCallback;
                    ret = PARTY_CONDITION_FUNC_RETURN;
                }
            }
            else
            {
                PlaySE(SE_SELECT);
                ret = PARTY_CONDITION_FUNC_ADD_MARKINGS;
                structPtr->callback = ConditionMenu_OpenMarkingsMenu;
            }
        }
    }

    return ret;
}

u32 ConditionMenu_OpenMarkingsMenu(struct PokenavSub11 *structPtr)
{
    struct PokenavSub18 *monListPtr;
    u8 markings;
    u32 ret = PARTY_CONDITION_FUNC_NONE, boxId, monId;

    if (!MonMarkingsMenuHandleInput())
    {
        structPtr->monMarks[structPtr->mark] = GetMonMarkingsData();
        monListPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_MON_LIST);
        boxId = monListPtr->monData[monListPtr->currIndex].boxId;
        monId = monListPtr->monData[monListPtr->currIndex].monId;
        markings = structPtr->monMarks[structPtr->mark];

        if (boxId == TOTAL_BOXES_COUNT)
            SetMonData(&gPlayerParty[monId], MON_DATA_MARKINGS, &markings);
        else
            SetBoxMonDataAt(boxId, monId, MON_DATA_MARKINGS, &markings);

        structPtr->callback = HandlePartyConditionInput;
        ret = PARTY_CONDITION_FUNC_CLOSE_MARKINGS;
    }

    return ret;
}

u32 GetConditionReturnCallback(struct PokenavSub11 *structPtr)
{
    if (structPtr->searchMode == 0)
        return POKENAV_CONDITION_MENU;
    else
        return POKENAV_RETURN_CONDITION_SEARCH;
}

void FreePartyConditionSubstruct1(void)
{
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);
    if (structPtr->searchMode == 0)
        FreePokenavSubstruct(POKENAV_SUBSTRUCT_MON_LIST);

    FreePokenavSubstruct(POKENAV_SUBSTRUCT_CONDITION_GRAPH);
}

u8 ConditionGraphHandleDpadInput(struct PokenavSub11 *structPtr)
{
    struct PokenavSub18 *monListPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_MON_LIST);
    u8 ret = 0;

    if (JOY_HELD(DPAD_UP))
    {
        if (structPtr->searchMode == 0 || monListPtr->currIndex != 0)
        {
            PlaySE(SE_SELECT);
            ret = SwitchConditionSummaryIndex(1);
        }
    }
    else if (JOY_HELD(DPAD_DOWN))
    {
        if (structPtr->searchMode == 0 || monListPtr->currIndex < monListPtr->listCount - 1)
        {
            PlaySE(SE_SELECT);
            ret = SwitchConditionSummaryIndex(0);
        }
    }

    return ret;
}

u8 SwitchConditionSummaryIndex(u8 moveUp)
{
    u16 r7;
    bool8 wasNotLastMon, isNotLastMon;
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);
    struct PokenavSub18 *monListPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_MON_LIST);

    r7 = (moveUp) ? structPtr->unk6788 : structPtr->unk6787;
    sub_81D1F84(&structPtr->conditionData, structPtr->conditionData.unk14[structPtr->mark], structPtr->conditionData.unk14[r7]);
    wasNotLastMon = (monListPtr->currIndex != ((IsConditionMenuSearchMode() != 0) ? monListPtr->listCount : monListPtr->listCount - 1));
    if (moveUp)
    {
        structPtr->unk6788 = structPtr->unk6787;
        structPtr->unk6787 = structPtr->mark;
        structPtr->mark = r7;
        structPtr->unk6789 = structPtr->unk6788;

        monListPtr->currIndex = (monListPtr->currIndex == 0) ? monListPtr->listCount - 1 : monListPtr->currIndex - 1;
        structPtr->monIndex = (monListPtr->currIndex != 0) ? monListPtr->currIndex - 1 : monListPtr->listCount - 1;
    }
    else
    {
        structPtr->unk6787 = structPtr->unk6788;
        structPtr->unk6788 = structPtr->mark;
        structPtr->mark = r7;
        structPtr->unk6789 = structPtr->unk6787;

        monListPtr->currIndex = (monListPtr->currIndex < monListPtr->listCount - 1) ? monListPtr->currIndex + 1 : 0;
        structPtr->monIndex = (monListPtr->currIndex < monListPtr->listCount - 1) ? monListPtr->currIndex + 1 : 0;
    }

    isNotLastMon = (monListPtr->currIndex != ((IsConditionMenuSearchMode() != 0) ? monListPtr->listCount : monListPtr->listCount - 1));
    
    if (!wasNotLastMon)
        return PARTY_CONDITION_FUNC_NO_TRANSITION;
    else if (!isNotLastMon)
        return PARTY_CONDITION_FUNC_SLIDE_MON_OUT;
    else
        return PARTY_CONDITION_FUNC_SLIDE_MON_IN;
}

bool32 LoadPartyConditionMenuGfx(void)
{
    s32 var;
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);
    struct PokenavSub18 *monListPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_MON_LIST);

    switch (structPtr->state)
    {
    case 0:
        CopyMonNameGenderLocation(monListPtr->currIndex, 0);
        break;
    case 1:
        GetMonConditionGraphData(monListPtr->currIndex, 0);
        break;
    case 2:
        ConditionGraphDrawMonPic(monListPtr->currIndex, 0);
        break;
    case 3:
        if (monListPtr->listCount == 1)
        {
            structPtr->mark = 0;
            structPtr->unk6787 = 0;
            structPtr->unk6788 = 0;
            structPtr->state = 0;
            return TRUE;
        }
        else
        {
            structPtr->mark = 0;
            structPtr->unk6787 = 1;
            structPtr->unk6788 = 2;
        }
        break;
    // These were probably ternaries just like cases 7-9, but couldn't match it any other way.
    case 4:
        var = monListPtr->currIndex + 1;
        if (var >= monListPtr->listCount)
            var = 0;
        CopyMonNameGenderLocation(var, 1);
        break;
    case 5:
        var = monListPtr->currIndex + 1;
        if (var >= monListPtr->listCount)
            var = 0;
        GetMonConditionGraphData(var, 1);
        break;
    case 6:
        var = monListPtr->currIndex + 1;
        if (var >= monListPtr->listCount)
            var = 0;
        ConditionGraphDrawMonPic(var, 1);
        break;
    case 7:
        CopyMonNameGenderLocation((monListPtr->currIndex - 1 >= 0) ? monListPtr->currIndex - 1 : monListPtr->listCount - 1, 2);
        break;
    case 8:
        GetMonConditionGraphData((monListPtr->currIndex - 1 >= 0) ? monListPtr->currIndex - 1 : monListPtr->listCount - 1, 2);
        break;
    case 9:
        ConditionGraphDrawMonPic((monListPtr->currIndex - 1 >= 0) ? monListPtr->currIndex - 1 : monListPtr->listCount - 1, 2);
        structPtr->state = 0;
        return TRUE;
    }

    structPtr->state++;
    return FALSE;
}

bool32 SetConditionGraphData(u8 mode)
{
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);

    switch (mode)
    {
    case 0:
        CopyMonNameGenderLocation(structPtr->monIndex, structPtr->unk6789);
        break;
    case 1:
        GetMonConditionGraphData(structPtr->monIndex, structPtr->unk6789);
        break;
    case 2:
        ConditionGraphDrawMonPic(structPtr->monIndex, structPtr->unk6789);
        return TRUE;
    }

    return FALSE;
}

u8 *CopyStringLeftAlignedToConditionData(u8 *dst, const u8 *src, s16 n)
{
    while (*src != EOS)
        *dst++ = *src++, n--;

    while (n-- > 0)
        *dst++ = CHAR_SPACE;

    *dst = EOS;
    return dst;
}

u8 *CopyMonConditionNameGender(u8 *str, u16 id, bool8 arg3)
{
    u16 boxId, monId, gender, species, level, lvlDigits;
    struct BoxPokemon *boxMon;
    u8 *txtPtr, *str_;
    struct PokenavSub18 *monListPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_MON_LIST);

    boxId = monListPtr->monData[id].boxId;
    monId = monListPtr->monData[id].monId;
    *(str++) = EXT_CTRL_CODE_BEGIN;
    *(str++) = EXT_CTRL_CODE_COLOR_HIGHLIGHT_SHADOW;
    *(str++) = TEXT_COLOR_BLUE;
    *(str++) = TEXT_COLOR_TRANSPARENT;
    *(str++) = TEXT_COLOR_LIGHT_BLUE;

    if (GetBoxOrPartyMonData(boxId, monId, MON_DATA_IS_EGG, NULL))
        return StringCopyPadded(str, gText_EggNickname, CHAR_SPACE, 12);

    GetBoxOrPartyMonData(boxId, monId, MON_DATA_NICKNAME, str);
    StringGetEnd10(str);
    species = GetBoxOrPartyMonData(boxId, monId, MON_DATA_SPECIES, NULL);
    if (boxId == TOTAL_BOXES_COUNT)
    {
        level = GetMonData(&gPlayerParty[monId], MON_DATA_LEVEL);
        gender = GetMonGender(&gPlayerParty[monId]);
    }
    else
    {
        boxMon = GetBoxedMonPtr(boxId, monId);
        gender = GetBoxMonGender(boxMon);
        level = GetLevelFromBoxMonExp(boxMon);
    }

    if ((species == SPECIES_NIDORAN_F || species == SPECIES_NIDORAN_M) && !StringCompare(str, gSpeciesNames[species]))
        gender = MON_GENDERLESS;

    str_ = str; // For some reason, a variable is needed to match.
    while (*str_ != EOS)
        (str_++);

    *(str_++) = EXT_CTRL_CODE_BEGIN;
    *(str_++) = EXT_CTRL_CODE_SKIP;
    *(str_++) = 60;
    switch (gender)
    {
    default:
        *(str_++) = CHAR_UNK_SPACER;
        break;
    case MON_MALE:
        *(str_++) = EXT_CTRL_CODE_BEGIN;
        *(str_++) = EXT_CTRL_CODE_COLOR;
        *(str_++) = TEXT_COLOR_RED;
        *(str_++) = EXT_CTRL_CODE_BEGIN;
        *(str_++) = EXT_CTRL_CODE_SHADOW;
        *(str_++) = TEXT_COLOR_LIGHT_RED;
        *(str_++) = CHAR_MALE;
        break;
    case MON_FEMALE:
        *(str_++) = EXT_CTRL_CODE_BEGIN;
        *(str_++) = EXT_CTRL_CODE_COLOR;
        *(str_++) = TEXT_COLOR_GREEN;
        *(str_++) = EXT_CTRL_CODE_BEGIN;
        *(str_++) = EXT_CTRL_CODE_SHADOW;
        *(str_++) = TEXT_COLOR_LIGHT_GREEN;
        *(str_++) = CHAR_FEMALE;
        break;
    }

    *(str_++) = EXT_CTRL_CODE_BEGIN;
    *(str_++) = EXT_CTRL_CODE_COLOR_HIGHLIGHT_SHADOW;
    *(str_++) = TEXT_COLOR_BLUE;
    *(str_++) = TEXT_COLOR_TRANSPARENT;
    *(str_++) = TEXT_COLOR_LIGHT_BLUE;
    *(str_++) = CHAR_SLASH;
    *(str_++) = CHAR_EXTRA_SYMBOL;
    *(str_++) = CHAR_LV_2;
    txtPtr = str_;
    str_ = ConvertIntToDecimalStringN(str_, level, STR_CONV_MODE_LEFT_ALIGN, 3);
    lvlDigits = str_ - txtPtr;
    *(str_++) = CHAR_SPACE;
    if (!arg3)
    {
        lvlDigits = 3 - lvlDigits;
        while (lvlDigits-- != 0)
            *(str_++) = CHAR_SPACE;
    }

    *str_ = EOS;
    return str_;
}

void CopyMonNameGenderLocation(s16 id, u8 arg1)
{
    u16 boxId, i;
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);
    struct PokenavSub18 *monListPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_MON_LIST);

    if (id != (IsConditionMenuSearchMode() != 0 ? monListPtr->listCount : monListPtr->listCount - 1))
    {
        CopyMonConditionNameGender(structPtr->nameBuffer[arg1], id, FALSE);
        boxId = monListPtr->monData[id].boxId;
        structPtr->searchLocBuffer[arg1][0] = EXT_CTRL_CODE_BEGIN;
        structPtr->searchLocBuffer[arg1][1] = EXT_CTRL_CODE_COLOR_HIGHLIGHT_SHADOW;
        structPtr->searchLocBuffer[arg1][2] = TEXT_COLOR_BLUE;
        structPtr->searchLocBuffer[arg1][3] = TEXT_COLOR_TRANSPARENT;
        structPtr->searchLocBuffer[arg1][4] = TEXT_COLOR_LIGHT_BLUE;
        if (boxId == TOTAL_BOXES_COUNT)
            CopyStringLeftAlignedToConditionData(&structPtr->searchLocBuffer[arg1][5], gText_InParty, 8);
        else
            CopyStringLeftAlignedToConditionData(&structPtr->searchLocBuffer[arg1][5], GetBoxNamePtr(boxId), 8);
    }
    else
    {
        for (i = 0; i < 12; i++)
            structPtr->nameBuffer[arg1][i] = CHAR_SPACE;
        structPtr->nameBuffer[arg1][i] = EOS;

        for (i = 0; i < 8; i++)
            structPtr->searchLocBuffer[arg1][i] = CHAR_SPACE;
        structPtr->searchLocBuffer[arg1][i] = EOS;
    }
}

void InitPartyConditionListParameters(void)
{
    u16 i, count;
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);
    struct PokenavSub18 *monListPtr = AllocSubstruct(POKENAV_SUBSTRUCT_MON_LIST, sizeof(struct PokenavSub18));

    structPtr->searchMode = 0;
    for (i = 0, count = 0; i < CalculatePlayerPartyCount(); i++)
    {
        if (!GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG))
        {
            monListPtr->monData[count].boxId = TOTAL_BOXES_COUNT;
            monListPtr->monData[count].monId = i;
            monListPtr->monData[count].data = 0;
            count++;
        }
    }

    monListPtr->monData[count].boxId = 0;
    monListPtr->monData[count].monId = 0;
    monListPtr->monData[count].data = 0;
    monListPtr->currIndex = 0;
    monListPtr->listCount = count + 1;
    structPtr->state = 0;
}

void sub_81CD9F8(void)
{
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);
    structPtr->searchMode = 1;
    structPtr->state = 0;
}

void GetMonConditionGraphData(s16 id, u8 arg1)
{
    u16 boxId, monId, i;
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);
    struct PokenavSub18 *monListPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_MON_LIST);

    if (id != (IsConditionMenuSearchMode() != 0 ? monListPtr->listCount : monListPtr->listCount - 1))
    {
        boxId = monListPtr->monData[id].boxId;
        monId = monListPtr->monData[id].monId;
        structPtr->conditionData.stat[arg1][0] = GetBoxOrPartyMonData(boxId, monId, MON_DATA_COOL, NULL);
        structPtr->conditionData.stat[arg1][1] = GetBoxOrPartyMonData(boxId, monId, MON_DATA_TOUGH, NULL);
        structPtr->conditionData.stat[arg1][2] = GetBoxOrPartyMonData(boxId, monId, MON_DATA_SMART, NULL);
        structPtr->conditionData.stat[arg1][3] = GetBoxOrPartyMonData(boxId, monId, MON_DATA_CUTE, NULL);
        structPtr->conditionData.stat[arg1][4] = GetBoxOrPartyMonData(boxId, monId, MON_DATA_BEAUTY, NULL);
        structPtr->sheen[arg1] = (GetBoxOrPartyMonData(boxId, monId, MON_DATA_SHEEN, NULL) != 255)
                                 ? GetBoxOrPartyMonData(boxId, monId, MON_DATA_SHEEN, NULL) / 29u
                                 : 9;
        structPtr->monMarks[arg1] = GetBoxOrPartyMonData(boxId, monId, MON_DATA_MARKINGS, NULL);
        sub_81D2754(structPtr->conditionData.stat[arg1], structPtr->conditionData.unk14[arg1]);
    }
    else
    {
        for (i = 0; i < FLAVOR_COUNT; i++)
        {
            structPtr->conditionData.stat[arg1][i] = 0;
            structPtr->conditionData.unk14[arg1][i].unk0 = 155;
            structPtr->conditionData.unk14[arg1][i].unk2 = 91;
        }
    }
}

void ConditionGraphDrawMonPic(s16 index, u8 arg1)
{
    u16 boxId, monId, species;
    u32 personality, tid;
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);
    struct PokenavSub18 *monListPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_MON_LIST);

    if (index == (IsConditionMenuSearchMode() != 0 ? monListPtr->listCount : monListPtr->listCount - 1))
        return;

    boxId = monListPtr->monData[index].boxId;
    monId = monListPtr->monData[index].monId;
    species = GetBoxOrPartyMonData(boxId, monId, MON_DATA_SPECIES2, NULL);
    tid = GetBoxOrPartyMonData(boxId, monId, MON_DATA_OT_ID, NULL);
    personality = GetBoxOrPartyMonData(boxId, monId, MON_DATA_PERSONALITY, NULL);
    LoadSpecialPokePic(&gMonFrontPicTable[species], structPtr->monPicGfx[arg1], species, personality, TRUE);
    LZ77UnCompWram(GetMonSpritePalFromSpeciesAndPersonality(species, tid, personality), structPtr->monPal[arg1]);
}

u16 GetMonListCount(void)
{
    struct PokenavSub18 *monListPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_MON_LIST);
    return monListPtr->listCount;
}

u16 GetConditionGraphCurrentMonIndex(void)
{
    struct PokenavSub18 *monListPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_MON_LIST);
    return monListPtr->currIndex;
}

struct ConditionGraph *GetConditionGraphDataPtr(void)
{
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);
    return &structPtr->conditionData;
}

u8 GetMonMarkIndex(void)
{
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);
    return structPtr->mark;
}

u8 sub_81CDC9C(void)
{
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);
    return structPtr->monIndex;
}

void *GetConditionMonPicGfx(u8 id)
{
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);
    return structPtr->monPicGfx[id];
}

void *GetConditionMonPal(u8 id)
{
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);
    return structPtr->monPal[id];
}

u8 sub_81CDCEC(void)
{
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);
    return structPtr->unk6789;
}

u8 *GetConditionMonNameBuffer(u8 id)
{
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);
    return structPtr->nameBuffer[id];
}

u8 *GetConditionMonLocationBuffer(u8 id)
{
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);
    return structPtr->searchLocBuffer[id];
}

u16 GetConditionMonDataBuffer(void)
{
    struct PokenavSub18 *monListPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_MON_LIST);
    return monListPtr->monData[monListPtr->currIndex].data;
}

bool32 IsConditionMenuSearchMode(void)
{
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);
    if (structPtr->searchMode == 1)
        return TRUE;
    else
        return FALSE;
}

u8 TryGetMonMarkId(void)
{
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);
    if (structPtr->searchMode == 1)
        return structPtr->monMarks[structPtr->mark];
    else
        return 0;
}

u8 GetMonSheen(void)
{
    struct PokenavSub11 *structPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH);
    return structPtr->sheen[structPtr->mark];
}
