# Copyright (C) 2022 Thomas Hoppe (h0bB1T). All rights reserved.
#
# Unauthorized copying of this file via any medium is strictly prohibited.
# Proprietary and confidential.

import bpy

import numpy as np

from bpy.types import Operator
from bpy.props import StringProperty, IntProperty, BoolProperty

from ..utils.tools import Measure

class UI_OT_support_mix_gray_textures(Operator):
    """
    Currently unused. Builds 4G textures from 4 single gray images.
    """
    bl_idname = 'snw.support_mix_gray_textures'
    bl_label = 'Mix Gray Textures'
    bl_description = 'Create one single RGBA texture from up to 4 single gray textures (from R channel).'
    bl_options = {'REGISTER'}

    texture_r: StringProperty() # type: ignore
    texture_g: StringProperty() # type: ignore
    texture_b: StringProperty() # type: ignore
    texture_a: StringProperty() # type: ignore
    texture_out: StringProperty() # type: ignore
    size: IntProperty() # type: ignore
    pack: BoolProperty() # type: ignore

    def _get_size(self, src: str) -> int:
        """
        Returns width of image.
        """
        if src:
            return bpy.data.images[src].size[0]
        return 0

    def _get_gray(self, src: str, size: int, alpha: bool = False) -> np.array:
        """
        Returns image as gray in correct size or zeros if not set.
        """
        if src:
            d = bpy.data.images[src]
            if d.size[0] != size and d.size[1] != size:
                _tmp = bpy.data.images.new('_TMP_IMAGE', d.size[0], d.size[1]) # type: bpy.types.Image
                _tmp.pixels[:] = d.pixels[:]
                _tmp.scale(size, size)
                pixels = _tmp.pixels[:]
                bpy.data.images.remove(_tmp, do_unlink=True)
            else:
                pixels = d.pixels[:]
            return np.array(pixels)[0::4]
        else:
            if alpha:
                return np.ones((size ** 2), dtype=float)
            else:
                return np.zeros((size ** 2), dtype=float)


    def execute(self, context: bpy.types.Context):
        size = self.size
        if size == 0:
            size = max(
                self._get_size(self.texture_r),
                self._get_size(self.texture_g),
                self._get_size(self.texture_b),
                self._get_size(self.texture_a)
            )

        with Measure('Extract data'):
            channel_r = self._get_gray(self.texture_r, size)
            channel_g = self._get_gray(self.texture_g, size)
            channel_b = self._get_gray(self.texture_b, size)
            channel_a = self._get_gray(self.texture_a, size, True)

        with Measure('Merge maps'):
            data = np.ravel(np.column_stack((
                channel_r,
                channel_g,
                channel_b,
                channel_a
            ))).tolist()

        with Measure('...'):
            bpy.ops.uv.textools_bake()

        with Measure('Create/update image'):
            if not self.texture_out in bpy.data.images:
                image = bpy.data.images.new(self.texture_out, size, size, alpha=True) # type: bpy.types.Image
            else:
                image = bpy.data.images[self.texture_out] # type: bpy.types.Image
            image.alpha_mode = 'CHANNEL_PACKED'
            if image.size[0] != size or image.size[1] != size:
                image.scale(size, size)
            image.pixels[:] = data
            image.update()

            # TODO: PACK

            return{'FINISHED'} # TODO: DropNode
