import copy

from typing import Dict

from ours.memories.relative_graph import KnowledgeGraph as OracleGraph
from ours.util import (
    max_pickaxe_level,
)


def determine_dependency_mining(new_item, current_inventory):
    pickaxe_level = max_pickaxe_level(current_inventory)

    tmp_name = copy.deepcopy(new_item)
    if 'log' in tmp_name:
        tmp_name = 'logs'
    elif 'planks' in tmp_name:
        tmp_name = 'planks'
    elif 'sapling' in tmp_name:
        tmp_name = 'saplings'
    elif 'charcoal' in tmp_name:
        tmp_name = 'charcoal'
    elif 'coal' in tmp_name:
        tmp_name = 'coals'

    data = {
        "item_name": tmp_name,
        "output_qty": 1,
        "ingredients": dict(),
        "required_pickaxe": pickaxe_level,
        "is_crafting": False,
    }
    return data


def match_item_names(new_item, dependency, is_crafting=True):
    tmp_name = copy.deepcopy(new_item)
    if 'log' in tmp_name:
        tmp_name = 'logs'
    elif 'planks' in tmp_name:
        tmp_name = 'planks'
    elif 'sapling' in tmp_name:
        tmp_name = 'saplings'
    elif 'charcoal' in tmp_name:
        tmp_name = 'charcoal'
    elif 'coal' in tmp_name:
        tmp_name = 'coals'

    ingredients = {}
    for k, v in dependency['ingredients'].items():
        if "log" in k:
            ingredients["logs"] = v
        elif "planks" in k:
            ingredients["planks"] = v
        elif "sapling" in k:
            ingredients["saplings"] = v
        elif "charcoal" in k:
            ingredients["charcoal"] = v
        elif "coal" in k:
            ingredients["coals"] = v
        else:
            ingredients[k] = v

    data = {
        "item_name": tmp_name,
        "output_qty": dependency['output_qty'],
        "ingredients": ingredients,
        "required_pickaxe": 0,
        "is_crafting": is_crafting,
    }

    return data


def extract_dependencies(init_inventory, current_inventory, operation, oracle_graph: OracleGraph):
    # NOTE: Currently, for crafting and smelting, oracle graph emits oracle dependency.
    # I choose this way because it is easy to implement.
    # It might be seen as cheating, but this is same with learning dependencies just using state transition data.
    # We can track which items are used, and which items are crafted/smelted.

    result = [] # list of dependencies

    # first, find new items
    init_inv_items = set(init_inventory.keys())
    current_inv_items = set(current_inventory.keys())
    new_items = list(current_inv_items - init_inv_items)
    if len(new_items) == 0:
        return []

    if "mine" in operation or "chop" in operation or "dig" in operation:
        for new_item in new_items:
            dependency = determine_dependency_mining(new_item, current_inventory)
            result.append(dependency)
    elif operation == "craft":
        for new_item in new_items:
            dependency = oracle_graph.get_recipe(new_item)
            if dependency is None:
                # sometimes, miscellaneous items which are not crafted are obtained during crafting (e.g., saplings, ...)
                dependency = determine_dependency_mining(new_item, current_inventory)
                result.append(dependency)
                continue

            dependency = match_item_names(new_item, copy.deepcopy(dependency), True)
            result.append(dependency)
    elif operation == "smelt":
        for new_item in new_items:
            dependency = oracle_graph.get_recipe(new_item)
            if dependency is None:
                dependency = determine_dependency_mining(new_item, current_inventory)
                result.append(dependency)
                continue

            dependency = match_item_names(new_item, copy.deepcopy(dependency), False)
            # add {"coals": 1} to the dependency, as a fuel for smelting
            dependency["ingredients"]["coals"] = 1
            result.append(dependency)

    return result
