#include "soh/Enhancements/randomizer/location_access.h"
#include "soh/Enhancements/randomizer/entrance.h"

using namespace Rando;

void RegionTable_Init_Graveyard() {
    // clang-format off
    areaTable[RR_THE_GRAVEYARD] = Region("The Graveyard", SCENE_GRAVEYARD, {
        //Events
        EVENT_ACCESS(LOGIC_FAIRY_ACCESS,      (logic->AtDay && logic->CanUse(RG_STICKS)) || (logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS))),
        EVENT_ACCESS(LOGIC_BUG_ACCESS,        logic->HasItem(RG_POWER_BRACELET)),
        EVENT_ACCESS(LOGIC_BORROW_BUNNY_HOOD, logic->IsChild && logic->AtDay && logic->Get(LOGIC_BORROW_SPOOKY_MASK) && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN)),
    }, {
        //Locations
        LOCATION(RC_GRAVEYARD_FREESTANDING_POH,        (((logic->IsAdult && CanPlantBean(RR_THE_GRAVEYARD, RG_GRAVEYARD_BEAN_SOUL)) || logic->CanUse(RG_LONGSHOT)) && logic->CanBreakCrates()) || (ctx->GetTrickOption(RT_GY_POH) && logic->CanUse(RG_BOOMERANG))),
        LOCATION(RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsChild && logic->AtNight), //TODO: This needs to change
        LOCATION(RC_GRAVEYARD_GS_WALL,                 logic->IsChild && logic->HookshotOrBoomerang() && logic->AtNight && logic->CanGetNightTimeGS()),
        LOCATION(RC_GRAVEYARD_GS_BEAN_PATCH,           logic->CanSpawnSoilSkull(RG_GRAVEYARD_BEAN_SOUL) && logic->CanAttack()),
        LOCATION(RC_GRAVEYARD_BEAN_SPROUT_FAIRY_1,     logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GRAVEYARD_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)),
        LOCATION(RC_GRAVEYARD_BEAN_SPROUT_FAIRY_2,     logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GRAVEYARD_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)),
        LOCATION(RC_GRAVEYARD_BEAN_SPROUT_FAIRY_3,     logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GRAVEYARD_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)),
        LOCATION(RC_GY_GRASS_1,                        logic->CanCutShrubs()),
        LOCATION(RC_GY_GRASS_2,                        logic->CanCutShrubs()),
        LOCATION(RC_GY_GRASS_3,                        logic->CanCutShrubs()),
        LOCATION(RC_GY_GRASS_4,                        logic->CanCutShrubs()),
        LOCATION(RC_GY_GRASS_5,                        logic->CanCutShrubs()),
        LOCATION(RC_GY_GRASS_6,                        logic->CanCutShrubs()),
        LOCATION(RC_GY_GRASS_7,                        logic->CanCutShrubs()),
        LOCATION(RC_GY_GRASS_8,                        logic->CanCutShrubs()),
        LOCATION(RC_GY_GRASS_9,                        logic->CanCutShrubs()),
        LOCATION(RC_GY_GRASS_10,                       logic->CanCutShrubs()),
        LOCATION(RC_GY_GRASS_11,                       logic->CanCutShrubs()),
        LOCATION(RC_GY_GRASS_12,                       logic->CanCutShrubs()),
        LOCATION(RC_GRAVEYARD_CRATE,                   ((logic->IsAdult && CanPlantBean(RR_THE_GRAVEYARD, RG_GRAVEYARD_BEAN_SOUL)) || logic->CanUse(RG_LONGSHOT)) && logic->CanBreakCrates()),
        LOCATION(RC_GY_ROCK,                           logic->CanBreakRocks()),
        LOCATION(RC_GY_NEAR_HUT_GRAVE_BUTTERFLY_FAIRY, logic->IsChild && logic->AtDay && logic->CanUse(RG_STICKS)),
        LOCATION(RC_GY_ENTRANCE_RECTANGLE_SIGN,        logic->CanRead()),
        LOCATION(RC_GY_ENTRANCE_PLINTH,                logic->CanRead()),
        LOCATION(RC_GY_RIGHT_OF_ROYAL_TOMB_GRAVE,      logic->CanRead()),
        LOCATION(RC_GY_LEFT_OF_ROYAL_TOMB_GRAVE,       logic->CanRead()),
        LOCATION(RC_GY_ROYAL_TOMB_GRAVE,               logic->CanRead() || logic->CanUse(RG_ZELDAS_LULLABY)),
    }, {
        //Exits
        ENTRANCE(RR_GRAVEYARD_SHIELD_GRAVE,       (logic->IsAdult || logic->AtNight) && logic->HasItem(RG_POWER_BRACELET)),
        ENTRANCE(RR_GRAVEYARD_COMPOSERS_GRAVE,    logic->CanUse(RG_ZELDAS_LULLABY)),
        ENTRANCE(RR_GRAVEYARD_HEART_PIECE_GRAVE,  (logic->IsAdult || logic->AtNight) && logic->HasItem(RG_POWER_BRACELET)),
        ENTRANCE(RR_GRAVEYARD_DAMPES_GRAVE,       logic->IsAdult && logic->HasItem(RG_POWER_BRACELET)),
        ENTRANCE(RR_GRAVEYARD_DAMPES_HOUSE,       logic->IsAdult && logic->HasItem(RG_DAMPES_HUT_KEY) /*|| logic->AtDampeTime*/), //TODO: This needs to be handled in ToD rework
        ENTRANCE(RR_KAKARIKO_VILLAGE,             true),
        ENTRANCE(RR_GRAVEYARD_WARP_PAD_REGION,    false),
    });

    areaTable[RR_GRAVEYARD_SHIELD_GRAVE] = Region("Graveyard Shield Grave", SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, {}, {
        //Locations
        LOCATION(RC_GRAVEYARD_SHIELD_GRAVE_CHEST, logic->HasItem(RG_OPEN_CHEST)),
    }, {
        //Exits
        ENTRANCE(RR_THE_GRAVEYARD,               true),
        ENTRANCE(RR_GRAVEYARD_SHIELD_GRAVE_BACK, AnyAgeTime([]{return logic->CanBreakMudWalls();})),
    });

    areaTable[RR_GRAVEYARD_SHIELD_GRAVE_BACK] = Region("Graveyard Shield Grave Back", SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, {}, {
        //Locations
        LOCATION(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_1, true),
        LOCATION(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_2, true),
        LOCATION(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_3, true),
        LOCATION(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_4, true),
        LOCATION(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_5, true),
        LOCATION(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_6, true),
        LOCATION(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_7, true),
        LOCATION(RC_GRAVEYARD_SHIELD_GRAVE_FAIRY_8, true),
    }, {
        //Exits
        ENTRANCE(RR_GRAVEYARD_SHIELD_GRAVE, true),
    });

    areaTable[RR_GRAVEYARD_HEART_PIECE_GRAVE] = Region("Graveyard Heart Piece Grave", SCENE_REDEAD_GRAVE, {}, {
        //Locations
        LOCATION(RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, logic->CanUse(RG_SUNS_SONG) && logic->HasItem(RG_OPEN_CHEST)),
    }, {
        //Exits
        ENTRANCE(RR_THE_GRAVEYARD, true),
    });

    areaTable[RR_GRAVEYARD_COMPOSERS_GRAVE] = Region("Graveyard Composers Grave", SCENE_ROYAL_FAMILYS_TOMB, {}, {
        //Locations
        LOCATION(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST,     logic->HasFireSource() && logic->HasItem(RG_OPEN_CHEST)),
        LOCATION(RC_SONG_FROM_ROYAL_FAMILYS_TOMB,           logic->CanUseProjectile() || logic->CanJumpslash()),
        LOCATION(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)),
    }, {
        //Exits
        ENTRANCE(RR_THE_GRAVEYARD, true),
    });

    areaTable[RR_GRAVEYARD_DAMPES_GRAVE] = Region("Graveyard Dampes Grave", SCENE_WINDMILL_AND_DAMPES_GRAVE, {
        //Events
        EVENT_ACCESS(LOGIC_NUT_ACCESS, logic->CanBreakPots()),
    }, {
        //Locations
        LOCATION(RC_GRAVEYARD_HOOKSHOT_CHEST,              logic->HasItem(RG_SPEAK_HYLIAN) && logic->HasItem(RG_OPEN_CHEST)),
        LOCATION(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, (logic->IsAdult || ctx->GetTrickOption(RT_GY_CHILD_DAMPE_RACE_POH)) && logic->HasItem(RG_SPEAK_HYLIAN)),
        LOCATION(RC_GY_DAMPES_GRAVE_POT_1,                 logic->CanBreakPots()),
        LOCATION(RC_GY_DAMPES_GRAVE_POT_2,                 logic->CanBreakPots()),
        LOCATION(RC_GY_DAMPES_GRAVE_POT_3,                 logic->CanBreakPots()),
        LOCATION(RC_GY_DAMPES_GRAVE_POT_4,                 logic->CanBreakPots()),
        LOCATION(RC_GY_DAMPES_GRAVE_POT_5,                 logic->CanBreakPots()),
        LOCATION(RC_GY_DAMPES_GRAVE_POT_6,                 logic->CanBreakPots()),
        LOCATION(RC_GRAVEYARD_DAMPE_RACE_RUPEE_1,          true),
        LOCATION(RC_GRAVEYARD_DAMPE_RACE_RUPEE_2,          true),
        LOCATION(RC_GRAVEYARD_DAMPE_RACE_RUPEE_3,          true),
        LOCATION(RC_GRAVEYARD_DAMPE_RACE_RUPEE_4,          true),
        LOCATION(RC_GRAVEYARD_DAMPE_RACE_RUPEE_5,          true),
        LOCATION(RC_GRAVEYARD_DAMPE_RACE_RUPEE_6,          true),
        LOCATION(RC_GRAVEYARD_DAMPE_RACE_RUPEE_7,          true),
        LOCATION(RC_GRAVEYARD_DAMPE_RACE_RUPEE_8,          true),
        LOCATION(RC_GY_WONDER_DAMPE_RACE_1,                true),
        LOCATION(RC_GY_WONDER_DAMPE_RACE_2,                true),
        LOCATION(RC_GY_WONDER_DAMPE_RACE_3,                true),
        LOCATION(RC_GY_WONDER_DAMPE_RACE_4,                true),
        LOCATION(RC_GY_WONDER_DAMPE_RACE_5,                true),
        LOCATION(RC_GY_WONDER_DAMPE_RACE_6,                true),
        LOCATION(RC_GY_WONDER_DAMPE_RACE_7,                true),
        LOCATION(RC_GY_WONDER_DAMPE_RACE_8,                true),
        LOCATION(RC_GY_WONDER_DAMPE_RACE_9,                true),
        LOCATION(RC_GY_WONDER_DAMPE_RACE_10,               true),
        LOCATION(RC_GY_WONDER_DAMPE_RACE_11,               true),
        LOCATION(RC_GY_WONDER_DAMPE_RACE_12,               true),
        LOCATION(RC_GY_WONDER_DAMPE_RACE_13,               true),
        LOCATION(RC_GY_WONDER_DAMPE_RACE_14,               true),
        LOCATION(RC_GY_WONDER_DAMPE_RACE_15,               true),
    }, {
        //Exits
        ENTRANCE(RR_THE_GRAVEYARD,      true),
        ENTRANCE(RR_KAK_WINDMILL_UPPER, (logic->IsAdult && logic->CanUse(RG_SONG_OF_TIME)) || (logic->IsChild && logic->CanGroundJump()), false),
    });

    areaTable[RR_GRAVEYARD_DAMPES_HOUSE] = Region("Graveyard Dampes House", SCENE_GRAVEKEEPERS_HUT, {}, {
        //Locations
        LOCATION(RC_DAMPE_HINT, logic->IsAdult),
    }, {
        //Exits
        ENTRANCE(RR_THE_GRAVEYARD, true),
    });

    areaTable[RR_GRAVEYARD_WARP_PAD_REGION] = Region("Graveyard Warp Pad Region", SCENE_GRAVEYARD, {
        //Events
        EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CallGossipFairyExceptSuns()),
    }, {
        //Locations
        LOCATION(RC_GRAVEYARD_GOSSIP_STONE_FAIRY,     logic->CallGossipFairyExceptSuns()),
        LOCATION(RC_GRAVEYARD_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)),
        LOCATION(RC_GRAVEYARD_GOSSIP_STONE,           true),
    }, {
        //Exits
        ENTRANCE(RR_THE_GRAVEYARD,          true),
        ENTRANCE(RR_SHADOW_TEMPLE_ENTRYWAY, logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_GY_SHADOW_FIRE_ARROWS) && logic->IsAdult && logic->CanUse(RG_FIRE_ARROWS))),
    });

    // clang-format on
}
