from nbt import nbt
from nbt.nbt import (TAG_Short, TAG_Compound, TAG_String, TAG_List, TAG_Float,
    TAG_Byte, TAG_Long, TAG_Double, TAG_Int)
import mc_objects
import struct
import uuid


def get_tag_for_type(tag_type):
    if tag_type == 'Byte':
        return TAG_Byte
    elif tag_type == 'Int':
        return TAG_Int
    elif tag_type == 'Float':
        return TAG_Float
    elif tag_type == 'Short':
        return TAG_Short
    elif tag_type == 'Long':
        return TAG_Long
    elif tag_type == 'String':
        return TAG_String
    elif tag_type == 'List':
        return TAG_List
    elif tag_type == 'Compound':
        return TAG_Compound
    else:
        raise NotImplementedError(tag_type)


def load_spawn_potential_from_tag(tag):
    return SpawnPotential(load_mob_from_tag(tag['Entity']),
                          weight=tag['Weight'].value)

def load_spawner_from_tag(tag):
    potentials = []
    delay = tag['Delay'].value
    min_delay = tag['MinSpawnDelay'].value
    max_delay = tag['MaxSpawnDelay'].value
    spawn_count = tag['SpawnCount'].value
    spawn_range = tag['SpawnRange'].value
    if 'SpawnPotentials' in tag:
        potentials_subtag = tag['SpawnPotentials']
        for potent in potentials_subtag:
            potentials.append(load_spawn_potential_from_tag(potent))
    if 'MaxNearbyEntities' in tag:
        max_nearby_entities = tag['MaxNearbyEntities'].value
    else:
        max_nearby_entities = None
    if 'RequiredPlayerRange' in tag:
        required_player_range = tag['RequiredPlayerRange'].value
    else:
        required_player_range = None
    return Spawner(potentials, spawn_count=spawn_count,
                   spawn_range=spawn_range, delay=delay,
                   min_spawn_delay=min_delay, max_spawn_delay=max_delay,
                   required_player_range=required_player_range,
                   max_nearby_entities=max_nearby_entities)


def load_mob_from_tag(tag):
    attributes = []
    effects = []
    passengers = []
    mob_id = tag['id'].value
    if 'Attributes' in tag:
        attribute_tags = tag['Attributes']
        for attr in attribute_tags:
            attributes.append(Attribute(
                attr['AttributeName'].value, attr['Amount'].value,
                op_choice=attr['Operation'].value,
                attr_uuid=(attr['UUIDLeast'].value, attr['UUIDMost'].value)))
    if 'ActiveEffects' in tag:
        effect_tags = tag['ActiveEffects']
        for pot in effect_tags:
            effects.append(Effect(
                pot['id'].value, pot['Amplifier'].value,
                pot['Duration'].value,
                ambient=pot['Ambient'].value,
                show_particles=pot['ShowParticles'].value
                ))
    if 'Passengers' in tag:
        passenger_tags = tag['Passengers']
        for passenger in passenger_tags:
            passengers.append(load_mob_from_tag(passenger))
    if 'Glowing' in tag:
        glowing = tag['Glowing'].value
    else:
        glowing = False
    if 'LeftHanded' in tag:
        left_handed = tag['LeftHanded'].value
    else:
        left_handed = False
    if 'Silent' in tag:
        silent = tag['Silent'].value
    else:
        silent = False
    if 'CanPickUpLoot' in tag:
        can_pickup_loot = tag['CanPickUpLoot'].value
    else:
        can_pickup_loot = False
    if 'CustomNameVisible' in tag:
        custom_name_visible = tag['CustomNameVisible'].value
    else:
        custom_name_visible = False
    if 'CustomName' in tag:
        custom_name = tag['CustomName'].value
    else:
        custom_name = None
    if 'AbsorptionAmount' in tag:
        absorbtion_amount = tag['AbsorptionAmount'].value
    else:
        absorbtion_amount = 0.0
    if 'Health' in tag:
        health = tag['Health'].value
    else:
        health = 10.0
    if 'Fire' in tag:
        fire = tag['Fire'].value
    else:
        fire = -20.0
    if 'HandItems' in tag:
        hand_subtag = tag['HandItems']
        if len(hand_subtag[0]) <= 0:
            main_hand = None
        else:
            main_hand = load_item_from_tag(hand_subtag[0])
        if len(hand_subtag[1]) <= 0:
            off_hand = None
        else:
            off_hand = load_item_from_tag(hand_subtag[1])
    else:
        main_hand = None
        off_hand = None
    hand_items = {'MainHand': main_hand, 'OffHand': off_hand}
    if 'ArmorItems' in tag:
        armor_subtag = tag['ArmorItems']
        if len(armor_subtag[0]) <= 0:
            feet = None
        else:
            feet = load_item_from_tag(armor_subtag[0])
        if len(armor_subtag[1]) <= 0:
            legs = None
        else:
            legs = load_item_from_tag(armor_subtag[1])
        if len(armor_subtag[2]) <= 0:
            chest = None
        else:
            chest = load_item_from_tag(armor_subtag[2])
        if len(armor_subtag[3]) <= 0:
            head = None
        else:
            head = load_item_from_tag(armor_subtag[3])
    else:
        feet = None
        legs = None
        chest = None
        head = None
    armor_items= {'Feet': feet, 'Legs': legs, 'Chest': chest, 'Head': head}
    if 'HandDropChances' in tag:
        hand_drops = tag['HandDropChances']
        hand_drop_chances = {'MainHand': hand_drops[0].value, 
                             'OffHand': hand_drops[1].value}
    else:
        hand_drop_chances = {'MainHand': 0.0, 
                             'OffHand': 0.0}
    if 'ArmorDropChances' in tag:
        armor_drops = tag['ArmorDropChances']
        armor_drop_chances = {'Feet': armor_drops[0].value, 
                              'Legs': armor_drops[1].value,
                              'Chest': armor_drops[2].value, 
                              'Head': armor_drops[3].value}
    else:
        armor_drop_chances = {'Feet': 0.0, 
                              'Legs': 0.0,
                              'Chest': 0.0, 
                              'Head': 0.0}
    mc_mob = mc_objects.MOBS[mob_id]
    options = mc_mob.options
    additional_settings = {}
    for tag_name, option_type, tag_data, tag_type in options:
        if tag_name in tag:
            tag_value = tag[tag_name].value
        else:
            tag_value = 0