# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'EFA.ui'
#
# Created by: PyQt5 UI code generator 5.15.10
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.
import os
os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
import numpy as np
import pandas as pd

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QImage, QPixmap, QPainterPath, QPainter,QPen,QColor
from PyQt5.QtCore import Qt
import sys
# import openpyxl


sys.path.append('/functions')
from functions.fourier_approx_norm_modify import fourier_approx_norm_modify
from functions.calc_dc_components_modify import calc_dc_components_modify
from functions.code2axis import code2axis


class MainWindow_1(QMainWindow):
    def __init__(self,chaincode,filename,id_full):
        super().__init__()
        self.setObjectName("MainWindow")
        self.resize(1143, 543)
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(10)
        self.setFont(font)
        self.centralwidget = QtWidgets.QWidget(self)
        self.centralwidget.setObjectName("centralwidget")
        self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox.setGeometry(QtCore.QRect(20, 80, 221, 401))
        self.groupBox.setObjectName("groupBox")
        
        self.checkBox = QtWidgets.QCheckBox(self.centralwidget)
        self.checkBox.setGeometry(QtCore.QRect(70, 100, 141, 51))
        self.checkBox.setObjectName("checkBox")
        self.checkBox.setChecked(True)
        self.checkBox_2 = QtWidgets.QCheckBox(self.centralwidget)
        self.checkBox_2.setGeometry(QtCore.QRect(70, 150, 141, 51))
        self.checkBox_2.setObjectName("checkBox_2")
        self.checkBox_2.setChecked(True)
        self.checkBox_3 = QtWidgets.QCheckBox(self.centralwidget)
        self.checkBox_3.setGeometry(QtCore.QRect(70, 200, 141, 51))
        self.checkBox_3.setObjectName("checkBox_3")
        self.checkBox_3.setChecked(True)
        self.checkBox_4 = QtWidgets.QCheckBox(self.centralwidget)
        self.checkBox_4.setGeometry(QtCore.QRect(70, 250, 141, 51))
        self.checkBox_4.setObjectName("checkBox_4")
        self.checkBox_4.setChecked(True)
        self.checkBox_5 = QtWidgets.QCheckBox(self.centralwidget)
        self.checkBox_5.setGeometry(QtCore.QRect(70, 300, 141, 51))
        self.checkBox_5.setObjectName("checkBox_5")
        self.checkBox_5.setChecked(True)
        self.checkBox_6 = QtWidgets.QCheckBox(self.centralwidget)
        self.checkBox_6.setGeometry(QtCore.QRect(70, 360, 141, 51))
        self.checkBox_6.setObjectName("checkBox_6")
        self.checkBox_6.setChecked(True)
        self.checkBox_7 = QtWidgets.QCheckBox(self.centralwidget)
        self.checkBox_7.setGeometry(QtCore.QRect(70, 420, 141, 51))
        self.checkBox_7.setObjectName("checkBox_7")
        self.checkBox_7.setChecked(True)

        self.widget = QtWidgets.QWidget(self.centralwidget)
        self.widget.setGeometry(QtCore.QRect(250, 90, 421, 371))
        self.widget.setObjectName("widget")
        self.widget_3 = QtWidgets.QWidget(self.centralwidget)
        self.widget_3.setGeometry(QtCore.QRect(690, 90, 431, 371))
        self.widget_3.setObjectName("widget_3")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(310, 50, 221, 21))
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(310, 10, 231, 21))
        self.label_2.setObjectName("label_2")
        self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
        self.textEdit.setGeometry(QtCore.QRect(550, 10, 81, 31))
        self.textEdit.setObjectName("textEdit")
        self.textEdit_2 = QtWidgets.QTextEdit(self.centralwidget)
        self.textEdit_2.setGeometry(QtCore.QRect(550, 50, 81, 31))
        self.textEdit_2.setObjectName("textEdit_2")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(700, 10, 201, 31))
        self.pushButton.setObjectName("pushButton")
        self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_2.setGeometry(QtCore.QRect(700, 50, 201, 31))
        self.pushButton_2.setObjectName("pushButton_2")
        self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_3.setGeometry(QtCore.QRect(910, 50, 201, 31))
        self.pushButton_3.setObjectName("pushButton_3")
        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setGeometry(QtCore.QRect(250, 470, 421, 16))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(8)
        self.label_3.setFont(font)
        self.label_3.setObjectName("label_3")
        self.label_4 = QtWidgets.QLabel(self.centralwidget)
        self.label_4.setGeometry(QtCore.QRect(750, 470, 421, 16))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(8)
        self.label_4.setFont(font)
        self.label_4.setObjectName("label_4")
        self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
        self.graphicsView.setGeometry(QtCore.QRect(250, 90, 421, 371))
        self.graphicsView.setObjectName("graphicsView")
        self.graphicsView_2 = QtWidgets.QGraphicsView(self.centralwidget)
        self.graphicsView_2.setGeometry(QtCore.QRect(690, 90, 431, 371))
        self.graphicsView_2.setObjectName("graphicsView_2")
        self.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(self)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 1143, 25))
        self.menubar.setObjectName("menubar")
        self.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(self)
        self.statusbar.setObjectName("statusbar")
        self.setStatusBar(self.statusbar)

        _translate = QtCore.QCoreApplication.translate
        self.setWindowTitle(_translate("MainWindow", "EFA"))
        self.checkBox.setText(_translate("MainWindow", "Translatoin"))
        self.checkBox_2.setText(_translate("MainWindow", "Reverse"))
        self.checkBox_3.setText(_translate("MainWindow", "Scale"))
        self.checkBox_4.setText(_translate("MainWindow", "Rotate"))
        self.checkBox_5.setText(_translate("MainWindow", "Starting point"))
        self.checkBox_6.setText(_translate("MainWindow", "Y-symmetric"))
        self.checkBox_7.setText(_translate("MainWindow", "X-symmetric"))
        self.groupBox.setTitle(_translate("MainWindow", "normalization options"))
        self.label.setText(_translate("MainWindow", "Visualized harmonic number:"))
        self.label_2.setText(_translate("MainWindow", "Maximum harmonic number:"))
        self.pushButton.setText(_translate("MainWindow", "Calculate and save "))
        self.pushButton_2.setText(_translate("MainWindow", "Plot curve"))
        self.pushButton_3.setText(_translate("MainWindow", "Save curve"))
        self.pushButton_2.setEnabled(False)
        self.pushButton_3.setEnabled(False)
        self.textEdit.setText("35")
        self.textEdit_2.setText("35")
        self.label_3.setText(_translate("self", "reconstructed shapes using EFDs (red line) and chain-code (bhue line)"))
        self.label_4.setText(_translate("self", "reconstructed shapes using normalized EFDs"))

        self.scene = QGraphicsScene()
        self.scene_1 = QGraphicsScene()
        self.chaincode = chaincode
        self.id_full = id_full
        self.filename = filename
        self.option = [1,1,1,1,1,1,1]

        self.checkBox_4.stateChanged.connect(self.onCheckBox4StateChanged)
        self.checkBox_5.stateChanged.connect(self.onCheckBox4StateChanged)
        self.pushButton.clicked.connect(self.cal_hs)
        self.pushButton_2.clicked.connect(self.plot_hs)
        self.pushButton_3.clicked.connect(self.save_hs)


    def onCheckBox4StateChanged(self):
        # Assuming you have imported Tkinter as tk
        # and you have a Tkinter variable handles
        t_1 = self.checkBox_4.isChecked()
        t_2 = self.checkBox_5.isChecked()

        if t_1 == 1 and t_2 == 1:
            self.checkBox_6.setEnabled(True)
            self.checkBox_7.setEnabled(True)
        else:
            self.checkBox_6.setChecked(False) 
            self.checkBox_7.setChecked(False) 
            self.checkBox_6.setEnabled(False)
            self.checkBox_7.setEnabled(False)


    def cal_hs(self):
        circle = self.textEdit.toPlainText()
        if circle.isdigit():
            numofharmoinc = int(circle)
            if numofharmoinc <= 0:
                QMessageBox.warning(self, '', 'please enter the positive number.')
                return
        else:
            QMessageBox.warning(self, '', 'please enter the number.')
            return
        
        self.option = [
            self.checkBox_4.isChecked(),
            self.checkBox_3.isChecked(),
            self.checkBox_2.isChecked(),
            self.checkBox_6.isChecked(),
            self.checkBox_7.isChecked(),
            self.checkBox_5.isChecked(),
            self.checkBox.isChecked()
        ]
        # 假设 chaincode 是一个 (N, 2) 的数组，表示 2D 点
        # num_points = 1000  # 降采样后的点数
        # indices = np.linspace(0, len(self.chaincode) - 1, num_points).astype(int)
        # simplified_chaincode = self.chaincode[indices]

        _, a, b, c, d = fourier_approx_norm_modify(self.chaincode, numofharmoinc, 400, 1,  self.option)
        t=np.transpose([a ,b, c, d])
        Hs = np.reshape(t, (1, -1))
        coffs = [["filepath"]]
        cols = numofharmoinc * 4
        # matrix = []
        # for col in range(1, cols + 1):
        #     letter = chr(ord('a') + (col - 1) % 4)
        #     number = str((col - 1) // 4 + 1)
        #     matrix.append(letter + number)
        matrix = [f"{chr(97 + (col - 1) % 4)}{(col - 1) // 4 + 1}" for col in range(1, cols + 1)]
        coffs[0].extend(matrix)
        coffs.append([f"{self.filename[:-4]}_{self.id_full}"])
        coffs[1].extend(Hs.flatten().tolist())

        df = pd.DataFrame(coffs)
        # 确保目录存在
        output_dir = "results/"
        os.makedirs(output_dir, exist_ok=True)
        with pd.ExcelWriter(f"results/{self.filename[:-4]}_{self.id_full}_info.xlsx", engine='openpyxl', mode='a', if_sheet_exists='replace') as writer:
            df.to_excel(writer, sheet_name='Sheet2', index=False, header=False)
        QMessageBox.information(None, "Success", "  done!  ")
        self.pushButton_2.setEnabled(True)
        self.pushButton_3.setEnabled(True)   


    def plot_hs(self):
        self.scene.clear()
        self.scene_1.clear()
        chain_code = self.chaincode
        if (self.textEdit.toPlainText()).isdigit():
            max_numofharmoinc = int(self.textEdit.toPlainText())
            if max_numofharmoinc <= 0:
                QMessageBox.warning(self, '', 'please enter the positive number.')
                return
        else:
            QMessageBox.warning(self, '', 'please enter the number.')
            return


        if chain_code.size > 0:
            contour_points = np.array([0, 0])
            chain_points = code2axis(chain_code, contour_points)
            for i in range(len(chain_points)-1):
                x1, y1 = chain_points[i,:]
                x2, y2 = chain_points[i + 1,:]
                line = QGraphicsLineItem(x1, y1, x2, y2)
                line.setPen(QPen(QColor(0, 0, 255)))
                self.scene.addItem(line)
                self.scene_1.setSceneRect(self.scene_1.itemsBoundingRect()) 

            circle = self.textEdit_2.toPlainText()
            if circle.isdigit():
                numofharmoinc = int(circle)
                if numofharmoinc <= 0:
                    QMessageBox.warning(self, '', 'please enter the positive number.')
                    return
                if numofharmoinc > max_numofharmoinc:
                    QMessageBox.warning(self, 'message', f"The input must be less than {max_numofharmoinc}")
                else:
                    ro = self.checkBox_4.isChecked()
                    sc = self.checkBox_3.isChecked()
                    re = self.checkBox_2.isChecked()
                    y_sy = self.checkBox_6.isChecked()
                    x_sy = self.checkBox_7.isChecked()
                    sta = self.checkBox_5.isChecked()
                    trans = self.checkBox.isChecked()
                    option = [ro, sc, re, y_sy, x_sy, sta, trans]

                    x_,_,_,_,_ = fourier_approx_norm_modify(chain_code, numofharmoinc, 400, 0, option)
                    chain_points_approx = np.vstack((x_, x_[0,:]))
                    # print(chain_points_approx)

                    for i in range(len(chain_points_approx)-1):
                        x1  = chain_points_approx[i,0] + contour_points[0]
                        y1 = contour_points[1] - chain_points_approx[i, 1]

                        x2  = chain_points_approx[i+1,0] + contour_points[0]
                        y2 = contour_points[1] - chain_points_approx[i+1, 1]

                        line = QGraphicsLineItem(y1, x1, y2, x2)
                        line.setPen(QPen(QColor(255, 0, 0)))
                        self.scene.addItem(line)
                    self.graphicsView.setScene(self.scene)
                    self.graphicsView.fitInView(self.graphicsView.sceneRect(), Qt.KeepAspectRatio)

                    
                    x_,_,_,_,_ = fourier_approx_norm_modify(chain_code, numofharmoinc, 400, 1, option)
                    chain_points_approx = x_
                    for i in range(len(chain_points_approx)-1):
                        x1  = chain_points_approx[i,0] + contour_points[0]
                        y1 = contour_points[1] - chain_points_approx[i, 1]

                        x2  = chain_points_approx[i+1,0] + contour_points[0]
                        y2 = contour_points[1] - chain_points_approx[i+1, 1]

                        line = QGraphicsLineItem(y1, x1, y2, x2)
                        line.setPen(QPen(QColor(255, 0, 0),0.01))
                        
                        self.scene_1.addItem(line)
                        self.scene_1.setSceneRect(self.scene_1.itemsBoundingRect()) 

                    self.graphicsView_2.setScene(self.scene_1)
                    self.graphicsView_2.fitInView(self.graphicsView_2.sceneRect(), Qt.KeepAspectRatio)
            else:
                QMessageBox.warning(self, '', 'please enter the number.')
                return
                
        else:
            print('Chain code is null')
            QMessageBox.warning(self, '', 'Chain code is null')





    # def plot_hs(self):
    #     self.scene.clear()
    #     self.scene_1.clear()
    #     chain_code = self.chaincode
    #     # a = self.a
    #     # b = self.b 
    #     # c = self.c
    #     # d = self.d
    #     max_numofharmoinc = int(self.textEdit.toPlainText())

    #     if chain_code.size > 0:
    #         contour_points = np.array([0, 0])
    #         chain_points = code2axis(chain_code, contour_points)
    #         for i in range(len(chain_points)-1):
    #             x1, y1 = chain_points[i,:]
    #             x2, y2 = chain_points[i + 1,:]
    #             line = QGraphicsLineItem(x1, y1, x2, y2)
    #             line.setPen(QPen(QColor(0, 0, 255)))
    #             self.scene.addItem(line)
    #             self.scene_1.setSceneRect(self.scene_1.itemsBoundingRect()) 

    #         circle = self.textEdit_2.toPlainText()
    #         numofharmoinc = int(circle)
    #         if numofharmoinc > max_numofharmoinc:
    #             QMessageBox.warning(self, 'message', f"The input must be less than {max_numofharmoinc}")
    #         else:

    #             x_, _, _, _, _ = fourier_approx_norm_modify(chain_code, numofharmoinc, 400, 0, self.option)
    #             # x_2, _, _, _, _  = fourier_approx_norm_modify(chain_code, numofharmoinc, 400, 1, self.option)


    #             chain_points_approx_1 = np.vstack((x_, x_[0,:]))
    #             # print(chain_points_approx)
    #             x_coords_1 = chain_points_approx_1[:, 0] + contour_points[0]
    #             y_coords_1 = contour_points[1] - chain_points_approx_1[:, 1]

    #             # pen_red = QPen(QColor(255, 0, 0))
    #             for x1, y1, x2, y2 in zip(x_coords_1[:-1], y_coords_1[:-1], x_coords_1[1:], y_coords_1[1:]):
    #             # for i in range(len(chain_points_approx)-1):
    #             #     x1  = chain_points_approx[i,0] + contour_points[0]
    #             #     y1 = contour_points[1] - chain_points_approx[i, 1]

    #             #     x2  = chain_points_approx[i+1,0] + contour_points[0]
    #             #     y2 = contour_points[1] - chain_points_approx[i+1, 1]

    #                 line = QGraphicsLineItem(y1, x1, y2, x2)
    #                 line.setPen(QPen(QColor(255, 0, 0)))
    #                 self.scene.addItem(line)
    #             self.graphicsView.setScene(self.scene)
    #             self.graphicsView.fitInView(self.graphicsView.sceneRect(), Qt.KeepAspectRatio)

                
    #             x_2,_,_,_,_ = fourier_approx_norm_modify(chain_code, numofharmoinc, 400, 1, mode, option)
    #             chain_points_approx = x_2
    #             # _, _, Tk, T = calc_dc_components_modify(chain_code, 0)
    #             # output = np.zeros((400, 2))
    #             # for t in range(400):
    #             #     x_2 = 0.0
    #             #     y_2 = 0.0
    #             #     for i in range(numofharmoinc):
    #             #         x_2 += (a[i] * np.cos(2 * (i + 1) * np.pi * (t) * Tk / (400 - 1) / T) + b[i] * np.sin(2 * (i + 1) * np.pi * (t) * Tk / (400 - 1) / T))
    #             #         y_2 += (c[i] * np.cos(2 * (i + 1) * np.pi * (t) * Tk / (400 - 1) / T) + d[i] * np.sin(2 * (i + 1) * np.pi * (t) * Tk / (400 - 1) / T))
    #             #     output[t, 0] =  x_2
    #             #     output[t, 1] =  y_2
    #             # chain_points_approx = output
    #             for i in range(len(chain_points_approx)-1):
    #                 x1  = chain_points_approx[i,0] + contour_points[0]
    #                 y1 = contour_points[1] - chain_points_approx[i, 1]

    #                 x2  = chain_points_approx[i+1,0] + contour_points[0]
    #                 y2 = contour_points[1] - chain_points_approx[i+1, 1]

    #                 line = QGraphicsLineItem(y1, x1, y2, x2)
    #                 line.setPen(QPen(QColor(255, 0, 0),0.01))
                    
    #                 self.scene_1.addItem(line)
    #                 self.scene_1.setSceneRect(self.scene_1.itemsBoundingRect()) 

    #             self.graphicsView_2.setScene(self.scene_1)
    #             self.graphicsView_2.fitInView(self.graphicsView_2.sceneRect(), Qt.KeepAspectRatio)

    #     else:
    #         print('Chain code is null')
    #         QMessageBox.warning(self, '', 'Chain code is null')

    def save_hs(self):
        options = QFileDialog.Options()
        defaultPath = './results/'
        defaultFileName = f"{defaultPath}{'_'.join(self.filename.split('.')[:-1])}_{self.id_full}.png"
        filePath, _ = QFileDialog.getSaveFileName(self, "Save File", defaultFileName, 
                                                  "PNG files (*.png);;JPEG files (*.jpg);;All Files (*)", options=options)

        if filePath:
            extension = filePath.split('.')[-1].lower()
            pixmap = QApplication.primaryScreen().grabWindow(self.winId()) 
            if extension == 'png':                
                pixmap.save(filePath+'.png')
            elif extension == 'jpg':
                pixmap.save(filePath+'.jpg')
            else:
                print('Unsupported file format. Image not saved.')

            print(f'Image saved as: {filePath}')


