from core.terraform.helper import placeContentInArea

from siege import game, InventoryItem
from siege.network import NetworkManager
from siege.util import WeightedRandomGenerator, Random


class TreasureSystem(object):
    NAME = "treasure"

    def getName(self):
        return self.NAME

    def __init__(self):
        self.treasures = {}
        populateTreasure(self)
        for treasures in self.treasures.values():
            treasures.sort()

    def update(self, frameTime):
        pass

    def add(self, group, path, weight, cost, quantity=(1, 1)):
        try:
            self.treasures[group].append(Treasure(path, weight, cost, quantity))
        except KeyError:
            self.treasures[group] = []
            self.treasures[group].append(Treasure(path, weight, cost, quantity))

    def getChest(self, quality):
        if quality > 150:
            return "large_gold_chest"
        elif quality > 100:
            return "small_gold_chest"
        elif quality > 50:
            return "large_silver_chest"
        else:
            return "small_silver_chest"

    def generate(self, group, quality, realm, area, onSurface=False, isUnderground=False):
        chest = self.getChest(quality)
        items = self.getItemsForQuality(group, quality)
        return self.create(chest, items, realm, area, onSurface, isUnderground)

    def create(self, chest, items, realm, area, onSurface=False, isUnderground=False):
        content = game.content.get(chest)
        entity = placeContentInArea(realm, content.entity, area, onSurface, isUnderground)
        if entity:
            self.fillChestWithItems(entity, items)
        return entity

    def fillChestWithItems(self, entity, items):
        for item in items:
            itemEntity = item.entity
            if itemEntity.item.isUnique:
                if itemEntity.has('equipment'):
                    quality = Random.get(20, 100)
                    itemEntity = game.equipment.create(item.content, quality)
                else:
                    itemEntity = game.entity.create(item.content)
            entity.inventory.add(itemEntity, item.quantity)

    def getItemsForQuality(self, group, quality):
        """ Create a list of items based off of quality. """

        items = []
        potentials = []
        weights = []

        for treasure in self.treasures[group]:
            if treasure.cost > quality:
                break
            potentials.append(treasure)
            weights.append(treasure.weight)

        while quality > 0 and potentials:
            index = WeightedRandomGenerator(weights)()
            treasure = potentials[index]
            if quality >= treasure.cost * treasure.quantities[0]:
                quantities = (treasure.quantities[0], min(treasure.quantities[1], quality / treasure.cost))
                quantity = quantities[0] if quantities[0] == quantities[1] else Random.get(quantities[0], quantities[1])
                items.append(InventoryItem(treasure.path, quantity))
                quality -= quantity * treasure.cost
            del potentials[index]
            del weights[index]

        return items

    @staticmethod
    def register(world):
        if NetworkManager.isHost():
            game.registerSystem(TreasureSystem.NAME, TreasureSystem())

    @staticmethod
    def unregister(world):
        if game.hasSystem(TreasureSystem.NAME):
            game.unregisterSystem(TreasureSystem.NAME)


class Treasure(object):
    def __init__(self, path, weight, cost, quantities):
        self.path = path
        self.weight = weight
        self.cost = cost
        self.quantities = quantities

    def __repr__(self):
        return "<{0}(path='{1.path}', quantities={1.quantities})>".format(self.__class__.__name__, self)

    def __cmp__(self, other):
        return self.cost - other.cost


def populateTreasure(treasure):
    #Common
    treasure.add("basic", "torch", 100, 4, (1, 5))
    treasure.add("basic", "oil_clot", 100, 4, (1, 4))
    treasure.add("basic", "wood", 80, 4, (2, 5))
    treasure.add("basic", "lumber", 70, 1, (4, 15))
    treasure.add("basic", "silk", 50, 6, (1, 2))
    treasure.add("basic", "bone", 40, 4, (1, 4))
    treasure.add("basic", "feather", 40, 4, (1, 4))
    treasure.add("basic", "cloth", 40, 4, (1, 3))
    treasure.add("basic", "way_shard", 40, 4, (1, 2))
    treasure.add("basic", "leather", 40, 5, (1, 3))
    treasure.add("basic", "glass", 30, 4, (1, 4))

    #Equipment
    treasure.add("gear", "broadsword", 8, 14)
    treasure.add("gear", "studded_vest", 10, 16)
    treasure.add("gear", "studded_helm", 15, 12)
    treasure.add("gear", "studded_breeches", 15, 14)
