import torch
from PIL import Image, ImageOps, ImageSequence, ImageFile
from PIL.PngImagePlugin import PngInfo

import numpy as np
import os
import folder_paths 
import node_helpers
import hashlib
from uuid import uuid4

# Tensor to PIL
def tensor2pil(image):
    return Image.fromarray(np.clip(255. * image.cpu().numpy().squeeze(), 0, 255).astype(np.uint8))

# tensor 取hash值
def tensor_to_hash(tensor):
    # 将 Tensor 转换为 NumPy 数组
    np_array = tensor.cpu().numpy()
    
    # 将 NumPy 数组转换为字节数据
    byte_data = np_array.tobytes()
    
    # 计算哈希值
    hash_value = hashlib.md5(byte_data).hexdigest()
    
    return hash_value


def create_temp_file(image, uuid):
    output_dir = folder_paths.get_temp_directory()

    (
            full_output_folder,
            filename,
            counter,
            subfolder,
            _,
        ) = folder_paths.get_save_image_path(f'material_{uuid}', output_dir)

    
    image=tensor2pil(image)
 
    image_file = f"{filename}_{counter:05}.png"
     
    image_path=os.path.join(full_output_folder, image_file)

    image.save(image_path,compress_level=4)

    return (image_path,[{
    "filename": image_file,
    "subfolder": subfolder,
    "type": "temp"
    }])


# image - tensor - 文件路径
# loadImage的方法（ 文件路径 - image-mask ）
class EditMask:

    def __init__(self):
        self.image_id = None
        self.uuid = str(uuid4())

    @classmethod
    def INPUT_TYPES(s):
        return {"required":
                    {"image": ("IMAGE",), # 表示一个张量
                     
                     },

                    "optional":{
                            "image_update": ("IMAGE_FILE",)
                        },
                   
                }

    CATEGORY = "♾️Mixlab/Mask"

    RETURN_TYPES = ("IMAGE", "MASK")
    RETURN_NAMES = ("image", "mask")

    FUNCTION = "edit"

    OUTPUT_NODE = True

    def edit(self, image,image_update=None):

        # 根据image输入来判断是否是新的图片
        if self.image_id==None:
            self.image_id=tensor_to_hash(image)
            image_update=None
        else:
            image_id=tensor_to_hash(image)
            if image_id!=self.image_id:
                image_update=None
                self.image_id=image_id


        image_path=None
        # print('#image_update',self.image_id,image_update)
        if image_update==None:
            print('--')
        else:
            if 'images' in image_update:
                images=image_update['images']
                filename=images[0]['filename']
                subfolder=images[0]['subfolder']
                type=images[0]['type']
                name, base_dir=folder_paths.annotated_filepath(filename)
                if type.endswith("output"):
                    base_dir = folder_paths.get_output_directory() 
                elif type.endswith("input"):
                    base_dir = folder_paths.get_input_directory() 
                elif type.endswith("temp"):
                    base_dir = folder_paths.get_temp_directory() 
                #base_dir = folder_paths.get_input_directory()  
                # print(base_dir,subfolder, name)
                image_path = os.path.join(base_dir,subfolder, name)
        
        if image_path==None:
            image_path,images=create_temp_file(image, self.uuid)

        print('#image_path',os.path.exists(image_path),image_path)
        # image_path = folder_paths.get_annotated_filepath(image) #文件名
        
        if not os.path.exists(image_path):
            image_path,images=create_temp_file(image, self.uuid)


        img = node_helpers.pillow(Image.open, image_path)
        
        output_images = []
        output_masks = []
        w, h = None, None

        excluded_formats = ['MPO']
        
        for i in ImageSequence.Iterator(img):
            i = node_helpers.pillow(ImageOps.exif_transpose, i)

            if i.mode == 'I':
                i = i.point(lambda i: i * (1 / 255))
            image = i.convert("RGB")

            if len(output_images) == 0:
                w = image.size[0]
                h = image.size[1]
            
            if image.size[0] != w or image.size[1] != h:
                continue
            
            image = np.array(image).astype(np.float32) / 255.0
            image = torch.from_numpy(image)[None,]
            if 'A' in i.getbands():
                mask = np.array(i.getchannel('A')).astype(np.float32) / 255.0
                mask = 1. - torch.from_numpy(mask)
            else:
                # 尺寸不对，需要按照image来
                mask = torch.zeros((h, w), dtype=torch.float32, device="cpu")

            output_images.append(image)
            output_masks.append(mask.unsqueeze(0))

        if len(output_images) > 1 and img.format not in excluded_formats:
            output_image = torch.cat(output_images, dim=0)
            output_mask = torch.cat(output_masks, dim=0)
        else:
            output_image = output_images[0]
            output_mask = output_masks[0]

        return {"ui":{"images": images},"result": (output_image, output_mask)}

        # return (output_image, output_mask)
