from dataclasses import dataclass
from enum import Enum


class ObjectiveType(str, Enum):
    BOSS = "Boss"
    WORLDPROGRESS = "WorldProgress"
    FIGHT = "Fight"


class ObjectiveDifficulty(str, Enum):
    EARLY = "Early"
    MIDDLE = "Middle"
    LATE = "Late"
    LATEST = "Latest"


@dataclass(frozen=True)
class KH2Objective:
    Name: str
    Location: Enum
    Type: ObjectiveType
    Difficulty: ObjectiveDifficulty = ObjectiveDifficulty.EARLY


def get_last_story_objectives():
    from .location import (
        simulatedtwilighttown,
        twilighttown,
        hollowbastion,
        landofdragons,
        beastscastle,
        disneycastle,
        portroyal,
        agrabah,
        halloweentown,
        pridelands,
        spaceparanoids,
        worldthatneverwas,
        olympuscoliseum,
        hundredacrewood,
        atlantica,
        formlevel,
        puzzlereward,
    )

    return [
        KH2Objective(
            "Defeat Axel II",
            simulatedtwilighttown.CheckLocation.Axel2,
            ObjectiveType.BOSS,
        ),
        KH2Objective(
            "Fight alongside Axel",
            twilighttown.CheckLocation.BetwixtAndBetween,
            ObjectiveType.FIGHT,
            ObjectiveDifficulty.LATE,
        ),
        KH2Objective(
            "Stop the 1000 Heartless",
            hollowbastion.CheckLocation.ThousandHeartless,
            ObjectiveType.FIGHT,
            ObjectiveDifficulty.LATE,
        ),
        KH2Objective(
            "Defeat Stormrider",
            landofdragons.CheckLocation.StormRiderBonus,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATE,
        ),
        KH2Objective(
            "Defeat Xaldin",
            beastscastle.CheckLocation.XaldinBonus,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATE,
        ),
        KH2Objective(
            "Defeat Future Pete",
            disneycastle.CheckLocation.FuturePete,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATE,
        ),
        KH2Objective(
            "Defeat Grim Reaper II",
            portroyal.CheckLocation.GrimReaper2,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATE,
        ),
        KH2Objective(
            "Defeat Genie Jafar",
            agrabah.CheckLocation.GenieJafarBonus,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATE,
        ),
        KH2Objective(
            "Defeat the Experiment",
            halloweentown.CheckLocation.Experiment,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATE,
        ),
        KH2Objective(
            "Defeat Groundshaker",
            pridelands.CheckLocation.Groundshaker,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATE,
        ),
        KH2Objective(
            "Defeat MCP",
            spaceparanoids.CheckLocation.McpBonus,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATE,
        ),
        KH2Objective(
            "Defeat Xemnas",
            worldthatneverwas.CheckLocation.Xemnas1Bonus,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATE,
        ),
        KH2Objective(
            "Defeat Hades",
            olympuscoliseum.CheckLocation.Hades,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATE,
        ),
        KH2Objective(
            "Help Pooh out of the pot of hunny",
            hundredacrewood.CheckLocation.StarryHillCureElement,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Participate the New Day Musical",
            atlantica.CheckLocation.MusicalBlizzardElement,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.LATEST,
        ),
    ]


def get_full_objective_list():
    from .location import (
        simulatedtwilighttown,
        twilighttown,
        hollowbastion,
        landofdragons,
        beastscastle,
        disneycastle,
        portroyal,
        agrabah,
        halloweentown,
        pridelands,
        spaceparanoids,
        worldthatneverwas,
        olympuscoliseum,
        hundredacrewood,
        atlantica,
        formlevel,
        puzzlereward,
    )

    return get_last_story_objectives() + [
        # STT
        KH2Objective(
            "Defeat Twilight Thorn",
            simulatedtwilighttown.CheckLocation.TwilightThorn,
            ObjectiveType.BOSS,
        ),
        KH2Objective(
            "Defeat Axel I",
            simulatedtwilighttown.CheckLocation.Axel1,
            ObjectiveType.FIGHT,
        ),
        KH2Objective(
            "Fight Setzer",
            simulatedtwilighttown.CheckLocation.StruggleTrophy,
            ObjectiveType.FIGHT,
        ),
        # TT
        KH2Objective(
            "Talk to the 3 Fairies",
            twilighttown.CheckLocation.ValorForm,
            ObjectiveType.WORLDPROGRESS,
        ),
        KH2Objective(
            "Defeat Sandlot Berserkers",
            twilighttown.CheckLocation.SeifersTrophy,
            ObjectiveType.FIGHT,
            ObjectiveDifficulty.MIDDLE,
        ),
        # HB
        KH2Objective(
            "Defend the Bailey", hollowbastion.CheckLocation.Bailey, ObjectiveType.FIGHT
        ),
        KH2Objective(
            "Defeat Demyx",
            hollowbastion.CheckLocation.DemyxHollowBastion,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.MIDDLE,
        ),
        # CoR
        KH2Objective(
            "Reach the end of Cavern of Remembrance",
            hollowbastion.CheckLocation.CorMineshaftUpperLevelApBoost,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.LATE,
        ),
        KH2Objective(
            "Reach the end of Transport of Remembrance",
            hollowbastion.CheckLocation.TransportToRemembrance,
            ObjectiveType.FIGHT,
            ObjectiveDifficulty.LATEST,
        ),
        # LoD
        KH2Objective(
            "Climb the Mountain Trail",
            landofdragons.CheckLocation.VillageCaveAreaMap,
            ObjectiveType.WORLDPROGRESS,
        ),
        KH2Objective(
            "Fight the Enemies in Village Cave",
            landofdragons.CheckLocation.VillageCaveBonus,
            ObjectiveType.FIGHT,
        ),
        KH2Objective(
            "Defeat Shan Yu",
            landofdragons.CheckLocation.ShanYuBonus,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.MIDDLE,
        ),
        # BC
        KH2Objective(
            "Defeat Thresholder",
            beastscastle.CheckLocation.Thresholder,
            ObjectiveType.BOSS,
        ),
        KH2Objective(
            "Help Beast", beastscastle.CheckLocation.Beast, ObjectiveType.WORLDPROGRESS
        ),
        KH2Objective(
            "Defeat Dark Thorn",
            beastscastle.CheckLocation.DarkThorn,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.MIDDLE,
        ),
        # DC
        KH2Objective(
            "Escort Queen Minnie",
            disneycastle.CheckLocation.MinnieEscort,
            ObjectiveType.WORLDPROGRESS,
        ),
        KH2Objective(
            "Fight through Windows of Time",
            disneycastle.CheckLocation.WindowOfTimeMap,
            ObjectiveType.FIGHT,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Stop Pete from Escaping",
            disneycastle.CheckLocation.BoatPete,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.MIDDLE,
        ),
        # PR
        KH2Objective(
            "Stall for time on Isla de Muerta",
            portroyal.CheckLocation.IslaDeMuertaMap,
            ObjectiveType.WORLDPROGRESS,
        ),
        KH2Objective(
            "Defend the Interceptor from pirates",
            portroyal.CheckLocation.BoatFight,
            ObjectiveType.FIGHT,
        ),
        KH2Objective(
            "Stop the explosive barrels",
            portroyal.CheckLocation.InterceptorBarrels,
            ObjectiveType.WORLDPROGRESS,
        ),
        KH2Objective(
            "Defeat Barbossa",
            portroyal.CheckLocation.Barbossa,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Defeat Grim Reaper I",
            portroyal.CheckLocation.GrimReaper1,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.MIDDLE,
        ),
        # AG
        KH2Objective(
            "Escort Abu", agrabah.CheckLocation.AbuEscort, ObjectiveType.WORLDPROGRESS
        ),
        KH2Objective(
            "Survive the Treasure Room Ambush",
            agrabah.CheckLocation.TreasureRoomBonus,
            ObjectiveType.FIGHT,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Defeat the Elemental Lords",
            agrabah.CheckLocation.ElementalLordsBonus,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.MIDDLE,
        ),
        # HT
        KH2Objective(
            "Defeat Prison Keeper",
            halloweentown.CheckLocation.PrisonKeeper,
            ObjectiveType.BOSS,
        ),
        KH2Objective(
            "Defeat Oogie Boogie",
            halloweentown.CheckLocation.OogieBoogie,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Capture Lock Shock and Barrel",
            halloweentown.CheckLocation.LockShockBarrel,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Find the stolen presents",
            halloweentown.CheckLocation.Present,
            ObjectiveType.FIGHT,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Create decoy presents",
            halloweentown.CheckLocation.DecoyPresents,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.MIDDLE,
        ),
        # PL
        KH2Objective(
            "Reunite with Simba",
            pridelands.CheckLocation.CircleOfLife,
            ObjectiveType.WORLDPROGRESS,
        ),
        KH2Objective(
            "Rescue Timon and Pumbaa",
            pridelands.CheckLocation.Hyenas1,
            ObjectiveType.WORLDPROGRESS,
        ),
        KH2Objective(
            "Defeat Scar",
            pridelands.CheckLocation.Scar,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Get info about the ghost of Scar from Hyenas",
            pridelands.CheckLocation.Hyenas2,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.MIDDLE,
        ),
        # SP
        KH2Objective(
            "Survive the Dataspace Attack",
            spaceparanoids.CheckLocation.ScreensBonus,
            ObjectiveType.FIGHT,
        ),
        KH2Objective(
            "Defeat Hostile Program",
            spaceparanoids.CheckLocation.HostileProgramBonus,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Ride the Solar Sailor",
            spaceparanoids.CheckLocation.SolarSailerBonus,
            ObjectiveType.FIGHT,
            ObjectiveDifficulty.MIDDLE,
        ),
        # TWTNW
        KH2Objective(
            "Defeat Roxas", worldthatneverwas.CheckLocation.Roxas, ObjectiveType.BOSS
        ),
        KH2Objective(
            "Defeat Xigbar",
            worldthatneverwas.CheckLocation.XigbarBonus,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Defeat Luxord",
            worldthatneverwas.CheckLocation.LuxordBonus,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Defeat Saix",
            worldthatneverwas.CheckLocation.SaixBonus,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.MIDDLE,
        ),
        # OC
        KH2Objective(
            "Defeat Cerberus",
            olympuscoliseum.CheckLocation.Cerberus,
            ObjectiveType.BOSS,
        ),
        KH2Objective(
            "Train with Phil",
            olympuscoliseum.CheckLocation.Urns,
            ObjectiveType.WORLDPROGRESS,
        ),
        KH2Objective(
            "Defeat Pete at The Lock",
            olympuscoliseum.CheckLocation.PeteOlympusColiseum,
            ObjectiveType.FIGHT,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Defeat Hydra",
            olympuscoliseum.CheckLocation.Hydra,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Defeat the Ambush in Hades Chamber",
            olympuscoliseum.CheckLocation.AuronssStatue,
            ObjectiveType.FIGHT,
            ObjectiveDifficulty.MIDDLE,
        ),
        # Cups
        KH2Objective(
            "Win the Pain and Panic Cup",
            olympuscoliseum.CheckLocation.PainPanicCupProtectBelt,
            ObjectiveType.FIGHT,
        ),
        KH2Objective(
            "Win the Cerberus Cup",
            olympuscoliseum.CheckLocation.CerberusCupRisingDragon,
            ObjectiveType.FIGHT,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Win the Titan Cup",
            olympuscoliseum.CheckLocation.TitanCupGenjiShield,
            ObjectiveType.FIGHT,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Win the Goddess of Fate Cup",
            olympuscoliseum.CheckLocation.GoddessOfFateCupFatalCrest,
            ObjectiveType.FIGHT,
            ObjectiveDifficulty.LATE,
        ),
        # HAW
        KH2Objective(
            "Rescue Pooh from the Spooky Cave",
            hundredacrewood.CheckLocation.SweetMemories,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.LATE,
        ),
        # AT
        KH2Objective(
            "Relearn to swim",
            atlantica.CheckLocation.UnderseaKingdomMap,
            ObjectiveType.WORLDPROGRESS,
        ),
        KH2Objective(
            "Defeat Ursula",
            atlantica.CheckLocation.MysteriousAbyss,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.LATE,
        ),
        # FORM
        KH2Objective(
            "Reach Valor Level 3",
            formlevel.CheckLocation.Valor3,
            ObjectiveType.WORLDPROGRESS,
        ),
        KH2Objective(
            "Reach Valor Level 5",
            formlevel.CheckLocation.Valor5,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Reach Valor Level 7",
            formlevel.CheckLocation.Valor7,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Reach Wisdom Level 3",
            formlevel.CheckLocation.Wisdom3,
            ObjectiveType.WORLDPROGRESS,
        ),
        KH2Objective(
            "Reach Wisdom Level 5",
            formlevel.CheckLocation.Wisdom5,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Reach Wisdom Level 7",
            formlevel.CheckLocation.Wisdom7,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Reach Limit Level 3",
            formlevel.CheckLocation.Limit3,
            ObjectiveType.WORLDPROGRESS,
        ),
        KH2Objective(
            "Reach Limit Level 5",
            formlevel.CheckLocation.Limit5,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Reach Limit Level 7",
            formlevel.CheckLocation.Limit7,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Reach Master Level 3",
            formlevel.CheckLocation.Master3,
            ObjectiveType.WORLDPROGRESS,
        ),
        KH2Objective(
            "Reach Master Level 5",
            formlevel.CheckLocation.Master5,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Reach Master Level 7",
            formlevel.CheckLocation.Master7,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Reach Final Level 3",
            formlevel.CheckLocation.Final3,
            ObjectiveType.WORLDPROGRESS,
        ),
        KH2Objective(
            "Reach Final Level 5",
            formlevel.CheckLocation.Final5,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Reach Final Level 7",
            formlevel.CheckLocation.Final7,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.LATEST,
        ),
        # Puzzle
        KH2Objective(
            "Complete the Awakening Puzzle",
            puzzlereward.CheckLocation.AwakeningApBoost,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Complete the Heart Puzzle",
            puzzlereward.CheckLocation.HeartSerenityCrystal,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.MIDDLE,
        ),
        KH2Objective(
            "Complete the Duality Puzzle",
            puzzlereward.CheckLocation.DualityRareDocument,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.LATE,
        ),
        KH2Objective(
            "Complete the Frontier Puzzle",
            puzzlereward.CheckLocation.FrontierManifestIllusion,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.LATE,
        ),
        KH2Objective(
            "Complete the Daylight Puzzle",
            puzzlereward.CheckLocation.DaylightExecutivesRing,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.LATE,
        ),
        KH2Objective(
            "Complete the Sunset Puzzle",
            puzzlereward.CheckLocation.SunsetGrandRibbon,
            ObjectiveType.WORLDPROGRESS,
            ObjectiveDifficulty.LATE,
        ),
        # Superbosses
        KH2Objective(
            "Defeat Sephiroth",
            hollowbastion.CheckLocation.SephirothBonus,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Defeat Lingering Will",
            disneycastle.CheckLocation.LingeringWillBonus,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Defeat Data Roxas",
            simulatedtwilighttown.CheckLocation.DataRoxasMagicBoost,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Defeat Data Demyx",
            hollowbastion.CheckLocation.DataDemyxApBoost,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Defeat Data Xigbar",
            landofdragons.CheckLocation.DataXigbarDefenseBoost,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Defeat Data Saix",
            pridelands.CheckLocation.DataSaix,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Defeat Data Axel",
            twilighttown.CheckLocation.DataAxelMagicBoost,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Defeat Data Xaldin",
            beastscastle.CheckLocation.DataXaldin,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Defeat Data Luxord",
            portroyal.CheckLocation.DataLuxordApBoost,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Defeat Data Xemnas",
            worldthatneverwas.CheckLocation.DataXemnas,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Defeat Data Zexion",
            olympuscoliseum.CheckLocation.DataZexionLostIllusion,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Defeat Data Vexen",
            halloweentown.CheckLocation.DataVexen,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Defeat Data Larxene",
            spaceparanoids.CheckLocation.DataLarxeneLostIllusion,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Defeat Data Lexaeus",
            agrabah.CheckLocation.DataLexaeus,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Defeat Data Marluxia",
            disneycastle.CheckLocation.DataMarluxiaLostIllusion,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATEST,
        ),
        # AS
        KH2Objective(
            "Defeat AS Zexion",
            olympuscoliseum.CheckLocation.ZexionBonus,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Defeat AS Vexen",
            halloweentown.CheckLocation.VexenBonus,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Defeat AS Larxene",
            spaceparanoids.CheckLocation.LarxeneBonus,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Defeat AS Lexaeus",
            agrabah.CheckLocation.LexaeusBonus,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATEST,
        ),
        KH2Objective(
            "Defeat AS Marluxia",
            disneycastle.CheckLocation.MarluxiaBonus,
            ObjectiveType.BOSS,
            ObjectiveDifficulty.LATEST,
        ),
    ]
