import copy
from typing import List

from pyedm_platform_selector import pyedm

from logger import log
from materials.material_interface import IMaterial, get_transparency_value
from materials.material_wrap import DeckMaterialWrap
from serializer import SLink, SInput, get_first_socket_by_name
from enums import NodeSocketInDefaultEnum, NodeSocketInDeckEnum, NodeSocketCommonEnum, NodeGroupTypeEnum
from version_specific import get_version
from objects_custom_props import get_edm_props

# --- Deck
class DeckMaterial(IMaterial):
    name = NodeGroupTypeEnum.DECK
    description_file_name = 'data/EDM_Deck_Material.pickle'
    factory = DeckMaterialWrap

    @classmethod
    def build_blocks(cls, object, material_wrap, mesh_storage):
        edm_render_node = pyedm.DeckNode(object.name, material_wrap.material.name)
        edm_render_node.setPositions(mesh_storage.positions)
        edm_render_node.setNormals(mesh_storage.normals)
        edm_render_node.setIndices(mesh_storage.indices)

        transparency_mode: int = get_transparency_value(material_wrap.values.blend_mode.value)
        edm_render_node.setTransparentMode(transparency_mode)

        decal_id: int = material_wrap.values.decal_id.value
        if(decal_id < 0 or decal_id > 8):
            log.fatal(f"{material_wrap.name} material has wrong value {str(decal_id)}. Decal id must be in 0 to 8 range.")
        edm_render_node.setDecalId(decal_id)

        if material_wrap.textures.base_tile_map.texture:
            base_tile_uv_map_name: str = material_wrap.textures.base_tile_map.texture.get_uv_map(mesh_storage.uv_active)
            edm_render_node.setTiledUV(mesh_storage.uv[base_tile_uv_map_name])

            base_tile_map_name: str = material_wrap.textures.base_tile_map.texture.texture_name
            edm_render_node.setBaseTiledMap(base_tile_map_name)

        if material_wrap.textures.normal_tile_map.texture:
            normal_tile_map_name: str = material_wrap.textures.normal_tile_map.texture.texture_name
            edm_render_node.setNormalTiledMap(normal_tile_map_name)

        if material_wrap.textures.rmo_tile_map.texture:
            rmo_tile_map_name: str = material_wrap.textures.rmo_tile_map.texture.texture_name
            edm_render_node.setAormsTiledMap(rmo_tile_map_name)

        if material_wrap.textures.decal_map.texture:
            base_uv_map_name: str = material_wrap.textures.decal_map.texture.get_uv_map(mesh_storage.uv_active)
            edm_render_node.setRegularUV(mesh_storage.uv[base_uv_map_name])

            base_map_name: str = material_wrap.textures.decal_map.texture.texture_name
            edm_render_node.setBaseMap(base_map_name)

        if material_wrap.textures.decal_rmo.texture:
            rmo_map_name: str = material_wrap.textures.decal_rmo.texture.texture_name
            edm_render_node.setAormsMap(rmo_map_name)

        if material_wrap.textures.damage_color.texture:
            damage_map_name: str = material_wrap.textures.damage_color.texture.texture_name
            edm_render_node.setDamageMap(damage_map_name)

        if material_wrap.textures.damage_mask.texture:
            damage_mask_name: str = material_wrap.textures.damage_mask.texture.texture_name
            edm_render_node.setDamageMaskRGBA(damage_mask_name)

        if material_wrap.textures.rain_mask.texture:
            rain_mask_name: str = material_wrap.textures.rain_mask.texture.texture_name
            edm_render_node.setRainMask(rain_mask_name)

        edm_props = get_edm_props(object)
        edm_render_node.setArgument(edm_props.DAMAGE_ARG)

        return edm_render_node

    @classmethod
    def process_links(cls, old_links, old_version, group_node_type_name):
        new_links: List[SLink] = []
        
        if old_version < 7:
            for link in old_links:
                if link.to_type == 'ShaderNodeGroup':
                    if link.to_socket == 'Damage Color':
                        link = copy.copy(link)
                        link.to_socket = NodeSocketInDefaultEnum.DAMAGE_COLOR
                    elif link.to_socket == 'Damage Map':
                        link = copy.copy(link)
                        link.to_socket = NodeSocketInDeckEnum.DAMAGE_MASK
                    elif link.to_socket == 'Damage Map (Non-Color)':
                        link = copy.copy(link)
                        link.to_socket = NodeSocketInDeckEnum.DAMAGE_MASK
                    elif link.to_socket == 'Damage Normal':
                        link = copy.copy(link)
                        link.to_socket = NodeSocketInDeckEnum.DAMAGE_NORMAL
                new_links.append(link)
        else:
            for link in old_links:
                new_links.append(link)

        return new_links

    @classmethod    
    def restore_defaults(cls, old_sockest, new_node_group, old_version, material_name):
        version_new: int = get_version(new_node_group.node_tree)
        if old_version >= 1:
            for new_socket in new_node_group.inputs:
                old_socket_wrp: SInput = get_first_socket_by_name(old_sockest, new_socket.name)
                if not old_socket_wrp:
                    continue
                if new_socket.name == NodeSocketCommonEnum.VERSION:
                    new_socket.default_value = version_new
                    continue
                if old_socket_wrp.instance_value and new_socket.name not in (NodeSocketInDeckEnum.TRANSPARENCY): 
                    new_socket.default_value = old_socket_wrp.instance_value
