#include <unordered_map>
#include "static_data.h"
#include <spdlog/spdlog.h>

namespace Rando {

std::unordered_map<uint32_t, CustomMessage> StaticData::hintTypeNames = {
    { HINT_TYPE_HINT_KEY, CustomMessage("Message") },
    { HINT_TYPE_AREA, CustomMessage("Area") },
    { HINT_TYPE_ITEM, CustomMessage("Item") },
    { HINT_TYPE_TRIAL, CustomMessage("Trial") },
    { HINT_TYPE_ENTRANCE, CustomMessage("Entrance") },
    { HINT_TYPE_ITEM_AREA, CustomMessage("Item Area") },
    { HINT_TYPE_ALTAR_CHILD, CustomMessage("Child Altar") },
    { HINT_TYPE_ALTAR_ADULT, CustomMessage("Adult Altar") },
    { HINT_TYPE_WOTH, CustomMessage("Way of the Hero") },
    { HINT_TYPE_FOOLISH, CustomMessage("Foolish") },
    { HINT_TYPE_MESSAGE, CustomMessage("Hardcoded Message") }
};

// RANDOTODO When dynamic grotto check names are done, apply it to these hints
// RANDOTODO Translations
std::unordered_map<uint32_t, CustomMessage> StaticData::hintNames = {
    { RH_NONE, CustomMessage("ERROR HINT") },
    { RH_KF_DEKU_TREE_LEFT_GOSSIP_STONE,
      CustomMessage("KF Left Near Deku Gossip Stone") }, // RANDOTODO find cardinal direction
    { RH_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, CustomMessage("KF Right Near Deku Gossip Stone") },
    { RH_KF_GOSSIP_STONE, CustomMessage("KF Gossip Stone") },
    { RH_KF_STORMS_GROTTO_GOSSIP_STONE, CustomMessage("KF Storms Grotto Gossip Stone") },
    { RH_LW_GOSSIP_STONE, CustomMessage("LW Gossip Stone") },
    { RH_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, CustomMessage("LW Near Shortcuts Grotto Gossip Stone") },
    { RH_SFM_MAZE_NEAR_LW_GOSSIP_STONE, CustomMessage("SFM Near LW Gossip Stone") },
    { RH_SFM_MAZE_CENTER_GOSSIP_STONE, CustomMessage("SFM Center Gossip Stone") },
    { RH_SFM_SARIA_GOSSIP_STONE, CustomMessage("SFM Near Saria Gossip Stone") },
    { RH_HF_COW_GROTTO_GOSSIP_STONE, CustomMessage("HF Cow Grotto Gossip Stone") },
    { RH_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, CustomMessage("HF Near Market Grotto Gossip Stone") },
    { RH_HF_OPEN_GROTTO_GOSSIP_STONE, CustomMessage("HF Open Grotto Gossip Stone") },
    { RH_HF_SOUTHEAST_GROTTO_GOSSIP_STONE, CustomMessage("HF Southeast Grotto Gossip Stone") },
    { RH_TOT_LEFT_CENTER_GOSSIP_STONE, CustomMessage("Market Left Center Gossip Stone") },
    { RH_TOT_LEFTMOST_GOSSIP_STONE, CustomMessage("Market Leftmost Center Gossip Stone") },
    { RH_TOT_RIGHT_CENTER_GOSSIP_STONE, CustomMessage("Market Right Center Gossip Stone") },
    { RH_TOT_RIGHTMOST_GOSSIP_STONE, CustomMessage("Market Rightmost Gossip Stone") },
    { RH_HC_MALON_GOSSIP_STONE, CustomMessage("HC Near Malon Gossip Stone") },
    { RH_HC_ROCK_WALL_GOSSIP_STONE, CustomMessage("HC Rock Wall Gossip Stone") },
    { RH_HC_STORMS_GROTTO_GOSSIP_STONE, CustomMessage("HC Storm Grotto Gossip Stone") },
    { RH_KAK_OPEN_GROTTO_GOSSIP_STONE, CustomMessage("Kak Open Grotto Gossip Stone") },
    { RH_GRAVEYARD_GOSSIP_STONE, CustomMessage("Graveyard Gossip Stone") },
    { RH_DMT_GOSSIP_STONE, CustomMessage("DMT Gossip Stone") },
    { RH_DMT_STORMS_GROTTO_GOSSIP_STONE, CustomMessage("DMT Storms Grotto Gossip Stone") },
    { RH_GC_MAZE_GOSSIP_STONE, CustomMessage("GC Maze Gossip Stone") },
    { RH_GC_MEDIGORON_GOSSIP_STONE, CustomMessage("GC Medigoron Gossip Stone") },
    { RH_DMC_GOSSIP_STONE, CustomMessage("DMC Gossip Stone") },
    { RH_DMC_UPPER_GROTTO_GOSSIP_STONE, CustomMessage("DMC Upper Grotto Gossip Stone") },
    { RH_ZR_NEAR_DOMAIN_GOSSIP_STONE, CustomMessage("ZR Near Domain Gossip Stone") },
    { RH_ZR_NEAR_GROTTOS_GOSSIP_STONE, CustomMessage("ZR Near Grottos Gossip Stone") },
    { RH_ZR_OPEN_GROTTO_GOSSIP_STONE, CustomMessage("ZR Open Grotto Gossip Stone") },
    { RH_ZD_GOSSIP_STONE, CustomMessage("ZD Gossip Stone") },
    { RH_ZF_JABU_GOSSIP_STONE, CustomMessage("ZF Near Jabu Gossip Stone") },
    { RH_ZF_FAIRY_GOSSIP_STONE, CustomMessage("ZF Near Fairy Gossip Stone") },
    { RH_LH_LAB_GOSSIP_STONE, CustomMessage("LH Near Lab Gossip Stone") },
    { RH_LH_SOUTHEAST_GOSSIP_STONE, CustomMessage("LH Southeast Gossip Stone") },
    { RH_LH_SOUTHWEST_GOSSIP_STONE, CustomMessage("LH Southwest Gossip Stone") },
    { RH_GV_GOSSIP_STONE, CustomMessage("Gerudo Valley Gossip Stone") },
    { RH_COLOSSUS_GOSSIP_STONE, CustomMessage("Desert Colossus Gossip Stone") },
    { RH_DODONGOS_CAVERN_GOSSIP_STONE, CustomMessage("Dodongo's Cavern Gossip Stone") },
    { RH_GANONDORF_HINT, CustomMessage("Ganondorf Hint") },
    { RH_GANONDORF_JOKE, CustomMessage("Ganondorf Joke") },
    { RH_SHEIK_HINT, CustomMessage("Sheik in Ganons Castle Hint") },
    { RH_DAMPES_DIARY, CustomMessage("Dampe's Diary Hint") },
    { RH_GREG_RUPEE, CustomMessage("Treasure Chest Game Greg Hint") },
    { RH_ALTAR_CHILD, CustomMessage("ToT Altar as Child") },
    { RH_ALTAR_ADULT, CustomMessage("ToT Altar as Adult") },
    { RH_FOREST_BOSS_KEY_HINT, CustomMessage("Forest Temple Boss Key Hint") },
    { RH_FIRE_BOSS_KEY_HINT, CustomMessage("Fire Temple Boss Key Hint") },
    { RH_WATER_BOSS_KEY_HINT, CustomMessage("Water Temple Boss Key Hint") },
    { RH_SPIRIT_BOSS_KEY_HINT, CustomMessage("Spirit Temple Boss Key Hint") },
    { RH_SHADOW_BOSS_KEY_HINT, CustomMessage("Shadow Temple Boss Key Hint") },
    { RH_GANONS_BOSS_KEY_HINT, CustomMessage("Ganon's Boss Key Hint") },
    { RH_SARIA_HINT, CustomMessage("Saria's Magic Hint") },
    { RH_MIDO_HINT, CustomMessage("Mido's Kokiri Sword Hint") },
    { RH_LOACH_HINT, CustomMessage("Loach Hint") },
    { RH_FISHING_POLE, CustomMessage("Fishing Pole Hint") },
    { RH_MINUET_WARP_LOC, CustomMessage("Minuet of Forest Destination") },
    { RH_BOLERO_WARP_LOC, CustomMessage("Bolero of Fire Destination") },
    { RH_SERENADE_WARP_LOC, CustomMessage("Serenade of Water Destination") },
    { RH_REQUIEM_WARP_LOC, CustomMessage("Requiem of Spirit Destination") },
    { RH_NOCTURNE_WARP_LOC, CustomMessage("Nocturne of Shadow Destination") },
    { RH_PRELUDE_WARP_LOC, CustomMessage("Prelude of Light Destination") },
    { RH_HBA_HINT, CustomMessage("Horseback Archery Hint") },
    { RH_MALON_HINT, CustomMessage("Malon Hint") },
    { RH_CHICKENS_HINT, CustomMessage("Anju's Child Chickens Hint") },
    { RH_BIG_POES_HINT, CustomMessage("Big Poe Reward Hint") },
    { RH_BIGGORON_HINT, CustomMessage("Biggoron Claim Check Hint") },
    { RH_FROGS_HINT, CustomMessage("Final Frogs in River Hint") },
    { RH_OOT_HINT, CustomMessage("Sheik in Temple of Time Hint") },
    { RH_MASK_SHOP_HINT, CustomMessage("Mask Shop Hint") },
};

std::unordered_map<RandomizerCheck, RandomizerHint> StaticData::gossipStoneCheckToHint{
    { RC_COLOSSUS_GOSSIP_STONE, RH_COLOSSUS_GOSSIP_STONE },
    { RC_DMC_GOSSIP_STONE, RH_DMC_GOSSIP_STONE },
    { RC_DMC_UPPER_GROTTO_GOSSIP_STONE, RH_DMC_UPPER_GROTTO_GOSSIP_STONE },
    { RC_DMT_GOSSIP_STONE, RH_DMT_GOSSIP_STONE },
    { RC_DMT_STORMS_GROTTO_GOSSIP_STONE, RH_DMT_STORMS_GROTTO_GOSSIP_STONE },
    { RC_DODONGOS_CAVERN_GOSSIP_STONE, RH_DODONGOS_CAVERN_GOSSIP_STONE },
    { RC_ZF_FAIRY_GOSSIP_STONE, RH_ZF_FAIRY_GOSSIP_STONE },
    { RC_GC_MAZE_GOSSIP_STONE, RH_GC_MAZE_GOSSIP_STONE },
    { RC_GC_MEDIGORON_GOSSIP_STONE, RH_GC_MEDIGORON_GOSSIP_STONE },
    { RC_GV_GOSSIP_STONE, RH_GV_GOSSIP_STONE },
    { RC_GRAVEYARD_GOSSIP_STONE, RH_GRAVEYARD_GOSSIP_STONE },
    { RC_HC_MALON_GOSSIP_STONE, RH_HC_MALON_GOSSIP_STONE },
    { RC_HC_ROCK_WALL_GOSSIP_STONE, RH_HC_ROCK_WALL_GOSSIP_STONE },
    { RC_HC_STORMS_GROTTO_GOSSIP_STONE, RH_HC_STORMS_GROTTO_GOSSIP_STONE },
    { RC_HF_COW_GROTTO_GOSSIP_STONE, RH_HF_COW_GROTTO_GOSSIP_STONE },
    { RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, RH_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE },
    { RC_HF_OPEN_GROTTO_GOSSIP_STONE, RH_HF_OPEN_GROTTO_GOSSIP_STONE },
    { RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE, RH_HF_SOUTHEAST_GROTTO_GOSSIP_STONE },
    { RC_ZF_JABU_GOSSIP_STONE, RH_ZF_JABU_GOSSIP_STONE },
    { RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE, RH_KF_DEKU_TREE_LEFT_GOSSIP_STONE },
    { RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, RH_KF_DEKU_TREE_RIGHT_GOSSIP_STONE },
    { RC_KF_GOSSIP_STONE, RH_KF_GOSSIP_STONE },
    { RC_KF_STORMS_GROTTO_GOSSIP_STONE, RH_KF_STORMS_GROTTO_GOSSIP_STONE },
    { RC_KAK_OPEN_GROTTO_GOSSIP_STONE, RH_KAK_OPEN_GROTTO_GOSSIP_STONE },
    { RC_LH_LAB_GOSSIP_STONE, RH_LH_LAB_GOSSIP_STONE },
    { RC_LH_SOUTHEAST_GOSSIP_STONE, RH_LH_SOUTHEAST_GOSSIP_STONE },
    { RC_LH_SOUTHWEST_GOSSIP_STONE, RH_LH_SOUTHWEST_GOSSIP_STONE },
    { RC_LW_GOSSIP_STONE, RH_LW_GOSSIP_STONE },
    { RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, RH_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE },
    { RC_SFM_MAZE_LOWER_GOSSIP_STONE, RH_SFM_MAZE_NEAR_LW_GOSSIP_STONE },
    { RC_SFM_MAZE_UPPER_GOSSIP_STONE, RH_SFM_MAZE_CENTER_GOSSIP_STONE },
    { RC_SFM_SARIA_GOSSIP_STONE, RH_SFM_SARIA_GOSSIP_STONE },
    { RC_TOT_LEFT_CENTER_GOSSIP_STONE, RH_TOT_LEFT_CENTER_GOSSIP_STONE },
    { RC_TOT_LEFTMOST_GOSSIP_STONE, RH_TOT_LEFTMOST_GOSSIP_STONE },
    { RC_TOT_RIGHT_CENTER_GOSSIP_STONE, RH_TOT_RIGHT_CENTER_GOSSIP_STONE },
    { RC_TOT_RIGHTMOST_GOSSIP_STONE, RH_TOT_RIGHTMOST_GOSSIP_STONE },
    { RC_ZD_GOSSIP_STONE, RH_ZD_GOSSIP_STONE },
    { RC_ZR_NEAR_DOMAIN_GOSSIP_STONE, RH_ZR_NEAR_DOMAIN_GOSSIP_STONE },
    { RC_ZR_NEAR_GROTTOS_GOSSIP_STONE, RH_ZR_NEAR_GROTTOS_GOSSIP_STONE },
    { RC_ZR_OPEN_GROTTO_GOSSIP_STONE, RH_ZR_OPEN_GROTTO_GOSSIP_STONE }
};

std::unordered_map<uint32_t, RandomizerHintTextKey> StaticData::areaNames = {
    // RANDOTODO resolve None in area
    { RA_NONE, RHT_ISOLATED_PLACE }, // explicit none in area hints means we're disconnected
    { RA_LINKS_POCKET, RHT_LINKS_POCKET },
    { RA_KOKIRI_FOREST, RHT_KOKIRI_FOREST },
    { RA_THE_LOST_WOODS, RHT_THE_LOST_WOODS },
    { RA_SACRED_FOREST_MEADOW, RHT_SACRED_FOREST_MEADOW },
    { RA_HYRULE_FIELD, RHT_HYRULE_FIELD },
    { RA_LAKE_HYLIA, RHT_LAKE_HYLIA },
    { RA_GERUDO_VALLEY, RHT_GERUDO_VALLEY },
    { RA_GERUDO_FORTRESS, RHT_GERUDO_FORTRESS },
    { RA_HAUNTED_WASTELAND, RHT_HAUNTED_WASTELAND },
    { RA_DESERT_COLOSSUS, RHT_DESERT_COLOSSUS },
    { RA_THE_MARKET, RHT_THE_MARKET },
    { RA_TEMPLE_OF_TIME, RHT_TEMPLE_OF_TIME },
    { RA_HYRULE_CASTLE, RHT_HYRULE_CASTLE },
    { RA_OUTSIDE_GANONS_CASTLE, RHT_OUTSIDE_GANONS_CASTLE },
    { RA_CASTLE_GROUNDS, RHT_CASTLE_GROUNDS },
    { RA_KAKARIKO_VILLAGE, RHT_KAKARIKO_VILLAGE },
    { RA_THE_GRAVEYARD, RHT_THE_GRAVEYARD },
    { RA_DEATH_MOUNTAIN_TRAIL, RHT_DEATH_MOUNTAIN_TRAIL },
    { RA_GORON_CITY, RHT_GORON_CITY },
    { RA_DEATH_MOUNTAIN_CRATER, RHT_DEATH_MOUNTAIN_CRATER },
    { RA_ZORAS_RIVER, RHT_ZORAS_RIVER },
    { RA_ZORAS_DOMAIN, RHT_ZORAS_DOMAIN },
    { RA_ZORAS_FOUNTAIN, RHT_ZORAS_FOUNTAIN },
    { RA_LON_LON_RANCH, RHT_LON_LON_RANCH },
    { RA_DEKU_TREE, RHT_DEKU_TREE },
    { RA_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN },
    { RA_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY },
    { RA_FOREST_TEMPLE, RHT_FOREST_TEMPLE },
    { RA_FIRE_TEMPLE, RHT_FIRE_TEMPLE },
    { RA_WATER_TEMPLE, RHT_WATER_TEMPLE },
    { RA_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE },
    { RA_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE },
    { RA_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL },
    { RA_ICE_CAVERN, RHT_ICE_CAVERN },
    { RA_GERUDO_TRAINING_GROUND, RHT_GERUDO_TRAINING_GROUND },
    { RA_GANONS_CASTLE, RHT_GANONS_CASTLE },
};

std::unordered_map<uint32_t, RandomizerHintTextKey> StaticData::trialData = {
    { TK_LIGHT_TRIAL, RHT_LIGHT_TRIAL }, { TK_FOREST_TRIAL, RHT_FOREST_TRIAL }, { TK_FIRE_TRIAL, RHT_FIRE_TRIAL },
    { TK_WATER_TRIAL, RHT_WATER_TRIAL }, { TK_SHADOW_TRIAL, RHT_SHADOW_TRIAL }, { TK_SPIRIT_TRIAL, RHT_SPIRIT_TRIAL },
};

std::unordered_map<RandomizerHint, StaticHintInfo> StaticData::staticHintInfoMap = {
    // clang-format off
  // RH_GANONDORF_HINT is special cased due to being different based on master sword shuffle
  // Altar hints are special cased due to special hint marking rules
  // warp song hints are special cased due to entrances not being done properly yet
  // Ganondorf Joke is special cased as the text is random
  {RH_SHEIK_HINT,           StaticHintInfo(HINT_TYPE_AREA,     {RHT_SHEIK_HINT_LA_ONLY},            RSK_SHEIK_LA_HINT,       true, {}, {RG_LIGHT_ARROWS},            {RC_SHEIK_HINT_GC, RC_SHEIK_HINT_MQ_GC}, true)},
  {RH_FOREST_BOSS_KEY_HINT, StaticHintInfo(HINT_TYPE_AREA,     {RHT_BOSS_KEY_HINT},                 RSK_BOSS_KEY_HINT,       true, {}, {RG_FOREST_TEMPLE_BOSS_KEY},  {RC_FOREST_BOSS_KEY_HINT}, true)},
  {RH_FIRE_BOSS_KEY_HINT,   StaticHintInfo(HINT_TYPE_AREA,     {RHT_BOSS_KEY_HINT},                 RSK_BOSS_KEY_HINT,       true, {}, {RG_FIRE_TEMPLE_BOSS_KEY},    {RC_FIRE_BOSS_KEY_HINT}, true)},
  {RH_WATER_BOSS_KEY_HINT,  StaticHintInfo(HINT_TYPE_AREA,     {RHT_BOSS_KEY_HINT},                 RSK_BOSS_KEY_HINT,       true, {}, {RG_WATER_TEMPLE_BOSS_KEY},   {RC_WATER_BOSS_KEY_HINT}, true)},
  {RH_SPIRIT_BOSS_KEY_HINT, StaticHintInfo(HINT_TYPE_AREA,     {RHT_BOSS_KEY_HINT},                 RSK_BOSS_KEY_HINT,       true, {}, {RG_SPIRIT_TEMPLE_BOSS_KEY},  {RC_SPIRIT_BOSS_KEY_HINT}, true)},
  {RH_SHADOW_BOSS_KEY_HINT, StaticHintInfo(HINT_TYPE_AREA,     {RHT_BOSS_KEY_HINT},                 RSK_BOSS_KEY_HINT,       true, {}, {RG_SHADOW_TEMPLE_BOSS_KEY},  {RC_SHADOW_BOSS_KEY_HINT}, true)},
  {RH_GANONS_BOSS_KEY_HINT, StaticHintInfo(HINT_TYPE_AREA,     {RHT_BOSS_KEY_HINT},                 RSK_BOSS_KEY_HINT,       true, {}, {RG_GANONS_CASTLE_BOSS_KEY},  {RC_GANONS_BOSS_KEY_HINT}, true)},
  {RH_DAMPES_DIARY,         StaticHintInfo(HINT_TYPE_AREA,     {RHT_DAMPE_DIARY},                   RSK_DAMPES_DIARY_HINT,   true, {}, {RG_PROGRESSIVE_HOOKSHOT},    {RC_DAMPE_HINT})},
  {RH_GREG_RUPEE,           StaticHintInfo(HINT_TYPE_AREA,     {RHT_GREG_HINT},                     RSK_GREG_HINT,           true, {}, {RG_GREG_RUPEE},              {RC_GREG_HINT})},
  {RH_SARIA_HINT,           StaticHintInfo(HINT_TYPE_AREA,     {RHT_SARIA_TALK_HINT, RHT_SARIA_SONG_HINT}, RSK_SARIA_HINT,   true, {}, {RG_PROGRESSIVE_MAGIC_METER}, {RC_SARIA_SONG_HINT, RC_SONG_FROM_SARIA}, true)},
  {RH_MIDO_HINT,            StaticHintInfo(HINT_TYPE_AREA,     {RHT_MIDO_HINT},                     RSK_MIDO_HINT,           true, {}, {RG_KOKIRI_SWORD},            {RC_MIDO_HINT}, true)},
  {RH_LOACH_HINT,           StaticHintInfo(HINT_TYPE_ITEM,     {RHT_LOACH_HINT},                    RSK_LOACH_HINT,          true, {RC_LH_HYRULE_LOACH})},
  {RH_FISHING_POLE,         StaticHintInfo(HINT_TYPE_AREA,     {RHT_FISHING_POLE_HINT},             RSK_FISHING_POLE_HINT,   true, {}, {RG_FISHING_POLE},            {RC_FISHING_POLE_HINT}, true)},
  {RH_HBA_HINT,             StaticHintInfo(HINT_TYPE_ITEM,     {RHT_HBA_HINT_SIGN, RHT_HBA_HINT_NOT_ON_HORSE, RHT_HBA_HINT_INITIAL, RHT_HBA_HINT_HAVE_1000}, RSK_HBA_HINT, true, {RC_GF_HBA_1000_POINTS, RC_GF_HBA_1500_POINTS})},
  {RH_MALON_HINT,           StaticHintInfo(HINT_TYPE_ITEM,     {RHT_MALON_HINT_TURNING_EVIL, RHT_MALON_HINT_HOW_IS_EPONA, RHT_MALON_HINT_OBSTICLE_COURSE, RHT_MALON_HINT_INGO_TEMPTED}, RSK_MALON_HINT, true, {RC_KF_LINKS_HOUSE_COW})},
  {RH_BIG_POES_HINT,        StaticHintInfo(HINT_TYPE_ITEM,     {RHT_BIG_POES_HINT},                 RSK_BIG_POES_HINT,       true, {RC_MARKET_10_BIG_POES})},
  {RH_CHICKENS_HINT,        StaticHintInfo(HINT_TYPE_ITEM,     {RHT_CHICKENS_HINT},                 RSK_CHICKENS_HINT,       true, {RC_KAK_ANJU_AS_CHILD})},
  {RH_BIGGORON_HINT,        StaticHintInfo(HINT_TYPE_ITEM,     {RHT_BIGGORON_HINT},                 RSK_BIGGORON_HINT,       true, {RC_DMT_TRADE_CLAIM_CHECK},                                  {}, {RC_BIGGORON_HINT})},
  {RH_FROGS_HINT,           StaticHintInfo(HINT_TYPE_ITEM,     {RHT_FROGS_HINT},                    RSK_FROGS_HINT,          true, {RC_ZR_FROGS_OCARINA_GAME})},
  {RH_OOT_HINT,             StaticHintInfo(HINT_TYPE_ITEM,     {RHT_OOT_HINT},                      RSK_OOT_HINT,            true, {RC_HF_OCARINA_OF_TIME_ITEM, RC_SONG_FROM_OCARINA_OF_TIME},  {}, {RC_TOT_SHEIK_HINT})},
  {RH_MASK_SHOP_HINT,       StaticHintInfo(HINT_TYPE_ITEM,     {RHT_MASK_SHOP_HINT},                RSK_MASK_SHOP_HINT,      true, {RC_DEKU_THEATER_SKULL_MASK, RC_DEKU_THEATER_MASK_OF_TRUTH}, {}, {RC_MASK_SHOP_HINT})},
    // clang-format on
};

std::unordered_map<std::string, uint32_t>
StaticData::PopulateTranslationMap(const std::unordered_map<uint32_t, CustomMessage>& input) {
    std::unordered_map<std::string, uint32_t> output = {};
    for (const auto& [key, message] : input) {
        std::vector<std::string> strings = message.GetAllMessages(MF_CLEAN);
        for (const std::string& string : strings) {
            if (output.contains(string)) {
                if (output[string] != key) {
                    // RANDOTODO should this cause an error of some kind?
                    SPDLOG_DEBUG("REPEATED STRING IN " + message.GetEnglish(MF_CLEAN));
                }
            } else {
                output[string] = key;
            }
        }
    }
    return output;
}

std::unordered_map<std::string, uint32_t>
StaticData::PopulateTranslationMap(const std::unordered_map<uint32_t, RandomizerHintTextKey>& input) {
    std::unordered_map<std::string, uint32_t> output = {};
    for (const auto& [key, text] : input) {
        std::vector<std::string> strings = hintTextTable[text].GetClear().GetAllMessages(MF_CLEAN);
        for (const std::string& string : strings) {
            if (output.contains(string)) {
                if (output[string] != key) {
                    // RANDOTODO should this cause an error of some kind?
                    SPDLOG_DEBUG("REPEATED STRING WITH " + string);
                }
            } else {
                output[string] = key;
            }
        }
    }
    return output;
}

std::unordered_map<std::string, uint32_t> StaticData::hintNameToEnum = {};
std::unordered_map<std::string, uint32_t> StaticData::hintTypeNameToEnum = {};
std::unordered_map<std::string, uint32_t> StaticData::areaNameToEnum = {};
std::unordered_map<std::string, uint32_t> StaticData::trialNameToEnum = {};
std::unordered_map<std::string, RandomizerSettingKey> StaticData::optionNameToEnum = {};
std::unordered_map<std::string, RandomizerCheck>
    StaticData::locationNameToEnum = {}; // is filled in context based on location table

std::unordered_map<u32, RandomizerHint> StaticData::stoneParamsToHint{
    { 0x1, RH_ZF_FAIRY_GOSSIP_STONE },
    { 0x2, RH_ZF_JABU_GOSSIP_STONE },
    { 0x3, RH_LH_LAB_GOSSIP_STONE },
    { 0x4, RH_DMT_GOSSIP_STONE },
    { 0x5, RH_DMC_GOSSIP_STONE },
    { 0x6, RH_TOT_LEFTMOST_GOSSIP_STONE },
    { 0x7, RH_TOT_LEFT_CENTER_GOSSIP_STONE },
    { 0x8, RH_LH_SOUTHWEST_GOSSIP_STONE },
    { 0x9, RH_ZD_GOSSIP_STONE },
    { 0xA, RH_GRAVEYARD_GOSSIP_STONE },
    { 0xB, RH_HC_ROCK_WALL_GOSSIP_STONE },
    { 0xC, RH_ZR_NEAR_DOMAIN_GOSSIP_STONE },
    { 0xD, RH_ZR_NEAR_GROTTOS_GOSSIP_STONE },
    { 0xE, RH_TOT_RIGHT_CENTER_GOSSIP_STONE },
    { 0xF, RH_LH_SOUTHEAST_GOSSIP_STONE },
    { 0x10, RH_TOT_RIGHTMOST_GOSSIP_STONE },
    { 0x11, RH_GV_GOSSIP_STONE },
    { 0x12, RH_HC_MALON_GOSSIP_STONE },
    { 0x13, RH_HC_STORMS_GROTTO_GOSSIP_STONE },
    { 0x14, RH_DODONGOS_CAVERN_GOSSIP_STONE },
    { 0x15, RH_GC_MAZE_GOSSIP_STONE },
    { 0x16, RH_SFM_MAZE_NEAR_LW_GOSSIP_STONE },
    { 0x17, RH_SFM_MAZE_CENTER_GOSSIP_STONE },
    // generic grottos all use 0x18, grottoChestParamsToHint is used for conversion
    { 0x19, RH_GC_MEDIGORON_GOSSIP_STONE },
    { 0x1A, RH_COLOSSUS_GOSSIP_STONE },
    { 0x1B, RH_HF_COW_GROTTO_GOSSIP_STONE },
    { 0x1C, RH_SFM_SARIA_GOSSIP_STONE },
    { 0x1D, RH_LW_GOSSIP_STONE },
    { 0x1E, RH_KF_GOSSIP_STONE },
    { 0x1F, RH_KF_DEKU_TREE_LEFT_GOSSIP_STONE },
    { 0x20, RH_KF_DEKU_TREE_RIGHT_GOSSIP_STONE },
};

std::unordered_map<u32, RandomizerHint> StaticData::grottoChestParamsToHint{
    { 22944, RH_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE }, { 22978, RH_HF_SOUTHEAST_GROTTO_GOSSIP_STONE },
    { 22947, RH_HF_OPEN_GROTTO_GOSSIP_STONE },        { 22964, RH_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE },
    { 23255, RH_DMT_STORMS_GROTTO_GOSSIP_STONE },     { 22984, RH_KAK_OPEN_GROTTO_GOSSIP_STONE },
    { 22985, RH_ZR_OPEN_GROTTO_GOSSIP_STONE },        { 23802, RH_DMC_UPPER_GROTTO_GOSSIP_STONE },
    { 22988, RH_KF_STORMS_GROTTO_GOSSIP_STONE },
};

// preexisting entries are for compatibility with Copper Charlie and should not be updated
std::unordered_map<std::string, RandomizerTrick> StaticData::trickToEnum = {
    { "1", RT_GROTTOS_WITHOUT_AGONY },
    { "2", RT_FEWER_TUNIC_REQUIREMENTS },
    { "3", RT_VISIBLE_COLLISION },
    { "4", RT_FIRE_RINGS },
    { "6", RT_DAMAGE_BOOST_SIMPLE },
    { "7", RT_HOVER_BOOST_SIMPLE },
    { "8", RT_BOMBCHU_BEEHIVES },
    { "9", RT_BLUE_FIRE_MUD_WALLS },
    { "10", RT_OPEN_UNDERWATER_CHEST },
    { "11", RT_ITEM_EXTENSION },
    { "12", RT_KF_ADULT_GS },
    { "13", RT_LW_BRIDGE },
    { "14", RT_LW_MIDO_BACKFLIP },
    { "15", RT_LW_GS_BEAN },
    { "16", RT_HC_STORMS_GS },
    { "17", RT_HF_BIG_POE_WITHOUT_EPONA },
    { "19", RT_KAK_TOWER_GS },
    { "21", RT_KAK_CHILD_WINDMILL_POH },
    { "22", RT_KAK_ROOFTOP_GS },
    { "23", RT_GY_POH },
    { "24", RT_GY_CHILD_DAMPE_RACE_POH },
    { "25", RT_GY_SHADOW_FIRE_ARROWS },
    { "26", RT_DMT_SOIL_GS },
    { "27", RT_DMT_BOMBABLE },
    { "28", RT_DMT_HOVERS_LOWER_GS },
    { "29", RT_DMT_BEAN_LOWER_GS },
    { "30", RT_DMT_JS_LOWER_GS },
    { "31", RT_DMT_CLIMB_HOVERS },
    { "32", RT_DMT_UPPER_GS },
    { "34", RT_GC_POT },
    { "35", RT_GC_POT_STRENGTH },
    { "36", RT_GC_ROLLING_STRENGTH },
    { "37", RT_GC_LEFTMOST },
    { "38", RT_GC_GROTTO },
    { "39", RT_GC_LINK_GORON_DINS },
    { "40", RT_DMC_HOVER_BEAN_POH },
    { "41", RT_DMC_BOLERO_JUMP },
    { "42", RT_DMC_BOULDER_JS },
    { "43", RT_DMC_BOULDER_SKIP },
    { "44", RT_ZR_LOWER },
    { "45", RT_ZR_UPPER },
    { "46", RT_ZR_HOVERS },
    { "47", RT_ZR_CUCCO },
    { "48", RT_ZD_KING_ZORA_SKIP },
    { "49", RT_ZD_GS },
    { "50", RT_ZF_GREAT_FAIRY_WITHOUT_EXPLOSIVES },
    { "51", RT_LH_LAB_WALL_GS },
    { "52", RT_LH_LAB_DIVING },
    { "53", RT_LH_WATER_HOOKSHOT },
    { "54", RT_GV_CRATE_HOVERS },
    { "55", RT_PASS_GUARDS_WITH_NOTHING },
    { "57", RT_GF_WARRIOR_WITH_DIFFICULT_WEAPON },
    { "58", RT_GF_LEDGE_CLIP_INTO_GTG },
    { "60", RT_HW_CROSSING },
    { "61", RT_LENS_HW },
    { "62", RT_HW_REVERSE },
    { "63", RT_COLOSSUS_GS },
    { "64", RT_DEKU_BASEMENT_GS },
    { "65", RT_DEKU_B1_SKIP },
    { "66", RT_DEKU_B1_BOW_WEBS },
    { "67", RT_DEKU_B1_BACKFLIP_OVER_SPIKED_LOG },
    { "68", RT_DEKU_MQ_COMPASS_GS },
    { "69", RT_DEKU_MQ_LOG },
    { "70", RT_DC_SCARECROW_GS },
    { "71", RT_DC_VINES_GS },
    { "72", RT_DC_STAIRS_WITH_BOW },
    { "73", RT_DC_SLINGSHOT_SKIP },
    { "74", RT_DC_SCRUB_ROOM },
    { "76", RT_DC_HAMMER_FLOOR },
    { "77", RT_DC_MQ_STAIRS_WITH_ONLY_STRENGTH },
    { "78", RT_DC_MQ_CHILD_BOMBS },
    { "79", RT_DC_MQ_CHILD_EYES },
    { "80", RT_DC_MQ_ADULT_EYES },
    { "81", RT_DC_DODONGO_CHU },
    { "83", RT_JABU_BOSS_HOVER },
    { "84", RT_JABU_NEAR_BOSS_RANGED },
    { "85", RT_JABU_NEAR_BOSS_EXPLOSIVES },
    { "86", RT_LENS_JABU_MQ },
    { "87", RT_JABU_MQ_RANG_JUMP },
    { "88", RT_JABU_MQ_SOT_GS },
    { "89", RT_LENS_BOTW },
    { "90", RT_BOTW_CHILD_DEADHAND },
    { "91", RT_BOTW_BASEMENT },
    { "92", RT_BOTW_PITS },
    { "93", RT_BOTW_MQ_DEADHAND_KEY },
    { "94", RT_FOREST_FIRST_GS },
    { "95", RT_FOREST_COURTYARD_EAST_GS },
    { "96", RT_FOREST_VINES },
    { "97", RT_FOREST_COURTYARD_LEDGE },
    { "98", RT_FOREST_DOORFRAME },
    { "99", RT_FOREST_OUTSIDE_BACKDOOR },
    { "100", RT_FOREST_COURTYARD_HEARTS_BOOMERANG },
    { "101", RT_FOREST_WELL_SWIM },
    { "102", RT_FOREST_MQ_BLOCK_PUZZLE },
    { "103", RT_FOREST_MQ_JS_HALLWAY_SWITCH },
    { "104", RT_FOREST_MQ_HOOKSHOT_HALLWAY_SWITCH },
    { "105", RT_FOREST_MQ_RANG_HALLWAY_SWITCH },
    { "107", RT_FIRE_SOT },
    { "108", RT_FIRE_STRENGTH },
    { "109", RT_FIRE_SCARECROW },
    { "111", RT_FIRE_MQ_NEAR_BOSS },
    { "112", RT_FIRE_MQ_BLOCKED_CHEST },
    { "113", RT_FIRE_MQ_BK_CHEST },
    { "114", RT_FIRE_MQ_CLIMB },
    { "115", RT_FIRE_MQ_MAZE_SIDE_ROOM },
    { "116", RT_FIRE_MQ_MAZE_HOVERS },
    { "117", RT_FIRE_MQ_MAZE_JUMP },
    { "118", RT_FIRE_MQ_ABOVE_MAZE_GS },
    { "120", RT_WATER_LONGSHOT_TORCH },
    { "121", RT_WATER_CRACKED_WALL_HOVERS },
    { "122", RT_WATER_CRACKED_WALL },
    { "123", RT_WATER_BK_REGION },
    { "124", RT_WATER_NORTH_BASEMENT_LEDGE_JUMP },
    { "126", RT_WATER_FW_CENTRAL_GS },
    { "127", RT_WATER_IRONS_CENTRAL_GS },
    { "128", RT_WATER_CENTRAL_BOW },
    { "129", RT_WATER_HOOKSHOT_FALLING_PLATFORM_GS },
    { "130", RT_WATER_RANG_FALLING_PLATFORM_GS },
    { "131", RT_WATER_RIVER_GS },
    { "132", RT_WATER_DRAGON_JUMP_DIVE },
    { "133", RT_WATER_ADULT_DRAGON },
    { "134", RT_WATER_CHILD_DRAGON },
    { "135", RT_WATER_MQ_CENTRAL_PILLAR },
    { "136", RT_WATER_INVISIBLE_HOOKSHOT_TARGET },
    { "137", RT_WATER_MORPHA_WITHOUT_HOOKSHOT },
    { "138", RT_LENS_SHADOW },
    { "139", RT_LENS_SHADOW_PLATFORM },
    { "140", RT_LENS_BONGO },
    { "141", RT_SHADOW_UMBRELLA_HOVER },
    { "142", RT_SHADOW_UMBRELLA_CLIP },
    { "143", RT_SHADOW_UMBRELLA_GS },
    { "144", RT_SHADOW_FREESTANDING_KEY },
    { "145", RT_SHADOW_STATUE },
    { "146", RT_SHADOW_BONGO },
    { "147", RT_LENS_SHADOW_MQ },
    { "148", RT_LENS_SHADOW_MQ_INVISIBLE_BLADES },
    { "149", RT_LENS_SHADOW_MQ_PLATFORM },
    { "150", RT_LENS_SHADOW_MQ_DEADHAND },
    { "151", RT_SHADOW_MQ_GAP },
    { "152", RT_SHADOW_MQ_INVISIBLE_BLADES },
    { "153", RT_SHADOW_MQ_HUGE_PIT },
    { "154", RT_SHADOW_MQ_WINDY_WALKWAY },
    { "155", RT_LENS_SPIRIT },
    { "156", RT_SPIRIT_CHILD_CHU },
    { "157", RT_SPIRIT_WEST_LEDGE },
    { "158", RT_SPIRIT_LOWER_ADULT_SWITCH },
    { "159", RT_SPIRIT_STATUE_JUMP },
    { "161", RT_SPIRIT_MAP_CHEST },
    { "162", RT_SPIRIT_SUN_CHEST },
    { "163", RT_SPIRIT_WALL },
    { "164", RT_LENS_SPIRIT_MQ },
    { "165", RT_SPIRIT_MQ_SUN_BLOCK_SOT },
    { "166", RT_SPIRIT_MQ_SUN_BLOCK_GS },
    { "167", RT_SPIRIT_MQ_LOWER_ADULT },
    { "168", RT_SPIRIT_MQ_FROZEN_EYE },
    { "169", RT_ICE_BLOCK_GS },
    { "170", RT_ICE_MQ_RED_ICE_GS },
    { "171", RT_ICE_MQ_SCARECROW },
    { "172", RT_LENS_GTG },
    { "173", RT_GTG_WITHOUT_HOOKSHOT },
    { "174", RT_GTG_FAKE_WALL },
    { "175", RT_LENS_GTG_MQ },
    { "176", RT_GTG_MQ_WITH_HOOKSHOT },
    { "177", RT_GTG_MQ_WITHOUT_HOOKSHOT },
    { "178", RT_LENS_GANON },
    { "179", RT_GANON_SPIRIT_TRIAL_HOOKSHOT },
    { "180", RT_LENS_GANON_MQ },
    { "181", RT_GANON_MQ_FIRE_TRIAL },
    { "182", RT_GANON_MQ_SHADOW_TRIAL },
    { "183", RT_GANON_MQ_LIGHT_TRIAL },
    { "201", RT_GROUND_JUMP },
    { "202", RT_GROUND_JUMP_HARD },
    { "223", RT_BOTTOM_OF_THE_WELL_NAVI_DIVE },
    { "224", RT_LOST_WOOD_NAVI_DIVE },
};

std::array<HintText, RHT_MAX> StaticData::hintTextTable = {};

std::vector<RandomizerGet> StaticData::normalBottles = {
    RG_EMPTY_BOTTLE,
    RG_BOTTLE_WITH_MILK,
    RG_BOTTLE_WITH_RED_POTION,
    RG_BOTTLE_WITH_GREEN_POTION,
    RG_BOTTLE_WITH_BLUE_POTION,
    RG_BOTTLE_WITH_FAIRY,
    RG_BOTTLE_WITH_FISH,
    RG_BOTTLE_WITH_BUGS,
    RG_BOTTLE_WITH_POE,
    RG_BOTTLE_WITH_BIG_POE,
    RG_BOTTLE_WITH_BLUE_FIRE,
};

std::vector<RandomizerGet> StaticData::beanSouls = {
    RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL,
    RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL,
    RG_DESERT_COLOSSUS_BEAN_SOUL,
    RG_GERUDO_VALLEY_BEAN_SOUL,
    RG_GRAVEYARD_BEAN_SOUL,
    RG_KOKIRI_FOREST_BEAN_SOUL,
    RG_LAKE_HYLIA_BEAN_SOUL,
    RG_LOST_WOODS_BRIDGE_BEAN_SOUL,
    RG_LOST_WOODS_BEAN_SOUL,
    RG_ZORAS_RIVER_BEAN_SOUL,
};

std::vector<RandomizerGet> StaticData::overworldKeys = {
    RG_GUARD_HOUSE_KEY,
    RG_MARKET_BAZAAR_KEY,
    RG_MARKET_POTION_SHOP_KEY,
    RG_MASK_SHOP_KEY,
    RG_MARKET_SHOOTING_GALLERY_KEY,
    RG_BOMBCHU_BOWLING_KEY,
    RG_TREASURE_CHEST_GAME_BUILDING_KEY,
    RG_BOMBCHU_SHOP_KEY,
    RG_RICHARDS_HOUSE_KEY,
    RG_ALLEY_HOUSE_KEY,
    RG_KAK_BAZAAR_KEY,
    RG_KAK_POTION_SHOP_KEY,
    RG_BOSS_HOUSE_KEY,
    RG_GRANNYS_POTION_SHOP_KEY,
    RG_SKULLTULA_HOUSE_KEY,
    RG_IMPAS_HOUSE_KEY,
    RG_WINDMILL_KEY,
    RG_KAK_SHOOTING_GALLERY_KEY,
    RG_DAMPES_HUT_KEY,
    RG_TALONS_HOUSE_KEY,
    RG_STABLES_KEY,
    RG_BACK_TOWER_KEY,
    RG_HYLIA_LAB_KEY,
    RG_FISHING_HOLE_KEY,
};
} // namespace Rando
