import os
import sys
from PyQt5 import QtWidgets, QtGui, QtCore
from datetime import datetime
import json
import subprocess

class MainView(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.version = "1.0.0"  # 프로그램 버전 설정
        self.default_save_path = os.path.join(os.path.expanduser("~"), "Desktop")  # 바탕화면 경로 설정
        self.file_paths = []  # 파일 경로 저장 리스트
        self.loadSettings()  # 설정 로드
        self.setupUI()  # UI 설정
        self.setButtons()  # 버튼 설정
        self.sortTreeView(0, True)  # 기본 파일명 오름차순 정렬
        self.channel_options = ["채널 1", "채널 2", "채널 3"]  # 채널 옵션 설정

    def loadSettings(self):
        self.settings_file = "settings.json"
        if os.path.exists(self.settings_file):
            with open(self.settings_file, "r", encoding="utf-8") as file:
                self.settings = json.load(file)  # 설정 파일 로드
                self.default_save_path = self.settings.get("default_save_path", self.default_save_path)
                self.file_paths = self.settings.get("file_paths", [])
        else:
            self.settings = {"theme": "light"}  # 기본 설정

    def saveSettings(self):
        settings = {
            "theme": self.settings.get("theme", "light"),
            "default_save_path": self.default_save_path,
            "file_paths": self.file_paths
        }
        with open(self.settings_file, "w", encoding="utf-8") as file:
            json.dump(settings, file, ensure_ascii=False)  # 설정 파일 저장

    def setupUI(self):
        self.setWindowTitle("DBC to C Converter")
        self.setGeometry(100, 100, 1000, 600)  # 창 크기 조정

        # 메뉴바 추가
        self.menu_bar = self.menuBar()

        file_menu = self.menu_bar.addMenu("파일")
        edit_menu = self.menu_bar.addMenu("편집")
        view_menu = self.menu_bar.addMenu("보기")
        tools_menu = self.menu_bar.addMenu("도구")

        # 파일 메뉴 항목 추가
        file_menu.addAction("파일 추가", self.FilesOpen)
        file_menu.addSeparator()
        file_menu.addAction("선택 파일 삭제", self.deleteSelectedFiles)
        file_menu.addSeparator()
        file_menu.addAction("모든 파일 삭제", self.deleteAllFiles)

        # 편집 메뉴 항목 추가
        edit_menu.addAction("모두 선택", self.selectAllFiles)
        edit_menu.addSeparator()
        edit_menu.addAction("선택 반전", self.invertSelection)

        # 보기 메뉴 항목 추가
        size_menu = view_menu.addMenu("창크기")
        size_menu.addAction("작게", lambda: self.setWindowSize("small"))
        size_menu.addSeparator()
        size_menu.addAction("보통", lambda: self.setWindowSize("medium"))
        size_menu.addSeparator()
        size_menu.addAction("크게", lambda: self.setWindowSize("large"))
        size_menu.addSeparator()
        size_menu.addAction("자동", lambda: self.setWindowSize("auto"))

        sort_menu = view_menu.addMenu("정렬")
        sort_menu.addAction("파일명 오름차순", lambda: self.sortTreeView(0, False))
        sort_menu.addSeparator()
        sort_menu.addAction("파일명 내림차순", lambda: self.sortTreeView(0, True))
        sort_menu.addSeparator()
        sort_menu.addAction("파일경로 오름차순", lambda: self.sortTreeView(1, False))
        sort_menu.addSeparator()
        sort_menu.addAction("파일경로 내림차순", lambda: self.sortTreeView(1, True))
        sort_menu.addSeparator()
        sort_menu.addAction("파일크기 오름차순", lambda: self.sortTreeView(3, False))
        sort_menu.addSeparator()
        sort_menu.addAction("파일크기 내림차순", lambda: self.sortTreeView(3, True))

        # 도구 메뉴 항목 추가
        tools_menu.addAction("설정", self.openSettings)
        tools_menu.addSeparator()
        tools_menu.addAction("프로그램 정보", self.openAbout)

        # 메인 위젯 설정
        main_widget = QtWidgets.QWidget()
        self.setCentralWidget(main_widget)
        main_layout = QtWidgets.QVBoxLayout(main_widget)

        # 파일 리스트 설정
        self.tree = QtWidgets.QTreeWidget()
        self.tree.setColumnCount(4)
        self.tree.setHeaderLabels(['파일명', '파일경로', '채널', '파일크기'])
        self.tree.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
        self.tree.header().sectionClicked.connect(self.onHeaderClicked)
        self.tree.itemDoubleClicked.connect(self.onItemDoubleClicked)
        main_layout.addWidget(self.tree)

        # 버튼 프레임 설정
        button_frame = QtWidgets.QWidget()
        button_layout = QtWidgets.QHBoxLayout(button_frame)
        main_layout.addWidget(button_frame)

        self.btn_list = QtWidgets.QPushButton("파일 추가")
        self.btn_list.clicked.connect(self.FilesOpen)
        button_layout.addWidget(self.btn_list)

        self.btn_delete = QtWidgets.QPushButton("파일 삭제")
        self.btn_delete.clicked.connect(self.deleteSelectedFiles)
        button_layout.addWidget(self.btn_delete)

        self.btn_delete_all = QtWidgets.QPushButton("모든 파일 삭제")
        self.btn_delete_all.clicked.connect(self.deleteAllFiles)
        button_layout.addWidget(self.btn_delete_all)

        self.btn_convert = QtWidgets.QPushButton("변환")
        self.btn_convert.clicked.connect(self.convertFiles)
        button_layout.addWidget(self.btn_convert)

        self.btn_clear_alerts = QtWidgets.QPushButton("알림창 내용 삭제")
        self.btn_clear_alerts.clicked.connect(self.clearAlerts)
        button_layout.addWidget(self.btn_clear_alerts)

        # 알림창 설정
        self.alert_text = QtWidgets.QTextEdit()
        self.alert_text.setReadOnly(True)
        main_layout.addWidget(self.alert_text)

        # 초기 테마 설정 적용
        if self.settings["theme"] == "light":
            self.setLightMode()

    def setButtons(self):
        self.btn_list.clicked.disconnect()
        self.btn_delete.clicked.disconnect()
        self.btn_delete_all.clicked.disconnect()
        self.btn_clear_alerts.clicked.disconnect()
        self.btn_list.clicked.connect(self.FilesOpen)
        self.btn_delete.clicked.connect(self.deleteSelectedFiles)
        self.btn_delete_all.clicked.connect(self.deleteAllFiles)
        self.btn_clear_alerts.clicked.connect(self.clearAlerts)

    def FilesOpen(self):
        file_paths, _ = QtWidgets.QFileDialog.getOpenFileNames(
            self, "파일 열기", "", "DBC 파일 (*.dbc);;모든 파일 (*.*)"
        )
        if file_paths:
            existing_files = [self.tree.topLevelItem(i).text(0) for i in range(self.tree.topLevelItemCount())]
            duplicate_files = [os.path.split(file_path)[1] for file_path in file_paths if os.path.split(file_path)[1] in existing_files]
            new_files = [file_path for file_path in file_paths if os.path.split(file_path)[1] not in existing_files]

            if duplicate_files:
                self.showDuplicateFilesWarning(duplicate_files, new_files, [os.path.split(file_path)[1] for file_path in new_files])
                self.updateAlertText(f"중복 파일 경고", duplicate_files)
            if new_files:
                self.populateTreeView(new_files)
                self.file_paths.extend(new_files)  # 파일 경로 저장
                self.updateAlertText(f"파일 추가 완료", [os.path.split(file_path)[1] for file_path in new_files])

    def deleteSelectedFiles(self):
        selected_items = self.tree.selectedItems()
        if not selected_items:
            self.showWarning("경고", "선택된 파일이 없습니다")
            self.updateAlertText("파일 삭제 실패", ["선택된 파일이 없습니다"])
            return
        deleted_files = [item.text(0) for item in selected_items]
        for item in selected_items:
            index = self.tree.indexOfTopLevelItem(item)
            self.tree.takeTopLevelItem(index)
        self.updateAlertText(f"파일 삭제 완료", deleted_files)

    def deleteAllFiles(self):
        if self.tree.topLevelItemCount() == 0:
            self.showWarning("경고", "삭제할 파일이 없습니다")
            self.updateAlertText("모든 파일 삭제 실패", ["삭제할 파일이 없습니다"])
            return
        deleted_files = [self.tree.topLevelItem(i).text(0) for i in range(self.tree.topLevelItemCount())]
        self.tree.clear()
        self.updateAlertText(f"모든 파일 삭제 완료", deleted_files)

    def clearAlerts(self):
        self.alert_text.clear()

    def showWarning(self, title, message):
        warning_box = QtWidgets.QMessageBox(self)
        warning_box.setIcon(QtWidgets.QMessageBox.Warning)
        warning_box.setWindowTitle(title)
        warning_box.setText(message)
        warning_box.exec_()

    def showDuplicateFilesWarning(self, duplicate_files, new_files, new_files_names):
        duplicate_files_str = "\n".join(duplicate_files)
        new_files_str = "\n".join(new_files_names)
        if new_files:
            self.showWarning("중복 파일 경고", f"중복 파일이 존재합니다\n\n{duplicate_files_str}\n\n\n중복 파일을 제외한 신규 파일을 추가합니다\n\n{new_files_str}")
        else:
            self.showWarning("중복 파일 경고", f"중복 파일이 존재합니다\n\n{duplicate_files_str}")

    def sortTreeView(self, col, reverse):
        items = []
        for i in range(self.tree.topLevelItemCount()):
            item = self.tree.takeTopLevelItem(0)
            items.append(item)
        items.sort(key=lambda x: x.text(col), reverse=reverse)
        for item in items:
            self.tree.addTopLevelItem(item)

    def selectAllFiles(self):
        for i in range(self.tree.topLevelItemCount()):
            self.tree.topLevelItem(i).setSelected(True)

    def invertSelection(self):
        for i in range(self.tree.topLevelItemCount()):
            item = self.tree.topLevelItem(i)
            item.setSelected(not item.isSelected())

    def setWindowSize(self, size):
        if size == "small":
            self.resize(600, 400)
        elif size == "medium":
            self.resize(800, 600)
        elif size == "large":
            self.resize(1000, 800)
        elif size == "auto":
            self.adjustSize()

    def openSettings(self):
        settings_window = QtWidgets.QDialog(self)
        settings_window.setWindowTitle("설정")
        settings_window.setGeometry(100, 100, 400, 300)
        layout = QtWidgets.QVBoxLayout(settings_window)
        label = QtWidgets.QLabel("설정 창입니다.")
        label.setAlignment(QtCore.Qt.AlignCenter)
        layout.addWidget(label)
        settings_window.exec_()

    def openAbout(self):
        about_window = QtWidgets.QDialog(self)
        about_window.setWindowTitle("프로그램 정보")
        about_window.setGeometry(100, 100, 400, 300)
        layout = QtWidgets.QVBoxLayout(about_window)
        label1 = QtWidgets.QLabel("이 프로그램은 DBC 파일을 C 파일로 변환합니다.")
        label1.setAlignment(QtCore.Qt.AlignCenter)
        layout.addWidget(label1)
        label2 = QtWidgets.QLabel("프로그램 정보")
        label2.setAlignment(QtCore.Qt.AlignCenter)
        layout.addWidget(label2)
        label3 = QtWidgets.QLabel(f"버전: {self.version}")
        label3.setAlignment(QtCore.Qt.AlignCenter)
        layout.addWidget(label3)
        about_window.exec_()

    def setLightMode(self):
        self.setStyleSheet("background-color: white; color: black;")
        self.alert_text.setStyleSheet("background-color: white; color: black;")
        self.tree.setStyleSheet("background-color: white; color: black;")
        self.menu_bar.setStyleSheet("background-color: white; color: black;")
        self.btn_list.setStyleSheet("background-color: white; color: black;")
        self.btn_delete.setStyleSheet("background-color: white; color: black;")
        self.btn_delete_all.setStyleSheet("background-color: white; color: black;")
        self.btn_convert.setStyleSheet("background-color: white; color: black;")
        self.btn_clear_alerts.setStyleSheet("background-color: white; color: black;")

    def populateTreeView(self, file_paths):
        def format_file_size(size_in_bytes):
            size_in_kb = size_in_bytes / 1024
            return f"{size_in_kb:.2f} KB"

        for file_path in file_paths:
            directory, file = os.path.split(file_path)
            fsize = format_file_size(os.path.getsize(file_path))
            item = QtWidgets.QTreeWidgetItem([file, directory, self.channel_options[0], fsize])
            self.tree.addTopLevelItem(item)

    def updateAlertText(self, message, file_list):
        current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.alert_text.append(f"[{current_time}] {message}")
        for file in file_list:
            self.alert_text.append(f"  - {file}")
        self.alert_text.setAlignment(QtCore.Qt.AlignLeft)

    def convertFiles(self):
        for file_path in self.file_paths:
            try:
                subprocess.run(["python", "DBC_to_C_RX.py", file_path], check=True)
                subprocess.run(["python", "DBC_to_C_TX.py", file_path], check=True)
                self.updateAlertText(f"변환 성공", [file_path])
            except subprocess.CalledProcessError as e:
                self.updateAlertText(f"변환 실패: {e}", [file_path])

    def onHeaderClicked(self, logicalIndex):
        header = self.tree.headerItem()
        if header.text(logicalIndex).endswith("▲"):
            self.sortTreeView(logicalIndex, True)
            header.setText(logicalIndex, header.text(logicalIndex).replace("▲", "▼"))
        else:
            self.sortTreeView(logicalIndex, False)
            header.setText(logicalIndex, header.text(logicalIndex).replace("▼", "▲"))

    def onItemDoubleClicked(self, item, column):
        if column == 0:  # 파일명을 더블클릭한 경우
            file_path = os.path.join(item.text(1), item.text(0))
            os.startfile(file_path)
        elif column == 1:  # 경로를 더블클릭한 경우
            os.startfile(item.text(1))

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    main_view = MainView()
    main_view.show()
    sys.exit(app.exec_())