import json
import os.path

from import_qt_mode import *
from UI.manual_image_matching.image_items import Ui_Form as Ui_Image_Items
from PIL import Image
import rawpy, io


class ImageLabel(QLabel, Ui_Image_Items):
    drop_sign = Signal(dict)  # 粘贴的位置
    drop_from_sign = Signal(dict)  # 粘贴来源的位置
    select_clearn_all_sign = Signal()
    selected_sign = Signal()  # 有选中
    delete_image_sign = Signal(list) # 删除通知

    def __init__(self, text, image_index, image_path, image_name, root_path, is_goods_list, parent=None, windows=None,
                 top_windows=None):
        super().__init__(parent)
        self.setupUi(self)
        # self.setFixedSize(150, 160)
        # self.ui_image.setFixedSize(150, 150)
        self.windows = windows
        self.top_windows = top_windows
        self.parent = parent
        self.text = image_name
        self.image_index = image_index
        self.image_path = image_path
        self.image_name = image_name
        self.root_path = root_path
        self.ui_text.setText(self.text)

        # 是图片列表还是普通列表
        self.is_goods_list = is_goods_list
        self.icon = None
        self.set_label_image()
        self.setMouseTracking(True)
        self.drag_start_position = None
        self.selected = False
        self.setAcceptDrops(True)

    def set_image_label_windows(self,windows):
        self.windows = windows

    def show_text(self):
        self.ui_text.setText(self.text)

    def crop_to_square(self, img):
        # 打开图片
        width, height = img.size  # 获取原始图片的宽度和高度
        if width == height:
            return img
        if width > height:
            _x = int((width - height) / 2)
            img = img.crop((_x, 0, width - _x, height))
        else:
            _y = int((height - width) / 2)
            img = img.crop((0, _y, width, height - _y))
        return img

    def set_new_parent(self, parent):
        self.parent = parent
        self.setParent(parent)

    def show_big_image(self):
        if self.top_windows is not None:
            if self.icon:
                self.top_windows.show_big_image(self.icon)

    def set_label_image2(self):
        try:
            w, h = self.ui_image.width() * 2, self.ui_image.height() * 2
            if "CR2" == self.image_path[-3:]:
                _img_raw = Image.open(self.image_path)
            else:
                if "jpg" == self.image_path[-3:] or "png" == self.image_path[-3:]:
                    _img_raw = Image.open(self.image_path)
                else:
                    with rawpy.imread(self.image_path) as raw:
                        raw_image = raw.postprocess()
                    _img_raw = Image.fromarray(raw_image)

            size = (w, int(_img_raw.height * w / _img_raw.width))
            _img_raw = _img_raw.resize(size)
            _img_raw = _img_raw.convert("RGB")

            bytes_io = io.BytesIO()
            _img_raw.save(bytes_io, "JPEG")

            icon = QPixmap()
            icon.loadFromData(bytes_io.getvalue())
            self.icon = icon
            icon = icon.scaled(
                self.ui_image.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation
            )
            self.ui_image.setPixmap(icon)
        except:
            pass

    def set_label_image(self):
        try:
            w, h = self.ui_image.width() * 2, self.ui_image.height() * 2
            if "CR2" == self.image_path[-3:]:
                _img_raw = Image.open(self.image_path)
            else:
                if "jpg" == self.image_path[-3:] or "png" == self.image_path[-3:]:
                    _img_raw = Image.open(self.image_path)
                else:
                    with rawpy.imread(self.image_path) as raw:
                        raw_image = raw.postprocess()
                    _img_raw = Image.fromarray(raw_image)

            # 取缩略图
            _img_raw.thumbnail((w, int(_img_raw.height * w / _img_raw.width)))

            size = (w, int(_img_raw.height * w / _img_raw.width))
            _img_raw = _img_raw.resize(size)
            _img_raw = _img_raw.convert("RGB")

            bytes_io = io.BytesIO()
            _img_raw.save(bytes_io, "JPEG")

            icon = QPixmap()
            icon.loadFromData(bytes_io.getvalue())
            self.icon = icon
            icon = icon.scaled(
                self.ui_image.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation
            )
            self.ui_image.setPixmap(icon)
        except:
            pass

    def get_image_orientation(self, img):
        # 获取EXIF数据
        exif = img._getexif()
        if exif is not None:
            # EXIF标签274对应的是Orientation
            orientation = exif.get(0x0112)
            if orientation == 2:
                # 水平翻转
                img = img.transpose(Image.FLIP_LEFT_RIGHT)
            elif orientation == 3:
                # 旋转180度
                img = img.rotate(180, expand=True)
            elif orientation == 4:
                # 垂直翻转
                img = img.transpose(Image.FLIP_TOP_BOTTOM)
            elif orientation == 5:
                # 水平翻转后顺时针旋转90度
                img = img.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_270)
            elif orientation == 6:
                # 顺时针旋转90度
                img = img.transpose(Image.ROTATE_270)
            elif orientation == 7:
                # 水平翻转后逆时针旋转90度
                img = img.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_90)
            elif orientation == 8:
                # 逆时针旋转90度
                img = img.transpose(Image.ROTATE_90)
            else:
                pass

        return img

    def set_selected(self, selected):
        self.selected = selected
        self.setStyleSheet("background-color: yellow;" if selected else "background-color: white;")

    def mouseMoveEvent(self, event):
        if not (event.buttons() & Qt.LeftButton) or self.drag_start_position is None:
            return

        if (event.pos() - self.drag_start_position).manhattanLength() < QApplication.startDragDistance():
            return

        print("Starting drag...{}".format(self.image_name))  # 调试信息

        # 创建拖拽任务
        drag = QDrag(self)
        mime_data = QMimeData()

        # 收集所有选中的控件的数据
        data = QByteArray()
        stream = QDataStream(data, QIODevice.WriteOnly)

        # 写入图片索引
        for widget in self.parent.findChildren(ImageLabel):
            if widget.selected:
                if widget != self:
                    stream.writeInt32(widget.image_index)

        # 设置当前为选中
        self.set_selected(True)

        stream.writeInt32(self.image_index)

        mime_data.setData('application/x-draggable-labels', data)
        drag.setMimeData(mime_data)

        # 可选：设置一个图标或快照来表示正在拖拽的对象
        pixmap = QPixmap(self.size())
        self.render(pixmap)
        drag.setPixmap(pixmap)

        # 设置热点为鼠标点击位置相对窗口的位置
        hot_spot = event.position().toPoint()
        drag.setHotSpot(hot_spot)

        # 开始拖拽操作
        result = drag.exec(Qt.MoveAction)
        if result == Qt.MoveAction:
            self.setParent(None)  # 如果成功移动，则从原位置移除
            self.hide()

        self.drag_start_position = None
        print("end drag...{}".format(self.image_name))  # 调试信息

    def mouseReleaseEvent(self, event):
        super().mouseReleaseEvent(event)
        # print("Mouse released.")  # 调试信息
        self.drag_start_position = None

    # 清除所有已选
    def clear_all(self):
        self.select_clearn_all_sign.emit()

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.show_big_image()
            self.drag_start_position = event.pos()
            self.selected_sign.emit()  # 发送单击事件给父窗口
            if event.modifiers() & Qt.ControlModifier:
                # 如果按下了 Ctrl 键，则进行复选
                self.set_selected(not self.selected)
            else:
                self.clear_all()
                self.set_selected(not self.selected)

    def dragEnterEvent(self, event):
        event.acceptProposedAction()

    def dragMoveEvent(self, event):
        event.acceptProposedAction()

    # 粘贴来源的位置，发送信号
    def drop_from_event(self, return_data):
        self.drop_from_sign.emit(return_data)

    def dropEvent(self, event):
        mime = event.mimeData()
        if mime.hasFormat('application/x-draggable-labels'):

            return_data = {"is_same_folder": True,
                           "from_image_index_list": [],
                           "from_source": "",
                           "to_image_index": 0,
                           "to_source": "",
                           }
            byte_array = mime.data('application/x-draggable-labels')
            stream = QDataStream(byte_array, QIODevice.ReadOnly)
            while not stream.atEnd():
                image_index = stream.readInt32()
                return_data["from_image_index_list"].append(image_index)

            from_source = event.source()
            return_data["from_source"] = from_source.windows
            return_data["to_source"] = self.windows
            return_data["to_image_index"] = self.image_index

            if from_source.windows == self.windows:
                return_data["is_same_folder"] = True
                print("同文件夹")
            else:
                return_data["is_same_folder"] = False
                print("不同文件夹")

            if return_data["is_same_folder"] is False:
                # 不同文件夹处理，处理发送到来源文件夹的操作
                from_source.drop_from_event(return_data)
            else:
                # 同文件夹处理，发送粘贴的信号
                self.drop_sign.emit(return_data)

    def contextMenuEvent(self, event):
        # 创建一个QMenu对象
        menu = QMenu(self)

        # 添加菜单项
        delete_action = menu.addAction("删除图片")

        # 连接菜单项到槽函数
        action = menu.exec(self.mapToGlobal(event.pos()))
        if action == delete_action:
            self.delete_selected_item()

    def delete_selected_item(self):
        # 获取当前选中的项并删除它
        print("delete_selected_item")
        image_index_list = [self.image_index]
        # 写入图片索引
        for widget in self.parent.findChildren(ImageLabel):
            if widget.selected:
                if widget != self:
                    image_index_list.append(widget.image_index)

        if image_index_list:
            self.delete_image_sign.emit(image_index_list)

    def del_image(self):
        """
        删除图片
        """
        parentPath, _ = os.path.split(self.root_path)
        cutImagePath = "{}/原始图_已抠图/{}.png".format(parentPath, self.image_name)
        f = False
        try:
            if os.path.exists(self.image_path):
                os.remove(self.image_path)
                f = True

            if os.path.exists(cutImagePath):
                os.remove(cutImagePath)
                f = True

        except FileNotFoundError:
            print(f"删除文件失败.")
        except Exception as e:
            print(f"发生错误: {e}")

        if f:
            self.hide()
            del self
