import bpy, os.path

def setupSparks(mat_name,col):
    mat = bpy.data.materials.new(name=mat_name)
    mat.use_nodes = True
    nodes = mat.node_tree.nodes
    for node in nodes:
        nodes.remove(node)
    # create principled
    node_emission = nodes.new(type="ShaderNodeEmission")
    node_emission.location = 200,0
    node_emission.inputs[1].default_value = 50.0
    node_emission.inputs[0].default_value = col
    # create output node
    node_output = nodes.new(type='ShaderNodeOutputMaterial')   
    node_output.location = 600,0
    # mix_node1 = nodes.new(type="ShaderNodeMixRGB")
    # mix_node1.location = -400,-600
    # mix_node1.blend_type = 'VALUE'
    # mix_node1.inputs[0].default_value = 0.5
    # link nodes
    links = mat.node_tree.links
    link = links.new(node_emission.outputs[0], node_output.inputs[0])
    return mat


def setupMaterial(mat_name,
    col,
    color_map,
    metallic,
    roughness,
    normal_map,
    bumpiness, 
    clearcoat,
    clearcoat_rouhness,
    transparency,
    style,
    monochrome):
    
    node_noise,node_math = None, None
    mat = bpy.data.materials.new(name=mat_name)
    mat.use_nodes = True
    nodes = mat.node_tree.nodes
    if monochrome:
        col = [float(x) for x in monochrome.split('|')]
        color_map = ''
        metallic = 0.0
        roughness = 1.0
        normal_map = ''
        bumpiness = 0
        clearcoat = 0
        clearcoat_rouhness = 0
        style = ''
        transparency = 0.0
    if style in ['N/A', '']:
        if '_cast_metal' in mat.name:
            style = 'castmetal'
        elif '_pulver' in mat.name:
            style = 'pulver'
    for node in nodes:
        nodes.remove(node)
    if not bpy.context.scene.render.use_freestyle:
        # create principled
        node_principled = nodes.new(type="ShaderNodeBsdfPrincipled")
        node_principled.location = 200,0
        node_principled.inputs[4].default_value = metallic#1.0 if metallic > 0 else 0.0 #material is metal or not.. nothing between
        node_principled.inputs[5].default_value = 0.7 #specular
        node_principled.inputs[7].default_value = max(roughness, 0.01)
        node_principled.inputs[12].default_value = clearcoat
        node_principled.inputs[13].default_value = max(clearcoat_rouhness, 0.1)
        # create output node
        node_output = nodes.new(type='ShaderNodeOutputMaterial')   
        node_output.location = 600,0
        # create texture     node
        node_texture = None
        if color_map and os.path.exists(color_map):
            node_texture = nodes.new(type='ShaderNodeTexImage')
            node_texture.location = -600,100
            texture_img = bpy.data.images.load(color_map)
            node_texture.image = texture_img
        else:
            # text color
            if len(col) == 3:
                ccolor = [0,0,0,1]
                ccolor[:3] = col
                col = tuple(ccolor)
            col = [x**2.2 for x in col] # gamma correction
            #if transparency < 1.0:
            #    col = [x/10.0 + 0.9 for x in col]
            node_principled.inputs[0].default_value = col
        if transparency < 1.0: #opacity
            node_principled.inputs[15].default_value = 1.0 #transmission
            col = [x/10.0 + 0.9 for x in col] #make it brighter
            bpy.context.scene.eevee.use_ssr_refraction = True
            mat.use_screen_refraction = True
            mat.use_sss_translucency = True
            mat.refraction_depth = 0.03


        else:
            node_principled.inputs[15].default_value = 0.0 #transmission
        style_vals = style.lower().split('|')
        node_normalmap = None
        if normal_map and os.path.exists(normal_map):
            node_normalmap = nodes.new(type='ShaderNodeTexImage')
            node_normalmap.location = -600,-300
            normalmap_img = bpy.data.images.load(normal_map)
            node_normalmap.image = normalmap_img
            normalmap_img.colorspace_settings.name = 'Non-Color'
            #
            node_normalvector = nodes.new(type="ShaderNodeNormalMap")
            node_normalvector.location = -300,-300
            node_normalvector.inputs[0].default_value = bumpiness*2
        elif style_vals[0] == 'castmetal':
            try:
                strength = float( style_vals[1] )
            except:
                strength = 0.05
            try:
                text_scale = float(style_vals[2])
            except:
                text_scale = 400.0
            coordinates_node = nodes.new(type="ShaderNodeTexCoord")
            coordinates_node.location = -1600,-300

            node_principled.inputs[7].default_value = max(roughness*.6, .2) # decreasing the roughness a little but clmaping it above .2

            mapping_node = nodes.new(type="ShaderNodeMapping")
            mapping_node.location = -1400,-300
            mapping_node.inputs['Scale'].default_value[0] = text_scale
            mapping_node.inputs['Scale'].default_value[1] = text_scale
            mapping_node.inputs['Scale'].default_value[2] = text_scale


            voronoi_node = nodes.new(type="ShaderNodeTexVoronoi")
            voronoi_node.location = -1000,-300
            voronoi_node.inputs[1].default_value = 200

            noise_node = nodes.new(type="ShaderNodeTexNoise")
            noise_node.location = -1000,-600
            noise_node.inputs[1].default_value = 600.0
            noise_node.inputs[2].default_value = 2.0
            noise_node.inputs[3].default_value = 5.0

            noise_node2 = nodes.new(type="ShaderNodeTexNoise")
            noise_node2.location = -1000,-900
            noise_node2.inputs[1].default_value = 10.0
            noise_node2.inputs[2].default_value = 2.0
            noise_node2.inputs[3].default_value = 80.0

            colorramp_node = nodes.new(type="ShaderNodeValToRGB")
            colorramp_node.location = -800,-300
            colorramp_node.color_ramp.elements[0].position = 0.5
            colorramp_node.color_ramp.elements[1].position = 0.65
            colorramp_node.color_ramp.elements[0].color = (1, 1, 1, 1)
            colorramp_node.color_ramp.elements[1].color = (0, 0, 0, 1)

            colorramp_node2 = nodes.new(type="ShaderNodeValToRGB")
            colorramp_node2.location = -800,-600
            colorramp_node2.color_ramp.elements[0].position = 0.25
            colorramp_node2.color_ramp.elements[1].position = 0.8
            colorramp_node2.color_ramp.elements[0].color = (1, 1, 1, 1)
            colorramp_node2.color_ramp.elements[1].color = (0, 0, 0, 1)

            colorramp_node3 = nodes.new(type="ShaderNodeValToRGB")
            colorramp_node3.location = -800,-900
            colorramp_node3.color_ramp.elements[0].position = 0.51
            colorramp_node3.color_ramp.elements[1].position = 0.675
            colorramp_node3.color_ramp.elements[0].color = (1, 1, 1, 1)
            colorramp_node3.color_ramp.elements[1].color = (0, 0, 0, 1)

            mix_node1 = nodes.new(type="ShaderNodeMixRGB")
            mix_node1.location = -400,-600
            mix_node1.blend_type = 'VALUE'
            mix_node1.inputs[0].default_value = 0.5

            mix_node2 = nodes.new(type="ShaderNodeMixRGB")
            mix_node2.location = -200,-300
            mix_node2.blend_type = 'VALUE'
            mix_node2.inputs[0].default_value = 0.66

            bump_node = nodes.new(type="ShaderNodeBump")
            bump_node.location = 0,-300
            bump_node.inputs[0].default_value = strength
            bump_node.inputs[1].default_value = 1.0

            links = mat.node_tree.links
            link = links.new(coordinates_node.outputs[3], mapping_node.inputs[0])
            link = links.new(mapping_node.outputs[0], voronoi_node.inputs[0])
            link = links.new(voronoi_node.outputs[0], colorramp_node.inputs[0])
            link = links.new(colorramp_node.outputs[0], mix_node2.inputs[1])
            link = links.new(mapping_node.outputs[0], noise_node.inputs[0])
            link = links.new(mapping_node.outputs[0], noise_node2.inputs[0])
            link = links.new(noise_node.outputs[0], colorramp_node2.inputs[0])
            link = links.new(noise_node2.outputs[0], colorramp_node3.inputs[0])
            link = links.new(colorramp_node2.outputs[0], mix_node1.inputs[1])
            link = links.new(colorramp_node3.outputs[0], mix_node1.inputs[2])
            link = links.new(mix_node1.outputs[0], mix_node2.inputs[2])
            link = links.new(mix_node2.outputs[0], bump_node.inputs[2])
            link = links.new(bump_node.outputs[0], node_principled.inputs['Normal'])

        elif style_vals[0] == 'pulver':
            try:
                strength = float( style_vals[1] )
            except:
                strength = 0.08
            try:
                text_scale = float(style_vals[2])
            except:
                text_scale = 1.0
            coordinates_node = nodes.new(type="ShaderNodeTexCoord")
            coordinates_node.location = -1400,-300

            mapping_node = nodes.new(type="ShaderNodeMapping")
            mapping_node.location = -1100,-300
            mapping_node.inputs['Scale'].default_value[0] = 200*text_scale
            mapping_node.inputs['Scale'].default_value[1] = 200*text_scale
            mapping_node.inputs['Scale'].default_value[2] = 200*text_scale


            noise_node = nodes.new(type="ShaderNodeTexNoise")
            noise_node.location = -700,-300
            noise_node.inputs[1].default_value = 5.0
            noise_node.inputs[2].default_value = 2.0
            noise_node.inputs[3].default_value = 0.0

            bump_node = nodes.new(type="ShaderNodeBump")
            bump_node.location = 0,-300
            bump_node.inputs[0].default_value = strength
            bump_node.inputs[1].default_value = 1.0

            links = mat.node_tree.links
            link = links.new(coordinates_node.outputs[3], mapping_node.inputs[0])
            link = links.new(mapping_node.outputs[0], noise_node.inputs[0])
            link = links.new(noise_node.outputs[0], bump_node.inputs[2])
            link = links.new(bump_node.outputs[0], node_principled.inputs['Normal'])
        # link nodes
        links = mat.node_tree.links
        if node_texture:
            link = links.new(node_texture.outputs[0], node_principled.inputs[0])
        if node_normalmap:
            link = links.new(node_normalmap.outputs[0], node_normalvector.inputs[1])
            link = links.new(node_normalvector.outputs[0], node_principled.inputs['Normal']) #needs to find the link by name, doesn't connect otherwise??
        link = links.new(node_principled.outputs[0], node_output.inputs[0])
        if node_noise and node_math:
            link = links.new(node_noise.outputs[1], node_math.inputs[0])
            link = links.new(node_math.outputs[0], node_output.inputs[2])
    else:
        # create toon shader when freestyle is enabled for cartoonish looks
        node_toon = nodes.new(type="ShaderNodeBsdfToon")
        node_toon.location = 0,0
        # create output node
        node_output = nodes.new(type='ShaderNodeOutputMaterial')   
        node_output.location = 300,0
        # create texture     node
        node_texture = None
        if color_map and os.path.exists(color_map):
            node_texture = nodes.new(type='ShaderNodeTexImage')
            node_texture.location = -600,100
            texture_img = bpy.data.images.load(color_map)
            node_texture.image = texture_img
        else:
            # text color_map
            if len(col) == 3:
                ccolor = [0,0,0,1]
                ccolor[:3] = col
                col = tuple(ccolor)
            col = [x**2.2 for x in col] # gamma correction
            node_toon.inputs[0].default_value = col
        node_toon.inputs[1].default_value = 0.7
        node_toon.inputs[2].default_value = 0.0
        # link nodes
        links = mat.node_tree.links
        link = links.new(node_toon.outputs[0], node_output.inputs[0])
        if node_texture:
            link = links.new(node_texture.outputs[0], node_toon.inputs[0])
    return mat


def setupShadowCatcher(mat_name, color):
    node_noise,node_math = None, None
    mat = bpy.data.materials.new(name=mat_name)
    mat.use_nodes = True
    nodes = mat.node_tree.nodes
    for node in nodes:
        nodes.remove(node)

    node_principled = nodes.new(type="ShaderNodeBsdfPrincipled")
    node_principled.location = 200,0
    if len(color) == 3:
        ccolor = [0,0,0,1]
        ccolor[:3] = color
        color = tuple(ccolor)
    color = [x**2.2 for x in color] # gamma correction
    node_principled.inputs[0].default_value = color

    node_output = nodes.new(type='ShaderNodeOutputMaterial')   
    node_output.location = 600,0
    
    node_diffuse = nodes.new(type='ShaderNodeBsdfDiffuse')
    node_diffuse.location = -600,-200
    
    node_shader2rgb = nodes.new(type='ShaderNodeShaderToRGB')
    node_shader2rgb.location = -400,-200

    node_colorramp = nodes.new(type='ShaderNodeValToRGB')
    node_colorramp.location = -200,-200

    node_colorramp.color_ramp.elements[0].position = 0.0
    node_colorramp.color_ramp.elements[0].color = (1,1,1,1)
    node_colorramp.color_ramp.elements[1].position = 0.3
    node_colorramp.color_ramp.elements[1].color = (0,0,0,1)

    links = mat.node_tree.links
    link = links.new(node_diffuse.outputs[0], node_shader2rgb.inputs[0])
    link = links.new(node_shader2rgb.outputs[0], node_colorramp.inputs[0])
    link = links.new(node_colorramp.outputs[0], node_principled.inputs['Alpha'])
    link = links.new(node_principled.outputs[0], node_output.inputs[0])

    mat.blend_method = 'BLEND'

    return mat
