import bpy
from .utils_debug import debug_err


def createImageWithColor(color, width: int, height: int, name: str or None = None) -> bpy.types.Image:
    # create linear colorspace image
    image = bpy.data.images.new(name="Color", width=width, height=height, float_buffer=True)
    pixels = [color[0], color[1], color[2], 1.0] * width * height
    image.pixels = pixels
    return image

def assignColorToImage(image: bpy.types.Image, color, intensity: float = 1.0, apply_view_transform: bool = False):

    # if apply_view_transform:
    #     transform_str = bpy.data.scenes[0].view_settings.view_transform
    #     if transform_str == "AgX":
    #         pass

    pixels = [color[0] * intensity, color[1] * intensity, color[2] * intensity, 1.0] * image.size[0] * image.size[1]
    image.pixels = pixels

def loadImage(path) -> bpy.types.Image:
    image = bpy.data.images.load(path)
    return image


def flipImage(image: bpy.types.Image):
    # https://blender.stackexchange.com/a/205517
    win = bpy.context.window_manager.windows[0]
    area = win.screen.areas[0]
    prevType = area.type
    try:
        area.type = "IMAGE_EDITOR"
        override = bpy.context.copy()
        override['window'] = win
        override['screen'] = win.screen
        override['area'] = win.screen.areas[0]
        override['area'].spaces.active.image = image
        override['region'] = win.screen.areas[0].regions[0]
        with bpy.context.temp_override(**override):
            # https://docs.blender.org/api/current/bpy.ops.image.html#bpy.ops.image.flip
            bpy.ops.image.flip(use_flip_x=False, use_flip_y=True)
            pass
    except Exception as e:
        debug_err(e)
    finally:
        area.type = prevType

def applyFactor(image: bpy.types.Image, factor: float):
    if factor == 1.0:
        return image
    pixels = image.pixels
    for i in range(0, len(pixels), 4):
        pixels[i] *= factor
        pixels[i + 1] *= factor
        pixels[i + 2] *= factor
        pixels[i + 3] *= factor
    return image

def assignMaterial(material, blender_object):
    if blender_object is not None:
        if blender_object.data.materials:
            # assign to 1st material slot
            blender_object.data.materials[0] = material
        else:
            # no slots
            blender_object.data.materials.append(material)


def createMaterialWithTexture(material_name, image):
    # create a material
    material = bpy.data.materials.new(name=material_name)
    material.use_nodes = True

    # we load it again to flip it:
    # set texture
    # image = bpy.data.images.load(texture_path)
    # create an image texture node
    image_texture = material.node_tree.nodes.new(type='ShaderNodeTexImage')
    image_texture.image = image

    # create a material output node
    material_output = material.node_tree.nodes.get("Material Output")

    # get principled BSDF node
    shader = material.node_tree.nodes.get("Principled BSDF")

    # connect the nodes
    material.node_tree.links.new(shader.outputs[0], material_output.inputs[0])
    material.node_tree.links.new(image_texture.outputs[0], shader.inputs[0])

    # positon the nodes
    image_texture.location = (-300, 0)
    shader.location = (0, 0)
    material_output.location = (300, 0)

    return material
