import copy
from typing import List, Dict, Tuple, Union

from pyedm_platform_selector import pyedm

import utils
import animation as anim
from logger import log
from objects_custom_props import get_edm_props, EDMPropsGroup
from serializer import SLink, SInput, get_first_socket_by_name
from version_specific import get_version, IS_BLENDER_4, IS_BLENDER_3
from custom_sockets import TransparencyEnumItems, ShadowCasterEnumItems
from mesh_storage import MeshStorage
from materials.material_interface import IMaterial, get_transparency_value
from materials.material_wrap import DefMaterialWrap, MaterialWrap, AttachedTextureStruct
from enums import (
    ShaderNodeMappingInParams, 
    EDMCustomEmissiveTypeInt, 
    EdmTransparencySocketItemsEnum,
    NodeSocketInDefaultEnum, 
    NodeSocketInDeckEnum, 
    BpyShaderNode, 
    NodeSocketCommonEnum,
    NodeGroupTypeEnum,
)

def get_shadow_caster_value(shadow_caster_value) -> int:
    if shadow_caster_value == ShadowCasterEnumItems[0][0]:
        return 0
    elif shadow_caster_value == ShadowCasterEnumItems[1][0]:
        return 1
    elif shadow_caster_value == ShadowCasterEnumItems[2][0]:
        return 2
    else:
        return 0

def make_base_texture(mesh_storage: MeshStorage, mat_wrap: DefMaterialWrap, texture: AttachedTextureStruct) -> pyedm.BaseBlock:
    edm_base_bock = pyedm.BaseBlock()
    
    albedo_uv_map_name: str = texture.get_uv_map(mesh_storage.uv_active)
    albedo_map_name: str = texture.texture_name
    uv_shift_animation_path: str = texture.uv_move_node.inputs[ShaderNodeMappingInParams.LOCATION].path_from_id('default_value') if mat_wrap.valid and texture.uv_move_node else None
    arg_n: int = utils.extract_arg_number(texture.uv_move_node.label) if texture.uv_move_node else -1

    edm_base_bock.setAlbedoMapUV(mesh_storage.uv[albedo_uv_map_name])
    edm_base_bock.setAlbedoMap(albedo_map_name)

    is_uv_shift_animated: bool = uv_shift_animation_path and anim.has_path_anim(mat_wrap.material.node_tree.animation_data, uv_shift_animation_path)
    if is_uv_shift_animated and arg_n != -1:
        key_list: anim.KeyFramePoints = anim.extract_anim_vec3(mat_wrap.material.node_tree.animation_data.action, uv_shift_animation_path, (0.0, 0.0, 0.0), lambda v: [v[0], 1.0 - v[1]])
        uv_shift_prop = pyedm.PropertyFloat2(arg_n, key_list)
        edm_base_bock.setAlbedoMapUVShift(uv_shift_prop)

    return edm_base_bock

def make_def_base_block(mesh_storage: MeshStorage, mat_wrap: DefMaterialWrap, edm_props: EDMPropsGroup) -> pyedm.BaseBlock:
    if not (mat_wrap.values.blend_mode.value == EdmTransparencySocketItemsEnum.SUM_BLENDING_SI and mat_wrap.textures.emissive.texture):
        if not mat_wrap.textures.albedo.texture:
            if utils.cmp_vec4(mat_wrap.textures.albedo.default_color, (0.0, 0.0, 0.0, 1.0)):
                return None
    
    if mat_wrap.values.blend_mode.value == EdmTransparencySocketItemsEnum.SUM_BLENDING_SI and mat_wrap.textures.emissive.texture:
        edm_base_bock = make_base_texture(mesh_storage, mat_wrap, mat_wrap.textures.emissive.texture)
    elif mat_wrap.textures.albedo.texture:
        edm_base_bock = make_base_texture(mesh_storage, mat_wrap, mat_wrap.textures.albedo.texture)
    else:
        edm_base_bock = pyedm.ColorBaseBlock()
        base_color_path: str = mat_wrap.textures.albedo.color_anim_path
        is_color_value_animated: bool = base_color_path and anim.has_path_anim(mat_wrap.material.node_tree.animation_data, base_color_path)
        if is_color_value_animated and edm_props.COLOR_ARG != -1:
            arg_color_n: int = edm_props.COLOR_ARG
            key_color_list: anim.KeyFramePoints = anim.extract_anim_vec4(mat_wrap.material.node_tree.animation_data.action, base_color_path, (0.0, 0.0, 0.0, 1.0), lambda v: [v[0], v[1], v[2]])
            base_color_prop = pyedm.PropertyFloat3(arg_color_n, key_color_list)
            edm_base_bock.setColor(base_color_prop)
        else:
            base_color_prop = pyedm.PropertyFloat3((mat_wrap.textures.albedo.default_color[0], mat_wrap.textures.albedo.default_color[1], mat_wrap.textures.albedo.default_color[2]))
            edm_base_bock.setColor(base_color_prop)

    edm_base_bock.setPositions(mesh_storage.positions)
    edm_base_bock.setNormals(mesh_storage.normals)

    return edm_base_bock

def make_def_rmo_block(mesh_storage: MeshStorage, mat_wrap: DefMaterialWrap, edm_props: EDMPropsGroup) -> pyedm.AormsBlock:
    if not mat_wrap.textures.rmo.texture:
        return None
    
    edm_aorms_block = pyedm.AormsBlock()

    aorms_uv_map_name: str = mat_wrap.textures.rmo.texture.get_uv_map(mesh_storage.uv_active)
    edm_aorms_block.setAormsMapUV(mesh_storage.uv[aorms_uv_map_name])

    aorms_map_name: str = mat_wrap.textures.rmo.texture.texture_name
    edm_aorms_block.setAormsMap(aorms_map_name)

    return edm_aorms_block

def make_def_normal_block(mesh_storage: MeshStorage, mat_wrap: DefMaterialWrap, edm_props: EDMPropsGroup) -> pyedm.NormalBlock:
    if not mat_wrap.textures.normal.texture:
        return None
    
    edm_normals_block = pyedm.NormalBlock()

    normals_uv_map_name: str = mat_wrap.textures.normal.texture.get_uv_map(mesh_storage.uv_active)
    edm_normals_block.setNormalMapUV(mesh_storage.uv[normals_uv_map_name])

    normal_map_name: str = mat_wrap.textures.normal.texture.texture_name
    edm_normals_block.setNormalMap(normal_map_name)

    return edm_normals_block

def make_def_ao_block(mesh_storage: MeshStorage, mat_wrap: DefMaterialWrap, edm_props: EDMPropsGroup) -> pyedm.AoBlock:
    if not mat_wrap.textures.light_map.texture:
        return None
    
    ao_block = pyedm.AoBlock()

    ao_uv_name: str = mat_wrap.textures.light_map.texture.get_uv_map(mesh_storage.uv_active)
    ao_block.setAoMapUV(mesh_storage.uv[ao_uv_name])

    ao_map_name: str = mat_wrap.textures.light_map.texture.texture_name
    ao_block.setAoMap(ao_map_name)

    uv_shift_animation_path: str = mat_wrap.textures.light_map.texture.uv_move_loc_anim_path if mat_wrap.valid and mat_wrap.textures.light_map.texture.uv_move_node else None
    is_uv_shift_animated: bool = uv_shift_animation_path and anim.has_path_anim(mat_wrap.material.node_tree.animation_data, uv_shift_animation_path)
    arg_n: int = utils.extract_arg_number(mat_wrap.textures.light_map.texture.uv_move_node.label) if is_uv_shift_animated else -1
    if is_uv_shift_animated and arg_n != -1:
        key_list: anim.KeyFramePoints = anim.extract_anim_vec3(mat_wrap.material.node_tree.animation_data.action, uv_shift_animation_path, (0.0, 0.0, 0.0), lambda v: [v[0], 1.0 - v[1]])
        uv_shift_prop = pyedm.PropertyFloat2(arg_n, key_list)
        ao_block.setAoShift(uv_shift_prop)

    return ao_block
    
def check_emissive_texture_eq_rule(mat_wrap: DefMaterialWrap) -> None:
    if not mat_wrap.textures.emissive.texture or not mat_wrap.textures.emissive_mask.texture:
        return
    if not mat_wrap.textures.emissive.texture.texture_name == mat_wrap.textures.emissive_mask.texture.texture_name:
        log.fatal(f"Emissive texture has different alpha source on material {mat_wrap.name}. Emissive texure is {mat_wrap.textures.emissive.texture.texture_name} and alpha mask is {mat_wrap.textures.emissive_mask.texture.texture_name}")

def make_def_emissive_block(mesh_storage: MeshStorage, mat_wrap: DefMaterialWrap, edm_props: EDMPropsGroup) -> pyedm.EmissiveBlock:
    if not mat_wrap.textures.emissive.texture and utils.cmp_vec4(mat_wrap.textures.emissive.default_color, (0.0, 0.0, 0.0, 1.0)):
        return None

    check_emissive_texture_eq_rule(mat_wrap)
    
    edm_emissive_block = pyedm.EmissiveBlock()
    
    if mat_wrap.textures.emissive.texture:
        edm_emissive_block.setEmissiveType(int(EDMCustomEmissiveTypeInt.DEFAULT))

        emissive_uv_map_name: str = mat_wrap.textures.emissive.texture.get_uv_map(mesh_storage.uv_active)
        edm_emissive_block.setEmissiveMapUV(mesh_storage.uv[emissive_uv_map_name])
    
        emissive_map_name: str = mat_wrap.textures.emissive.texture.texture_name
        edm_emissive_block.setEmissiveMap(emissive_map_name)
    else:
        edm_emissive_block.setEmissiveType(int(EDMCustomEmissiveTypeInt.SELF_ILLUMINATION))

        emissive_color_path: str = mat_wrap.textures.emissive.color_anim_path
        is_emissive_color_animated: bool = emissive_color_path and anim.has_path_anim(mat_wrap.material.node_tree.animation_data, emissive_color_path)
        if is_emissive_color_animated and edm_props.EMISSIVE_COLOR_ARG != -1:
            arg_color_n: int = edm_props.EMISSIVE_COLOR_ARG
            key_color_list: anim.KeyFramePoints = anim.extract_anim_vec4(mat_wrap.material.node_tree.animation_data.action, emissive_color_path, (0.0, 0.0, 0.0, 1.0), lambda v: [v[0], v[1], v[2]])
            emissive_color_prop = pyedm.PropertyFloat3(arg_color_n, key_color_list)
        else:
            emissive_color: Tuple[float, float, float] = (mat_wrap.textures.emissive.default_color[0], mat_wrap.textures.emissive.default_color[1], mat_wrap.textures.emissive.default_color[2])
            emissive_color_prop = pyedm.PropertyFloat3(emissive_color)
            
        edm_emissive_block.setColor(emissive_color_prop)

        if mat_wrap.textures.emissive_mask.texture:
            emissive_mask_uv_map_name: str = mat_wrap.textures.emissive_mask.texture.get_uv_map(mesh_storage.uv_active)
            edm_emissive_block.setEmissiveMapUV(mesh_storage.uv[emissive_mask_uv_map_name])

            emissive_mask_map_name: str = mat_wrap.textures.emissive_mask.texture.texture_name
            edm_emissive_block.setEmissiveMap(emissive_mask_map_name)
        
    emissive_value: float = mat_wrap.values.emissive_value.value
    emissive_value_prop = pyedm.PropertyFloat(emissive_value)
    emissive_value_anim_path: str = mat_wrap.values.emissive_value.anim_path if mat_wrap.valid else None
    is_emissive_value_animated: bool = emissive_value_anim_path and anim.has_path_anim(mat_wrap.material.node_tree.animation_data, emissive_value_anim_path)
    if is_emissive_value_animated and edm_props.EMISSIVE_ARG != -1:
        key_list: anim.KeyFramePoints = anim.extract_anim_float(mat_wrap.material.node_tree.animation_data.action, emissive_value_anim_path)
        arg_n: int = edm_props.EMISSIVE_ARG
        emissive_value_prop = pyedm.PropertyFloat(arg_n, key_list)
    edm_emissive_block.setAmount(emissive_value_prop)

    if mat_wrap.values.blend_mode.value == EdmTransparencySocketItemsEnum.SUM_BLENDING_SI:
        if not mat_wrap.textures.albedo.texture and not utils.cmp_vec4(mat_wrap.textures.emissive.default_color, (0.0, 0.0, 0.0, 1.0)):
            edm_emissive_block.setEmissiveType(int(EDMCustomEmissiveTypeInt.ADDITIVE_SELF_COLOR_ILLUMINATION))
        elif mat_wrap.textures.albedo.texture and mat_wrap.textures.emissive.texture:
            edm_emissive_block.setEmissiveType(int(EDMCustomEmissiveTypeInt.ADDITIVE_SELF_TEX_ILLUMINATION))
        else:
            edm_emissive_block.setEmissiveType(int(EDMCustomEmissiveTypeInt.ADDITIVE_SELF_ILLUMINATION))

    return edm_emissive_block

def make_def_flir_block(mesh_storage: MeshStorage, mat_wrap: DefMaterialWrap, edm_props: EDMPropsGroup) -> pyedm.FlirBlock:
    if not mat_wrap.textures.flir.texture:
        return None
    
    edm_flir_block = pyedm.FlirBlock()

    flir_name: str = mat_wrap.textures.flir.texture.texture_name
    edm_flir_block.setFlirMap(flir_name)

    return edm_flir_block

def make_def_decal_block(mesh_storage: MeshStorage, mat_wrap: DefMaterialWrap, edm_props: EDMPropsGroup) -> pyedm.DecalBlock:
    if not mat_wrap.textures.decal.texture:
        return None
    
    edm_decal_block = pyedm.DecalBlock()

    decal_uv_map_name: str = mat_wrap.textures.decal.texture.get_uv_map(mesh_storage.uv_active)
    edm_decal_block.setDecalMapUV(mesh_storage.uv[decal_uv_map_name])

    decal_map_name: str = mat_wrap.textures.decal.texture.texture_name
    edm_decal_block.setDecalMap(decal_map_name)

    uv_shift_animation_path: str = mat_wrap.textures.decal.texture.uv_move_loc_anim_path if mat_wrap.valid and mat_wrap.textures.decal.texture.uv_move_node else None
    is_uv_shift_animated: bool = ( uv_shift_animation_path and anim.has_path_anim(mat_wrap.material.node_tree.animation_data, uv_shift_animation_path) )
    arg_n: int = utils.extract_arg_number(mat_wrap.textures.decal.texture.uv_move_node.label) if is_uv_shift_animated else -1
    if is_uv_shift_animated and arg_n != -1:
        key_list: anim.KeyFramePoints = anim.extract_anim_vec3(mat_wrap.material.node_tree.animation_data.action, uv_shift_animation_path, (0.0, 0.0, 0.0), lambda v: [v[0], 1.0 - v[1]])
        uv_shift_prop = pyedm.PropertyFloat2(arg_n, key_list)
        edm_decal_block.setDecalShift(uv_shift_prop)

    return edm_decal_block

def make_def_damage_block(mesh_storage: MeshStorage, mat_wrap: DefMaterialWrap, edm_props: EDMPropsGroup) -> pyedm.DamageBlock:
    if not mat_wrap.textures.damage_color.texture or not mat_wrap.textures.damage_mask.texture:
        return None
    
    if edm_props.DAMAGE_ARG < 0 and not mesh_storage.has_dmg_group:
        return None

    edm_damage_block = pyedm.DamageBlock()
    if mesh_storage.has_dmg_group:
        edm_damage_block.setPerVertexArguments(mesh_storage.damage_arguments)

    damage_color_uv_map_name: str = mat_wrap.textures.damage_color.texture.get_uv_map(mesh_storage.uv_active)
    edm_damage_block.setAlbedoMapUV(mesh_storage.uv[damage_color_uv_map_name])

    damage_color_map_name: str = mat_wrap.textures.damage_color.texture.texture_name
    edm_damage_block.setAlbedoMap(damage_color_map_name)

    if mat_wrap.textures.damage_normal.texture:
        damage_normal_uv_map_name: str = mat_wrap.textures.damage_normal.texture.get_uv_map(mesh_storage.uv_active)
        edm_damage_block.setNormalMapUV(mesh_storage.uv[damage_normal_uv_map_name])

        damage_normal_map_name: str = mat_wrap.textures.damage_normal.texture.texture_name
        edm_damage_block.setNormalMap(damage_normal_map_name)

    damage_mask_name: str = mat_wrap.textures.damage_mask.texture.texture_name
    edm_damage_block.setMaskRGBA(damage_mask_name)

    edm_damage_block.setArgument(edm_props.DAMAGE_ARG)

    return edm_damage_block

def make_def_bone_block(mesh_storage: MeshStorage, mat_wrap: DefMaterialWrap, edm_props: EDMPropsGroup) -> pyedm.BoneBlock:
    if not mesh_storage.armature:
        return None
    
    edm_bone_block = pyedm.BoneBlock()
    edm_bone_block.setBoneIndices(mesh_storage.bone_indices)
    edm_bone_block.setBoneWeights(mesh_storage.bone_weights)

    bone_names = list(mesh_storage.bones.items())
    bone_names.sort(key=lambda x : x[1])
    bone_names = [x[0] for x in bone_names]

    edm_bone_block.setBoneNames(bone_names)

    return edm_bone_block

BlockCustomType = Union[pyedm.BaseBlock, pyedm.AormsBlock, pyedm.NormalBlock, pyedm.AoBlock, pyedm.EmissiveBlock, pyedm.FlirBlock, pyedm.DecalBlock, pyedm.DamageBlock, pyedm.BoneBlock, None]

BLOCK_FUNCTIONS = [
    make_def_base_block,
    make_def_rmo_block,
    make_def_normal_block,
    make_def_decal_block,
    make_def_emissive_block,
    make_def_ao_block,
    make_def_flir_block,
    make_def_damage_block,
    make_def_bone_block,
]

def create_blocks(mesh_storage: MeshStorage, material_wrap: MaterialWrap, edm_props: EDMPropsGroup) -> List[BlockCustomType]:
    blocks: List[BlockCustomType] = []
    for block_function in BLOCK_FUNCTIONS:
        block = block_function(mesh_storage, material_wrap, edm_props)
        if block:
            blocks.append(block)

    return blocks

## Default material
class DefaultMaterial(IMaterial):
    name = NodeGroupTypeEnum.DEFAULT
    description_file_name = 'data/EDM_Default_Material.pickle'
    factory = DefMaterialWrap
    
    @classmethod    
    def build_blocks(cls, object, material_wrap, mesh_storage):
        edm_props = get_edm_props(object)
        edm_render_node = pyedm.PBRNode(object.name, material_wrap.material.name)
        edm_render_node.setIndices(mesh_storage.indices)

        blocks = create_blocks(mesh_storage, material_wrap, edm_props)
        for block in blocks:
            edm_render_node.addBlock(block)
        
        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)
        
        transparency_mode: int = get_transparency_value(material_wrap.values.blend_mode.value)
        edm_render_node.setTransparentMode(transparency_mode)

        shadow_caster_type: int = get_shadow_caster_value(material_wrap.values.shadow_caster.value)
        edm_render_node.setShadowCaster(shadow_caster_type)

        opacity_value_path: str = material_wrap.values.opacity_value.anim_path
        is_color_value_animated: bool = opacity_value_path and anim.has_path_anim(material_wrap.material.node_tree.animation_data, opacity_value_path)
        if is_color_value_animated and edm_props.OPACITY_VALUE_ARG != -1:
            arg_opacity_value_n: int = edm_props.OPACITY_VALUE_ARG
            key_opacity_value_list: anim.KeyFramePoints = anim.extract_anim_float(material_wrap.material.node_tree.animation_data.action, opacity_value_path)
            opacity_value_prop = pyedm.PropertyFloat(arg_opacity_value_n, key_opacity_value_list)
            edm_render_node.setOpacityValue(opacity_value_prop)
        else:
            opacity_value_prop = pyedm.PropertyFloat(material_wrap.values.opacity_value.value)
            edm_render_node.setOpacityValue(opacity_value_prop)

        two_sided: bool = edm_props.TWO_SIDED
        edm_render_node.setTwoSided(two_sided)

        return edm_render_node
    
    @classmethod
    def process_links(cls, old_links, old_version, group_node_type_name):
        new_links: List[SLink] = []
        
        if old_version == 0 or old_version == 1:
            for link in old_links:
                if link.to_type == 'ShaderNodeGroup':
                    if link.to_socket == 'Normal' or link.to_socket == 'Normal  (Non-Color)' or link.to_socket == 'Normal (Non color)':
                        link = copy.copy(link)
                        link.to_socket = NodeSocketInDefaultEnum.NORMAL
                new_links.append(link)
        elif old_version <= 11:
            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 = NodeSocketInDefaultEnum.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 == 0:
            return
        if old_version < 8:
            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 == NodeSocketInDefaultEnum.SHADOW_CASTER and (old_socket_wrp.bl_socket_idname == 'NodeSocketUndefined' or not old_socket_wrp.instance_value):
                    new_socket.default_value = ShadowCasterEnumItems[0][0]
                    continue
                if new_socket.name == NodeSocketInDefaultEnum.SHADOW_CASTER:
                    new_socket.default_value = ShadowCasterEnumItems[old_socket_wrp.instance_value][0]
                    continue
                if new_socket.name == NodeSocketInDefaultEnum.TRANSPARENCY and (old_socket_wrp.bl_socket_idname == 'NodeSocketUndefined' or not old_socket_wrp.instance_value):
                    new_socket.default_value = TransparencyEnumItems[0][0]
                    continue
                if new_socket.name == NodeSocketInDefaultEnum.TRANSPARENCY:
                    new_socket.default_value = TransparencyEnumItems[old_socket_wrp.instance_value][0]
                    continue
                if new_socket.name == NodeSocketCommonEnum.VERSION:
                    new_socket.default_value = version_new
                    continue
                if hasattr(old_socket_wrp, 'instance_value'):
                    new_socket.default_value = old_socket_wrp.instance_value
        elif old_version >= 8:
            socket_map: Dict[str, Dict[str, str]] = utils.make_socket_map(new_node_group)
            socket_acro_map: Dict[str, str] = utils.make_acro_map(new_node_group)
            if socket_map.get(material_name):
                for socket_name in socket_map[material_name].keys():
                    if new_node_group.bl_idname in (BpyShaderNode.NODE_GROUP_DEFAULT, BpyShaderNode.NODE_GROUP_DECK, BpyShaderNode.NODE_GROUP_FAKE_OMNI, BpyShaderNode.NODE_GROUP_FAKE_SPOT):
                        prop_name: str = socket_acro_map.get(socket_name)
                        old_socket_wrp: SInput = get_first_socket_by_name(old_sockest, socket_name)
                        if hasattr(old_socket_wrp, 'instance_value'):
                            setattr(new_node_group, prop_name, old_socket_wrp.instance_value)
                    else:
                        enum_name: str = socket_map[material_name][socket_name]
                        old_socket_wrp: SInput = get_first_socket_by_name(old_sockest, socket_name)
                        if old_socket_wrp and hasattr(old_socket_wrp, 'instance_value'):
                            setattr(new_node_group, enum_name, old_socket_wrp.instance_value)
            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:
                    if IS_BLENDER_3:
                        new_socket.default_value = old_socket_wrp.instance_value
                    elif IS_BLENDER_4:
                        if new_socket.name not in (NodeSocketInDefaultEnum.TRANSPARENCY, NodeSocketInDefaultEnum.SHADOW_CASTER):
                            new_socket.default_value = old_socket_wrp.instance_value

