# So the goal here is to have a catalog of all the items in your game
# To correctly generate a games items they need to be bundled in a list
# A list in programming terms is anything in square brackets [] to put it simply

# When a list is described its described as a list of x where x is the type of variable within it
# IE: ["apple", "pear", "grape"] is a list of strings (anything inside "" OR '' are considered strings)

# Logging = output. How you'll figure out whats going wrong
import logging

# Built in AP imports
from BaseClasses import Item, ItemClassification

# These come from the other files in this example. If you want to see the source ctrl + click the name
# You can also do that ctrl + click for any functions to see what they do
from .Types import ItemData, AlbumType, MusipelagoItem, album_id_to_title
from .Locations import get_total_locations
from typing import List, Dict, TYPE_CHECKING

# This is just making sure nothing gets confused dw about what its doing exactly
if TYPE_CHECKING:
    from . import MusipelagoWorld

# If you're curious about the -> List[Item] that is a syntax to make sure you return the correct variable type
# In this instance we're saying we only want to return a list of items
# You'll see a bunch of other examples of this in other functions
# It's main purpose is to protect yourself from yourself
def create_itempool(world: "MusipelagoWorld") -> List[Item]:
    # This is the empty list of items. You'll add all the items in the game to this list
    itempool: List[Item] = []

    # In this function is where you would remove any starting items that you add in options such as starting chapter
    # This is also the place you would add dynamic amounts of items from options
    # I can point to Sly Cooper and the Thievious Raccoonus since I did that

    # This is a good place to grab anything you need from options
    starting_chapter = album_id_to_title[AlbumType(world.options.StartingAlbum)]

    # For this example I'll make it so there is a starting chapter
    # We loop through all the chapters in the my_chapter section
    for chapter in ap_skeleton_chapters.keys():
        # If the starting chapter equals the chapter we're looking at skip it
        # We skip it since we dont want to add the chapter the player started with to the item pool
        print("-------------------------")
        print(starting_chapter)
        print("-------------------------")
        if starting_chapter == chapter:
            continue
        # Otherwise then we create an item with that name and add it to the item pool
        else:
            itempool.append(create_item(world, chapter))
    
    # It's up to you and how you want things organized but I like to deal with victory here
    # This creates your win item and then places it at the "location" where you win
{% for album in apworld_data %}{% if album.tracks %}
    world.multiworld.get_location({{ "[%s] [%s] [%s]" | format(album.tracks[-1].artist | to_ascii, album.title | to_ascii, album.tracks[-1].title | to_ascii) | py_json }}, world.player).place_locked_item(create_item(world, "Album finished!"))
{% endif %}{% endfor %}

    # Then junk items are made
    # Check out the create_junk_items function for more details
    itempool += create_junk_items(world, get_total_locations(world) - len(itempool) - 1)

    return itempool

# This is a generic function to create a singular item
def create_item(world: "MusipelagoWorld", name: str) -> Item:
    data = item_table[name]
    return MusipelagoItem(name, data.classification, data.ap_code, world.player)

# Another generic function. For creating a bunch of items at once!
def create_multiple_items(world: "MusipelagoWorld", name: str, count: int,
                          item_type: ItemClassification = ItemClassification.progression) -> List[Item]:
    data = item_table[name]
    itemlist: List[Item] = []

    for i in range(count):
        itemlist += [MusipelagoItem(name, item_type, data.ap_code, world.player)]

    return itemlist

# Finally, where junk items are created
def create_junk_items(world: "MusipelagoWorld", count: int) -> List[Item]:
    junk_pool: List[Item] = []
    junk_list: Dict[str, int] = {}

    # This grabs all the junk items and trap items
    for name in item_table.keys():
        # Here we are getting all the junk item names and weights
        ic = item_table[name].classification
        if ic == ItemClassification.filler:
            junk_list[name] = junk_weights.get(name)

    # Where all the magic happens of adding the junk and traps randomly
    # AP does all the weight management so we just need to worry about how many are created
    for i in range(count):
            junk_pool.append(world.create_item(
                world.random.choices(list(junk_list.keys()), weights=list(junk_list.values()), k=1)[0]))

    return junk_pool

# Time for the fun part of listing all of the items
# Watch out for overlap with your item codes
# These are just random numbers dont trust them PLEASE
# I've seen some games that dynamically add item codes such as DOOM as well
ap_skeleton_items = {
    # Progression items
    "Album finished!": ItemData(2000001, ItemClassification.progression),

    # Victory is added here since in this organization it needs to be in the default item pool
    # "Victory": ItemData(2000002, ItemClassification.progression)
}

# I like to split up the items so that its easier to look at and since sometimes you only need to look at one specific type of list
# An example of that is in create_itempool where I simulated having a starting chapter
ap_skeleton_chapters = {
{% for album in apworld_data %}
    {{ "[%s] [%s]" | format(album.artist | to_ascii, album.title | to_ascii) | py_json }}: ItemData(1000{{ "%03d" | format(loop.index) }}, ItemClassification.progression),
{% endfor %}
}

# In the way that I made items, I added a way to specify how many of an item should exist
# That's why junk has a 0 since how many are created is in the create_junk_items
# There is a better way of doing this but this is my jank
junk_items = {
    # Junk
    "Scratched disc": ItemData(2001001, ItemClassification.filler, 0),
    ".mov file": ItemData(2001002, ItemClassification.filler, 0),
    "Funny animal .gif": ItemData(2001003, ItemClassification.filler, 0),
    "Concert tickets": ItemData(2001004, ItemClassification.filler, 0),

    # # Traps
    # "Forcefem Trap": ItemData(20050013, ItemClassification.trap, 0),
    # "Speed Change Trap": ItemData(20050014, ItemClassification.trap, 0)
}

# Junk weights is just how often an item will be chosen when junk is being made
# Bigger item = more likely to show up
junk_weights = {
    "Scratched disc": 1,
    ".mov file": 1,
    "Funny animal .gif": 1,
    "Concert tickets": 1
}

# This makes a really convenient list of all the other dictionaries
# (fun fact: {} is a dictionary)
item_table = {
    **ap_skeleton_items,
    **ap_skeleton_chapters,
    **junk_items
}