import io
from s4studio.core import Serializable, ExternalResource, PackedResource, ResourceKey, Resource
from s4studio.io import StreamWrapper, StreamReader, TGIList, StreamWriter,StreamPtr
from s4studio.material import Preset, DDSResource
from s4studio.model import VisualProxy


class ComplateElement(object):
    def __init__(self):
        self.preset = Preset.Element()
        self.priority = 0
class ComplateEncoder(object):
    complate_strings = (
        "",
        "filename",
        "X:",
        "-1",

        "assetRoot",
        "daeFileName",
        "daeFilePath",
        "Color",

        "ObjectRgbMask",
        "rgbmask",
        "specmap",
        "Background Image",

        "HSVShift Bg",
        "H Bg",
        "V Bg",
        "S Bg",


        "Base H Bg",
        "Base V Bg",
        "Base S Bg",
        "Mask",

        "Multiplier",
        "Dirt Layer",
        "1X Multiplier",
        "Specular",

        "Overlay",
        "Face",
        "partType",
        "gender",

        "bodyType",
        "age",
        "A",
        "M",


        "Stencil A",
        "Stencil B",
        "Stencil C",
        "Stencil D",

        "Stencil A Enabled",
        "Stencil B Enabled",
        "Stencil C Enabled",
        "Stencil D Enabled",

        "Stencil A Tiling",
        "Stencil B Tiling",
        "Stencil C Tiling",
        "Stencil D Tiling",

        "Stencil A Rotation",
        "Stencil B Rotation",
        "Stencil C Rotation",
        "Stencil D Rotation",


        "Pattern A",
        "Pattern B",
        "Pattern C",
        "Pattern A Enabled",

        "Pattern B Enabled",
        "Pattern C Enabled",
        "Pattern A Linked",
        "Pattern B Linked",

        "Pattern C Linked",
        "Pattern A Rotation",
        "Pattern B Rotation",
        "Pattern C Rotation",

        "Pattern A Tiling",
        "Pattern B Tiling",
        "Pattern C Tiling",
        "?0x3F",


        "",
        "MaskWidth",
        "MaskHeight",
        "ObjectRgbaMask",

        "RndColors",
        "Flat Color",
        "Alpha",
        "Color 0",

        "Color 1",
        "Color 2",
        "Color 3",
        "Color 4",

        "Channel 1",
        "Channel 2",
        "Channel 3",
        "Pattern D",


        "Pattern D Tiling",
        "Pattern D Enabled",
        "Pattern D Linked",
        "Pattern D Rotation",

        "HSVShift 1",
        "HSVShift 2",
        "HSVShift 3",
        "Channel 1 Enabled",

        "Channel 2 Enabled",
        "Channel 3 Enabled",
        "Base H 1",
        "Base V 1",

        "Base S 1",
        "Base H 2",
        "Base V 2",
        "Base S 2",


        "Base H 3",
        "Base V 3",
        "Base S 3",
        "H 1",

        "S 1",
        "V 1",
        "H 2",
        "S 2",

        "V 2",
        "H 3",
        "V 3",
        "S 3",

        "true",
        "1,0,0,0",
        "defaultFlatColor",
        "solidColor_1"

        )
    complate_string_lookup = {}

    for string_index,string in enumerate(complate_strings):
        complate_string_lookup[string_index] = string
        complate_string_lookup[string] = string_index

    def deserialize(self,stream,parent_tgi):
        def read_element(s,tgi_list):
            def read_complate_string(s):
                a = s.i8()
                if not a: return None
                if a & 0x80: return s.chars(s.i8() if a & 0x40 else a &0x3F)
                if a & 0x40: a = (a & 0x3F) + s.i8()
                return self.complate_string_lookup[a]
            def read_typecode(s,tgi_list):
                tc = s.u8()
                if   tc == 1: return read_complate_string(s)
                elif tc == 0x02: return [s.u8() for i in range(4)]
                elif tc == 0x03: return tgi_list.get_resource(s.i8())
                elif tc == 0x04: return s.f32()
                elif tc == 0x05: return [s.f32() for i in range(2)]
                elif tc == 0x06: return [s.f32() for i in range(3)]
                elif tc == 0x07: return bool(s.i8())
                else: raise Exception("Unknown typecode %02X"%tc)
            element = Preset.Element()
            element.resource = tgi_list.get_resource(s.u8())
            element.name = read_complate_string(s)
            element.variable = read_complate_string(s)

            for i in range(s.i32()):
                name = read_complate_string(s)
                value = read_typecode(s,tgi_list)
                element.values[name] =value
            element.patterns = [read_element(s,tgi_list) for i in range(s.i32())]
            return element
        s = StreamReader(stream)
        unk = s.i16()
        preset_tgi = TGIList(use_length=True)
        preset_tgi.begin_read(stream)
        element = read_element(s,preset_tgi)
        preset_tgi.end_read(stream)
        complate = ComplateElement()
        complate.preset = element
        complate.priority = unk
        return complate

    def serialize(self,complate,stream,resources):
        def write_element(s,tgi_list):
            def write_complate_string(string,s):
                if not string:
                    s.i8(0)
                    return
                if string in self.complate_string_lookup:
                    idx = self.complate_string_lookup[string]
                    if idx > 0x40:
                        s.i8(0x40)
                    s.i8(idx &0x3F)
                else:
                    x = len(string)


                pass
            def write_typecode(value,s,tgi_list):
                if isinstance(value,str):
                    s.i8(0x01)
                    write_complate_string(value,s)
                elif isinstance(value,list):
                    if len(value) == 4:
                        s.i8(0x02)
                        for e in value: s.u8(e)
                    elif len(value) == 2:
                        s.i8(0x05)
                        for e in value: s.f32(e)
                    elif len(value) == 3:
                        s.i8(0x06)
                        for e in value: s.f32(e)
                elif isinstance(value,Resource):
                    s.i8(0x03)
                    s.i8(tgi_list.get_resource_index(value))
                elif isinstance(value,float):
                    s.i8(0x04)
                    s.f32(value)
                elif isinstance(value,bool):
                    s.i8(0x07)
                    s.i8(1 if value else 0)
                else:
                    raise Exception ("Unable to handle typecode data %" %value)


                pass

            pass
        assert isinstance(complate,ComplateElement)
        s= StreamWriter(stream)
        s.i16(complate.priority)
        preset_tgi = TGIList(use_length=True)
        preset_tgi.begin_write(stream)

        raise NotImplementedError()

class ProductInfo(Serializable):
    def __init__(self, stream=None, resources=None):
        self.version = 0x0000000C
        self.name_guid = 0
        self.desc_guid = 0
        self.name_key = ''
        self.desc_key = ''
        self.price = 0.0
        self.niceness_multiplier = 1.0
        self.crap_score = 0.0
        self.status_flags = 0
        self.icon = 0x0000000000000000
        self.environment_score = 0.0
        self.fire_type = 0
        self.is_stealable = False
        self.is_reposessable = False
        self.ui_sort_index = 0
        self.is_placeable_on_roof = False       #0x0000000D
        self.is_visible_in_worldbuilder = False #0x0000000E
        self.product_name = 0                   #0x0000000F
        Serializable.__init__(self,stream,None)
    def read(self, stream, resources=None):
        s = StreamReader(stream)
        self.version = s.u32()
        self.name_guid = s.u64()
        self.desc_guid = s.u64()
        self.name_key = s.s7(size=16,order='>')
        self.desc_key = s.s7(size=16,order='>')
        self.price = s.f32()
        self.niceness_multiplier = s.f32()
        self.crap_score = s.f32()
        self.status_flags = s.u8()
        self.icon = s.u64()
        assert s.u8() == 0
        self.environment_score = s.f32()
        self.fire_type = s.u32()
        self.is_stealable = bool(s.i8())
        self.is_reposessable = bool(s.i8())
        self.ui_sort_index = s.u32()
        if self.version >= 0x0000000D: self.is_placeable_on_roof = bool(s.u8())
        if self.version >= 0x0000000E: self.is_visible_in_worldbuilder = bool(s.u8())
        if self.version >= 0x0000000F: self.product_name = s.u32()

class ProductBase(PackedResource):
    def __init__(self, key=None, stream=None, resources=None, name=None):
        self.presets = []
        self.product_info = ProductInfo()
        PackedResource.__init__(self,key,stream,resources,name)

    class BuildBuyPreset(Preset):
        def __init__(self):
            self.id = 0
            self.unk1 = 1
            self.unk2 = 0
            Preset.__init__(self)
    @classmethod
    def read_presets(cls,stream,resources=None):
        s = StreamReader(stream)
        c = s.i32()
        ce = ComplateEncoder()
        presets = []
        for i in range(c):
            preset = cls.BuildBuyPreset()
            preset.unk1 = s.i8()
            if preset.unk1 != 1:
                preset.unk2 = s.i32()
            preset_ptr = StreamPtr.begin_read(s,relative=True,offset_start=True)
            preset.complate = ce.deserialize(stream,resources)
            preset_ptr.end()
            preset.id = s.u32()
            presets.append(preset)
        return presets

    @classmethod
    def write_presets(cls, stream,presets, resources):
        s = StreamWriter(stream)
        s.i32(len(presets))
        ce = ComplateEncoder()
        for preset in presets:
            assert isinstance(preset,cls.BuildBuyPreset)
            s.i8(preset.unk1)
            if preset.unk1 != 1:
                s.i32(preset.unk2)
            preset_ptr = StreamPtr.begin_write(s)
            ce.serialize(preset.complate,stream,resources)
            preset_ptr.end()
            s.u32(preset.id)

class CatalogProductObject(ProductBase):
    ID = 0x319E4F1D

    class ProductRating(Serializable):
        def __init__(self,stream=None,resources=None):
            self.topic = 0x00000000
            self.rating = 0x00000000
            Serializable.__init__(self,stream,resources)
        def read(self, stream, resources=None):
            s = StreamReader(stream)
            self.topic = s.u32()
            self.rating = s.u32()
        def write(self, stream, resources=None):
            s = StreamWriter(stream)
            s.u32(self.topic)
            s.u32(self.rating)

    class WallMaskEntry(Serializable):
        def __init__(self,stream=None,resources=None):
            self.unknown = [0.0] * 4
            self.level_offset = 0
            self.wall_mask_texture = ExternalResource(ResourceKey(DDSResource.ID))
            Serializable.__init__(self,stream,resources)
        def read(self, stream, resources=None):
            s = StreamReader(stream)
            self.unknown = [s.f32() for i in range(4)]
            self.level_offset = s.i32()
            self.wall_mask_texture = resources.get_resource(s.i32())
    def __init__(self, key=None, stream=None, resources=None, name=None):
        self.version = 0x00000001B
        self.instance_name = ""                                                             #version >= 0x00000016
        self.object_component = ExternalResource(ResourceKey())
        self.object_type_flags = 0x00000000
        self.object_type_flags_2 = 0x00000000                                               #version >= 0x0000001A
        self.wall_placement_flags = 0x00000000
        self.movement_flags = 0x00000000
        self.num_wall_cutout_tiles_per_level = 0
        self.num_levels = 0
        self.wall_masks = []
        self.script_enabled = True
        self.diagonal_object = ExternalResource(ResourceKey(CatalogProductObject.ID))
        self.ambiance_type = ''
        self.room_flags = 0x00000000
        self.function_category_flags = 0x00000000
        self.sub_category_flags = 0x0000000000000000
        self.sub_category_flags_2 = 0x0000000000000000                                      #version >= 0x0000001C
        self.sub_room_flags = 0x00000000
        self.build_category_flags = 0x00000000
        self.wall_cutout_texture = ExternalResource(key= ResourceKey(DDSResource.ID))
        self.floor_cutout_texture =ExternalResource(key= ResourceKey(DDSResource.ID))       #version >= 0x00000017
        self.floor_cutout_level_offset = 0                                                  #version >= 0x00000017
        self.floor_cutout_bounds_length = 0.0                                               #version >= 0x00000017
        self.floor_cutout_bounds_width = 0.0                                                #version >= 0x00000020
        self.floor_cutout_offset_x = 0.0                                                    #version >= 0x00000021
        self.floor_cutout_offset_z = 0.0                                                    #version >= 0x00000021
        self.shell_states = []                                                              #version >= 0x00000018
        self.shell_level_below = ExternalResource(ResourceKey(CatalogProductObject.ID))     #version >= 0x00000019
        self.shell_proxy = ExternalResource(ResourceKey(CatalogProductObject.ID))           #version >= 0x0000001B
        self.blueprint_xml = ExternalResource(ResourceKey(CatalogProductObject.ID))         #version >= 0x0000001D
        self.blueprint_icon = ExternalResource(ResourceKey(CatalogProductObject.ID))        #version >= 0x0000001E
        self.blueprint_icon_offset_min_x = 0.0                                              #version >= 0x0000001F
        self.blueprint_icon_offset_min_z = 0.0                                              #version >= 0x0000001F
        self.blueprint_icon_offset_max_x = 0.0                                              #version >= 0x0000001F
        self.blueprint_icon_offset_max_z = 0.0                                              #version >= 0x0000001F
        self.slot_placement_flags = 0x00000000
        self.surface_type = ''
        self.source_material = ''
        self.moodlet_given = 0x00000000
        self.moodlet_score = 0x00000000
        self.ratings = []
        self.fallback = ExternalResource(ResourceKey(CatalogProductObject.ID))
        self.modular_arch_end_east_model = ExternalResource(ResourceKey(VisualProxy.ID))    #version >= 0x00000022
        self.modular_arch_end_west_model = ExternalResource(ResourceKey(VisualProxy.ID))    #version >= 0x00000022
        self.modular_arch_connecting_model = ExternalResource(ResourceKey(VisualProxy.ID))  #version >= 0x00000022
        self.modular_arch_single_model = ExternalResource(ResourceKey(VisualProxy.ID))      #version >= 0x00000022
        ProductBase.__init__(self,key,stream,resources,name)

    def read(self, stream, resources=None):
        s = StreamReader(stream)
        self.version = s.u32()
        tgi = TGIList()
        tgi.begin_read(stream)
        self.presets = ProductBase.read_presets(stream,tgi)
        if self.version >= 0x00000016:
            self.instance_name = s.s7(size=16,order='>')
        self.product_info = ProductInfo()
        self.product_info.read(stream,tgi)
        self.object_component = tgi.get_resource(s.i32())
        self.object_type_flags = s.u32()
        if self.version >= 0x00000001A:
            self.object_type_flags_2 = s.u32()
        self.wall_placement_flags = s.u32()
        self.movement_flags = s.u32()
        self.num_wall_cutout_tiles_per_level = s.i32()
        self.num_levels = s.i32()
        self.wall_masks = [self.WallMaskEntry(stream,tgi) for i in range(s.i8())]
        self.script_enabled = s.i8() == 1
        self.diagonal_object = tgi.get_resource(s.i32())
        self.ambiance_type = s.hash()
        self.room_flags = s.u32()
        self.function_category_flags = s.u32()
        self.sub_category_flags = s.u64()
        if self.version >= 0x0000001C:
            self.sub_category_flags_2 = s.u64()
        self.sub_room_flags = s.u64()
        self.build_category_flags = s.u32()
        self.wall_cutout_texture = tgi.get_resource(s.i32())
        if self.version >= 0x00000017:
            self.floor_cutout_texture = tgi.get_resource(s.i32())
            self.floor_cutout_level_offset = s.i32()
            self.floor_cutout_bounds_length = s.f32()
        if self.version >= 0x00000020:
            self.floor_cutout_bounds_width = s.f32()
        if self.version >= 0x0000021:
            self.floor_cutout_offset_x = s.f32()
            self.floor_cutout_offset_z = s.f32()
        if self.version >= 0x00000018:
            self.shell_states = [s.hash() for i in range(s.i32())]
        if self.version >= 0x00000019:
            self.shell_level_below =tgi.get_resource(s.i32())
        if self.version >= 0x0000001B:
            self.shell_proxy =tgi.get_resource(s.i32())
        if self.version >= 0x0000001D:
            self.blueprint_xml =tgi.get_resource(s.i32())
        if self.version >= 0x0000001E:
            self.blueprint_icon =tgi.get_resource(s.i32())
        if self.version >= 0x0000001F:
            self.blueprint_icon_offset_min_x = s.f32()
            self.blueprint_icon_offset_min_z = s.f32()
            self.blueprint_icon_offset_max_x = s.f32()
            self.blueprint_icon_offset_max_z = s.f32()
        self.slot_placement_flags = s.u32()
        self.surface_type = s.s7(size=16,order='>')
        self.source_material = s.s7(size=16,order='>')
        self.moodlet_given = s.u32()
        self.moodlet_score = s.u32()
        assert s.u32() == 5
        self.ratings = [self.ProductRating(stream) for i in range(5)]
        self.fallback = tgi.get_resource(s.i32())
        if self.version >= 0x00000022:
            self.modular_arch_end_east_model = tgi.get_resource(s.i32())
            self.modular_arch_end_west_model = tgi.get_resource(s.i32())
            self.modular_arch_connecting_model = tgi.get_resource(s.i32())
            self.modular_arch_single_model = tgi.get_resource(s.i32())
        tgi.end_read(stream)

    def write(self, stream, resources=None):
        s = StreamWriter(stream)
        s.u32(self.version)
        tgi = TGIList()
        tgi.begin_write(stream)
        ProductBase.write_presets(stream,self.presets,tgi)
        if self.version >= 0x00000016:
            s.s7(self.instance_name,size=16,order='>')
        self.product_info.write(stream,tgi)
        s.i32(tgi.get_resource(self.object_component))
        s.u32(self.object_type_flags)
        if self.version >= 0x000001A:
            s.u32(self.object_type_flags_2)
        s.u32(self.wall_placement_flags)
        s.u32(self.movement_flags)
        s.i32(self.num_wall_cutout_tiles_per_level)
        s.i32(self.num_levels)
        s.i8(len(self.wall_masks))
        for wall_mask in self.wall_masks:
            wall_mask.write(stream,tgi)
        s.i8(1 if self.script_enabled else 0)
        s.i32(tgi.get_resource_index(self.diagonal_object))
        s.hash(self.ambiance_type)
        s.u32(self.room_flags)
        s.u32(self.function_category_flags)
        s.u64(self.sub_category_flags)
        if self.version >= 0x0000001C:
            s.u64(self.sub_category_flags_2)
        s.u64(self.sub_room_flags)
        s.u32(self.build_category_flags)
        s.i32(tgi.get_resource_index(self.wall_cutout_texture))
        if self.version >= 0x00000017:
            s.i32(tgi.get_resource_index(self.floor_cutout_texture))
            s.i32(self.floor_cutout_level_offset)
            s.f32(self.floor_cutout_bounds_length )
        if self.version >= 0x00000020:
            s.f32(self.floor_cutout_bounds_width )
        if self.version >= 0x0000021:
            s.f32(self.floor_cutout_offset_x )
            s.f32(self.floor_cutout_offset_z )
        if self.version >= 0x00000018:
            s.i32(len(self.shell_states))
            for shell_state in self.shell_states: s.hash(shell_state)
        if self.version >= 0x00000019:
            s.i32(tgi.get_resource_index(self.shell_level_below ))
        if self.version >= 0x0000001B:
            s.i32(tgi.get_resource_index(self.shell_proxy ))
        if self.version >= 0x0000001D:
            s.i32(tgi.get_resource_index(self.blueprint_xml ))
        if self.version >= 0x0000001E:
            s.i32(tgi.get_resource_index(self.blueprint_icon ))
        if self.version >= 0x0000001F:
            s.f32(self.blueprint_icon_offset_min_x)
            s.f32(self.blueprint_icon_offset_min_z)
            s.f32(self.blueprint_icon_offset_max_x)
            s.f32(self.blueprint_icon_offset_max_z)
        s.u32(self.slot_placement_flags)
        s.s7(self.surface_type,size=16,order='>')
        s.s7(self.source_material,size=16,order='>')
        s.u32(self.moodlet_given)
        s.u32(self.moodlet_score)
        s.u32(5)
        for rating in self.ratings: rating.write(stream)
        s.i32(tgi.get_resource_index(self.fallback))
        if self.version >= 0x00000022:
            s.i32(tgi.get_resource_index(self.modular_arch_end_east_model))
            s.i32(tgi.get_resource_index(self.modular_arch_end_east_model))
            s.i32(tgi.get_resource_index(self.modular_arch_connecting_model))
            s.i32(tgi.get_resource_index(self.modular_arch_single_model))
        tgi.end_write(stream)


            


class CatalogProductStairs(ProductBase):
    ID= 0x049CA4CD
    def __init__(self, key=None, stream=None, resources=None, name=None):
        self.version = 0x000000003
        self.steps_4x_model = None
        self.steps_1x_model = None
        self.wall_cap_model = None
        self.railing = None
        self.wall = None
        self.floor = None
        self.fence = None
        ProductBase.__init__(self,key,stream,resources,name)

    def read(self, stream, resources=None):
        s = StreamReader(stream)
        self.version = s.u32()
        tgi = TGIList(package=resources)
        tgi.begin_read(stream)
        if self.version >= 0x00000003:
            self.presets = ProductBase.read_presets(stream,tgi)
        self.product_info.read(stream,resources)
        self.steps_4x_model = tgi.get_resource(s.i32())
        self.steps_1x_model = tgi.get_resource(s.i32())
        self.wall_cap_model = tgi.get_resource(s.i32())
        self.railing = tgi.get_resource(s.i32())
        self.wall = tgi.get_resource(s.i32())
        self.floor = tgi.get_resource(s.i32())
        self.fence = tgi.get_resource(s.i32())
        tgi.end_read(stream)
    def write(self,stream,resources=None):
        s = StreamWriter(stream)
        s.u32(self.version)
        tgi = TGIList()
        tgi.begin_write(stream)
        if self.version >= 0x00000003:
            ProductBase.write_presets(stream,self.presets,tgi)
        self.product_info.write(stream,tgi)
        s.i32(tgi.get_resource_index(self.steps_4x_model))
        s.i32(tgi.get_resource_index(self.steps_1x_model))
        s.i32(tgi.get_resource_index(self.wall_cap_model))
        s.i32(tgi.get_resource_index(self.railing))
        s.i32(tgi.get_resource_index(self.wall))
        s.i32(tgi.get_resource_index(self.floor))
        s.i32(tgi.get_resource_index(self.fence))
        tgi.end_write(stream)


class CatalogProductFence(ProductBase):
    ID=0x0418FE2A
    def __init__(self, key=None, stream=None, resources=None, name=None):
        self.version = 0x000000008
        self.model = None
        self.diagonal_model = None
        self.post_model = None
        self.post_tile_spacing = 0
        self.can_walk_over = False

        self.should_not_get_thick_snow = False
        self.snow_post_shape_is_circle = False
        self.snow_thickness_post_scale_factor = 0.0
        self.snow_thickness_rail_scale_factor = 0.0
        self.snow_thickness_post_vertical_offset= 0.0
        self.snow_thickness_rail_vertical_offset = 0.0
        self.has_wall = False

        self.raise_fence_geometry_above_wall = False
        self.wall = None

        ProductBase.__init__(self,key,stream,resources,name)
    def read(self, stream, resources=None):
        s = StreamReader(stream)
        self.version = s.u32()
        tgi = TGIList(package=resources)
        tgi.begin_read(stream)
        if self.version >= 0x00000007:
            self.presets = ProductBase.read_presets(stream,tgi)
        self.product_info = ProductInfo()
        self.product_info.read(stream,tgi)
        self.model = tgi.get_resource(s.i32())
        self.diagonal_model = tgi.get_resource(s.i32())
        self.post_model = tgi.get_resource(s.i32())
        self.post_tile_spacing = s.i32()
        self.can_walk_over = s.i8() == 1

        if self.version >= 0x00000008:
            if self.version >= 0x000000A:
                self.should_not_get_thick_snow = s.i8() == 1
                self.snow_post_shape_is_circle = s.i8()==1
                self.snow_thickness_post_scale_factor = s.f32()
                self.snow_thickness_rail_scale_factor = s.f32()
                self.snow_thickness_post_vertical_offset = s.f32()
                self.snow_thickness_rail_vertical_offset = s.f32()
                self.has_wall = s.i8() == 1
            if self.version < 0x000000A or self.has_wall:
                self.raise_fence_geometry_above_wall = s.i8()== 1
                self.wall = tgi.get_resource(s.i32())
        tgi.end_read(stream)

    def write(self, stream, resources=None):
        s = StreamWriter(stream)
        s.u32(self.version)
        tgi = TGIList()
        tgi.begin_write(stream)
        if self.version >= 0x00000007:
            ProductBase.write_presets(stream,self.presets,tgi)
        self.product_info.write(stream,tgi)

        s.i32(tgi.get_resource_index(self.model))
        s.i32(tgi.get_resource_index(self.diagonal_model))
        s.i32(tgi.get_resource_index(self.post_model))
        s.i32(self.post_tile_spacing)
        s.i8(1 if self.can_walk_over else 0)

        if self.version >= 0x00000008:
            if self.version >= 0x0000000A:
                s.i8(1 if self.should_not_get_thick_snow else 0)
                s.i8(1 if self.snow_post_shape_is_circle else 0)
                s.f32(self.snow_thickness_post_scale_factor)
                s.f32(self.snow_thickness_rail_scale_factor)
                s.f32(self.snow_thickness_post_vertical_offset)
                s.f32(self.snow_thickness_rail_vertical_offset)
                s.i8(1 if self.has_wall else 0)
            if self.version < 0x0000000A or self.has_wall:
                s.i8(1 if self.raise_fence_geometry_above_wall else 0)
                s.i32(tgi.get_resource_index(self.wall))
        tgi.end_write(stream)


class CatalogProductRailing(ProductBase):
    ID=0x04C58103
    def __init__(self, key=None, stream=None, resources=None, name=None):
        self.version = 0x000000003
        self.railing_4x_model = None
        self.railing_1x_model = None
        self.post_model = None
        ProductBase.__init__(self,key,stream,resources,name)
    def read(self, stream, resources=None):
        s = StreamReader(stream)
        self.version = s.u32()
        tgi = TGIList(package=resources)
        tgi.begin_read(stream)
        if self.version >= 0x00000003:
            self.presets = ProductBase.read_presets(stream,tgi)
        self.product_info = ProductInfo()
        self.product_info.read(stream,tgi)
        self.railing_4x_model = tgi.get_resource(s.i32())
        self.railing_1x_model = tgi.get_resource(s.i32())
        self.post_model = tgi.get_resource(s.i32())
        tgi.end_read(stream)
    def write(self, stream, resources=None):
        s = StreamWriter(stream)
        s.u32(self.version)
        tgi = TGIList()
        tgi.begin_write(stream)
        if self.version >= 0x00000003:
            ProductBase.write_presets(stream,self.presets,tgi)
        self.product_info.write(stream,tgi)
        s.i32(tgi.get_resource_index(self.railing_4x_model))
        s.i32(tgi.get_resource_index(self.railing_1x_model))
        s.i32(tgi.get_resource_index(self.post_model))
        tgi.end_write(stream)



class CatalogProductFireplace(ProductBase):
    ID=0x04F3CC01
    def __init__(self, key=None, stream=None, resources=None, name=None):
        self.version = 0x000000003
        self.fireplace_width = 2
        self.mantle = None
        self.chimney_mantle = None
        self.chimney_full_level = None
        self.chimney_ground_level = None
        self.chimney_body = None
        self.chimney_top = None
        self.chimney_cap = None
        ProductBase.__init__(self,key,stream,resources,name)
    def read(self, stream, resources=None):
        s = StreamReader(stream)
        self.version = s.u32()
        tgi = TGIList(package=resources)
        tgi.begin_read(stream)
        self.product_info = ProductInfo()
        self.product_info.read(stream,tgi)

        self.fireplace_width = s.i8()
        self.mantle =  tgi.get_resource(s.i32())
        self.chimney_mantle =  tgi.get_resource(s.i32())
        self.chimney_full_level =  tgi.get_resource(s.i32())
        self.chimney_ground_level =  tgi.get_resource(s.i32())
        self.chimney_body =  tgi.get_resource(s.i32())
        self.chimney_top =  tgi.get_resource(s.i32())
        self.chimney_cap =  tgi.get_resource(s.i32())
        tgi.end_read(stream)
    def write(self, stream, resources=None):
        s = StreamWriter(stream)
        s.u32(self.version)
        tgi = TGIList()
        tgi.begin_write(stream)
        self.product_info.write(stream,tgi)

        s.i8(self.fireplace_width)
        s.i32(tgi.get_resource_index(self.mantle))
        s.i32(tgi.get_resource_index(self.chimney_mantle))
        s.i32(tgi.get_resource_index(self.chimney_full_level))
        s.i32(tgi.get_resource_index(self.chimney_ground_level))
        s.i32(tgi.get_resource_index(self.chimney_body))
        s.i32(tgi.get_resource_index(self.chimney_top))
        s.i32(tgi.get_resource_index(self.chimney_cap))

        tgi.end_write(stream)
