from s4studio.core import PackedResource, Serializable, Resource
from s4studio.helpers import FNV32
from s4studio.io import StreamReader, TGIList, StreamWriter


class ObjectComponentModel(PackedResource):
    ID = 0x02DC343F

    class Visibility(object):
        ALWAYS = 0x00
        TOOLS_ONLY = 0x01
        DISTANT_TERRAIN = 0x02

    component_list = {
        'Physics',
        'Sim',
        'Script',
        'Model',
        'Slot',
        'Sacs',
        'Location',
        'VisualState',
        'Transform',
        'Steering',
        'LotObject',
        'Effect',
        'Tree',
        'Footprint',
        'Lighting',
        'Animation'
    }
    component_hashes = {}
    for string in component_list:
        component_hashes[FNV32.hash(string)] = string


    def __init__(self, key=None, stream=None, resources=None, name=None):
        self.version = 0x0000007
        self.components = []
        self.component_data = {}
        self.visible = True
        PackedResource.__init__(self, key, stream, resources, name)

    def read(self, stream, resources=None):
        s = StreamReader(stream)
        s.version = s.u32()
        tgi = TGIList(package=resources)
        tgi.begin_read(stream)
        self.components = [s.hash(self.component_hashes) for i in range(s.i8())]
        self.component_data = {}

        def read_component_data():
            key = s.p32()
            val = None
            t = s.i8()
            if t == 0x00:
                val = t, s.p32()
            elif t == 0x01:
                val = t, tgi.get_resource(s.i32())
            elif t == 0x02:
                val = t, tgi.get_resource(s.i32())
            elif t == 0x03:
                val = t, s.p32()
            elif t == 0x04:
                val = t, s.u32()
            self.component_data[key] = val

        for i in range(s.i8()):
            read_component_data()
        self.visible = s.u8()
        tgi.end_read(stream)
        pass

    def write(self, stream, resources=None):
        s = StreamWriter(stream)
        s.u32(self.version)
        tgi = TGIList(package=resources)
        tgi.begin_write(stream)
        s.i8(len(self.components))
        for component in self.components: s.hash(component)

        def write_component_data(data):
            s.i8(data[0])
            val = data[1]
            if isinstance(val, str):
                s.p32(val)
            elif isinstance(val, Resource):
                s.i32(tgi.get_resource_index(val))
            elif isinstance(val, int):
                s.u32(val)
            else:
                raise Exception('Unable to handle data type %' % type(val))

        k = self.component_data.keys()
        s.i8(len(k))
        for key in k:
            s.p32(key)
            write_component_data(self.component_data[key])
        s.i8(self.visible)
        tgi.end_write(stream)

