# SPDX-License-Identifier: GPL-2.0-or-later

""""Nodes based User interface for shaders exported to POV textures."""
import bpy

from bpy.utils import register_class, unregister_class
from bpy.types import Menu, Operator
from bpy.props import (
    StringProperty,
)

# def find_node_input(node, name):
# for input in node.inputs:
# if input.name == name:
# return input

# def panel_node_draw(layout, id_data, output_type, input_name):
# if not id_data.use_nodes:
# #layout.operator("pov.material_use_nodes", icon='SOUND')#'NODETREE')
# #layout.operator("pov.use_shading_nodes", icon='NODETREE')
# layout.operator("WM_OT_context_toggle", icon='NODETREE').data_path = \
# "material.pov.material_use_nodes"
# return False

# ntree = id_data.node_tree

# node = find_node(id_data, output_type)
# if not node:
# layout.label(text="No output node")
# else:
# input = find_node_input(node, input_name)
# layout.template_node_view(ntree, node, input)

# return True


class NODE_MT_POV_map_create(Menu):
    """Create maps"""

    bl_idname = "POVRAY_MT_node_map_create"
    bl_label = "Create map"

    def draw(self, context):
        layout = self.layout
        layout.operator("node.map_create")


def menu_func_nodes(self, context):
    ob = context.object
    if hasattr(ob, "active_material"):
        mat = context.object.active_material
        if mat and context.space_data.tree_type == "ObjectNodeTree":
            self.layout.prop(mat.pov, "material_use_nodes")
            self.layout.menu(NODE_MT_POV_map_create.bl_idname)
            self.layout.operator("wm.updatepreviewkey")
        if hasattr(mat, "active_texture") and context.scene.render.engine == "POVRAY_RENDER":
            tex = mat.active_texture
            if tex and context.space_data.tree_type == "TextureNodeTree":
                self.layout.prop(tex.pov, "texture_use_nodes")


# ------------------------------------------------------------------------------ #
# --------------------------------- Operators ---------------------------------- #
# ------------------------------------------------------------------------------ #


class NODE_OT_iso_add(Operator):
    bl_idname = "pov.nodeisoadd"
    bl_label = "Create iso props"

    def execute(self, context):
        ob = bpy.context.object
        if not bpy.context.scene.use_nodes:
            bpy.context.scene.use_nodes = True
        tree = bpy.context.scene.node_tree
        for node in tree.nodes:
            if node.bl_idname == "IsoPropsNode" and node.label == ob.name:
                tree.nodes.remove(node)
        isonode = tree.nodes.new("IsoPropsNode")
        isonode.location = (0, 0)
        isonode.label = ob.name
        return {"FINISHED"}


class NODE_OT_map_create(Operator):
    bl_idname = "node.map_create"
    bl_label = "Create map"

    def execute(self, context):
        x = y = 0
        space = context.space_data
        tree = space.edit_tree
        for node in tree.nodes:
            if node.select:
                x, y = node.location
            node.select = False
        tmap = tree.nodes.new("ShaderTextureMapNode")
        tmap.location = (x - 200, y)
        return {"FINISHED"}

    def invoke(self, context, event):
        wm = context.window_manager
        return wm.invoke_props_dialog(self)

    def draw(self, context):
        layout = self.layout
        mat = context.object.active_material
        layout.prop(mat.pov, "inputs_number")


class NODE_OT_povray_node_texture_map_add(Operator):
    bl_idname = "pov.nodetexmapadd"
    bl_label = "Texture map"

    def execute(self, context):
        tree = bpy.context.object.active_material.node_tree
        tmap = tree.nodes.active
        mtl = context.object.active_material
        mtl.node_tree.nodes.active = tmap
        el = tmap.color_ramp.elements.new(0.5)
        for el in tmap.color_ramp.elements:
            el.color = (0, 0, 0, 1)
        for inp in tmap.inputs:
            tmap.inputs.remove(inp)
        for outp in tmap.outputs:
            tmap.outputs.remove(outp)
        pattern = tmap.inputs.new("NodeSocketVector", "Pattern")
        pattern.hide_value = True
        for i in range(3):
            tmap.inputs.new("NodeSocketColor", "Shader")
        tmap.outputs.new("NodeSocketShader", "BSDF")
        tmap.label = "Texture Map"
        return {"FINISHED"}


class NODE_OT_povray_node_output_add(Operator):
    bl_idname = "pov.nodeoutputadd"
    bl_label = "Output"

    def execute(self, context):
        tree = bpy.context.object.active_material.node_tree
        tmap = tree.nodes.new("ShaderNodeOutputMaterial")
        mtl = context.object.active_material
        mtl.node_tree.nodes.active = tmap
        for inp in tmap.inputs:
            tmap.inputs.remove(inp)
        tmap.inputs.new("NodeSocketShader", "Surface")
        tmap.label = "Output"
        return {"FINISHED"}


class NODE_OT_povray_node_layered_add(Operator):
    bl_idname = "pov.nodelayeredadd"
    bl_label = "Layered material"

    def execute(self, context):
        tree = bpy.context.object.active_material.node_tree
        tmap = tree.nodes.new("ShaderNodeAddShader")
        mtl = context.object.active_material
        mtl.node_tree.nodes.active = tmap
        tmap.label = "Layered material"
        return {"FINISHED"}


class NODE_OT_povray_input_add(Operator):
    bl_idname = "pov.nodeinputadd"
    bl_label = "Add entry"

    def execute(self, context):
        mtl = context.object.active_material
        node = mtl.node_tree.nodes.active
        if node.type == "VALTORGB":
            number = 1
            for inp in node.inputs:
                if inp.type == "SHADER":
                    number += 1
            node.inputs.new("NodeSocketShader", "%s" % number)
            els = node.color_ramp.elements
            pos1 = els[len(els) - 1].position
            pos2 = els[len(els) - 2].position
            pos = (pos1 - pos2) / 2 + pos2
            el = els.new(pos)

        if node.bl_idname == "PovraySlopeNode":
            number = len(node.inputs)
            node.inputs.new("PovraySocketSlope", "%s" % number)

        return {"FINISHED"}


class NODE_OT_povray_input_remove(Operator):
    bl_idname = "pov.nodeinputremove"
    bl_label = "Remove input"

    def execute(self, context):
        mtl = context.object.active_material
        node = mtl.node_tree.nodes.active
        if node.type in {"VALTORGB", "ADD_SHADER"}:
            number = len(node.inputs) - 1
            if number > 5:
                inp = node.inputs[number]
                node.inputs.remove(inp)
                if node.type == "VALTORGB":
                    els = node.color_ramp.elements
                    number = len(els) - 2
                    el = els[number]
                    els.remove(el)
        return {"FINISHED"}


class NODE_OT_povray_image_open(Operator):
    bl_idname = "pov.imageopen"
    bl_label = "Open"

    filepath: StringProperty(
        name="File Path", description="Open image", maxlen=1024, subtype="FILE_PATH"
    )

    def invoke(self, context, event):
        context.window_manager.fileselect_add(self)
        return {"RUNNING_MODAL"}

    def execute(self, context):
        im = bpy.data.images.load(self.filepath)
        mtl = context.object.active_material
        node = mtl.node_tree.nodes.active
        node.image = im.name
        return {"FINISHED"}


# class TEXTURE_OT_povray_open_image(Operator):
# bl_idname = "pov.openimage"
# bl_label = "Open Image"

# filepath = StringProperty(
# name="File Path",
# description="Open image",
# maxlen=1024,
# subtype='FILE_PATH',
# )

# def invoke(self, context, event):
# context.window_manager.fileselect_add(self)
# return {'RUNNING_MODAL'}

# def execute(self, context):
# im=bpy.data.images.load(self.filepath)
# tex = context.texture
# tex.pov.image = im.name
# view_layer = context.view_layer
# view_layer.update()
# return {'FINISHED'}


classes = (
    NODE_MT_POV_map_create,
    NODE_OT_iso_add,
    NODE_OT_map_create,
    NODE_OT_povray_node_texture_map_add,
    NODE_OT_povray_node_output_add,
    NODE_OT_povray_node_layered_add,
    NODE_OT_povray_input_add,
    NODE_OT_povray_input_remove,
    NODE_OT_povray_image_open,
)


def register():
    bpy.types.NODE_HT_header.append(menu_func_nodes)
    for cls in classes:
        register_class(cls)


def unregister():
    for cls in reversed(classes):
        unregister_class(cls)
    bpy.types.NODE_HT_header.remove(menu_func_nodes)