import sys
import os
import json
from PyQt5.QtWidgets import (QApplication, QWidget, QGridLayout, QPushButton,
                             QFileDialog, QLabel, QVBoxLayout, QHBoxLayout,
                             QScrollArea, QFrame, QMessageBox, QLineEdit, QAction)  # QAction 추가
from PyQt5.QtGui import QIcon, QPixmap
from PyQt5.QtCore import Qt, QSize, QCoreApplication, QSettings

# 설정 파일 이름
CONFIG_FILE = "streamdeck_config.json"

# 기본 버튼 설정
DEFAULT_BUTTON_CONFIG = {
    "name": "New Button",
    "icon": None,
    "command": None
}


class StreamDeckButton(QPushButton):
    """스트림덱 버튼 위젯"""
    def __init__(self, config, button_id, parent=None):
        super().__init__(parent)
        self.config = config
        self.button_id = button_id  # 버튼 ID 저장
        self.setFixedSize(100, 100)  # 버튼 크기 고정
        self.update_button()
        self.clicked.connect(self.execute_command)

    def update_button(self):
        """버튼의 텍스트와 아이콘을 업데이트합니다."""
        text = self.config.get("name", "Unnamed")
        icon_path = self.config.get("icon")

        self.setText(text)  # 텍스트 설정

        if icon_path and os.path.exists(icon_path):
            icon = QIcon(icon_path)
            self.setIcon(icon)
            self.setIconSize(QSize(80, 80)) # 아이콘 크기 조절
        else:
            # 아이콘이 없으면 텍스트만 표시
            self.setIcon(QIcon())  # 아이콘 초기화
            self.setIconSize(QSize(0, 0)) # 아이콘 크기 초기화


    def execute_command(self):
        """버튼에 설정된 명령어를 실행합니다."""
        command = self.config.get("command")
        if command:
            try:
                os.system(command)
            except Exception as e:
                QMessageBox.critical(self, "Error", f"명령어 실행 오류: {e}")


class ConfigDialog(QWidget):
    """버튼 설정을 위한 대화 상자"""
    def __init__(self, config, button_id, parent=None):
        super().__init__(parent)
        self.config = config
        self.button_id = button_id
        self.setWindowTitle("버튼 설정")
        self.setGeometry(100, 100, 400, 300)  # 창 크기 설정

        self.name_label = QLabel("이름:")
        self.name_input = QLineEdit(self.config.get("name", ""))

        self.icon_label = QLabel("아이콘:")
        self.icon_path = self.config.get("icon", "")
        self.icon_button = QPushButton("아이콘 선택")
        self.icon_button.clicked.connect(self.choose_icon)
        self.icon_preview = QLabel()
        self.update_icon_preview()

        self.command_label = QLabel("명령어:")
        self.command_input = QLineEdit(self.config.get("command", ""))

        self.save_button = QPushButton("저장")
        self.save_button.clicked.connect(self.save_config)

        self.cancel_button = QPushButton("취소")
        self.cancel_button.clicked.connect(self.close)

        layout = QVBoxLayout()
        layout.addWidget(self.name_label)
        layout.addWidget(self.name_input)
        layout.addWidget(self.icon_label)
        icon_layout = QHBoxLayout()
        icon_layout.addWidget(self.icon_button)
        icon_layout.addWidget(self.icon_preview)
        layout.addLayout(icon_layout)
        layout.addWidget(self.command_label)
        layout.addWidget(self.command_input)

        button_layout = QHBoxLayout()
        button_layout.addWidget(self.save_button)
        button_layout.addWidget(self.cancel_button)
        layout.addLayout(button_layout)

        self.setLayout(layout)

    def choose_icon(self):
        """아이콘을 선택하는 파일 대화 상자를 엽니다."""
        file_dialog = QFileDialog()
        icon_path, _ = file_dialog.getOpenFileName(self, "아이콘 선택", "", "Images (*.png *.jpg *.bmp)")
        if icon_path:
            self.icon_path = icon_path
            self.update_icon_preview()

    def update_icon_preview(self):
        """선택된 아이콘을 미리보기로 표시합니다."""
        if self.icon_path and os.path.exists(self.icon_path):
            pixmap = QPixmap(self.icon_path)
            pixmap = pixmap.scaled(50, 50, Qt.KeepAspectRatio)  # 미리보기 크기 조절
            self.icon_preview.setPixmap(pixmap)
        else:
            self.icon_preview.clear()  # 아이콘 제거

    def save_config(self):
        """설정 값을 저장하고 대화 상자를 닫습니다."""
        self.config["name"] = self.name_input.text()
        self.config["icon"] = self.icon_path
        self.config["command"] = self.command_input.text()
        self.parent().update_button(self.button_id, self.config)  # 부모 윈도우의 버튼 업데이트
        self.close()



class MainWindow(QWidget):
    """메인 윈도우"""
    def __init__(self):
        super().__init__()
        self.setWindowTitle("스트림덱")
        self.setGeometry(100, 100, 600, 400)  # 창 크기 설정

        self.button_configs = self.load_config()
        self.buttons = {}  # 버튼 객체를 저장할 딕셔너리
        self.grid_layout = QGridLayout()

        self.init_ui()

    def init_ui(self):
        """UI를 초기화합니다."""
        self.create_buttons()
        self.add_button = QPushButton("버튼 추가")
        self.add_button.clicked.connect(self.add_new_button)

        main_layout = QVBoxLayout()
        scroll_area = QScrollArea()
        scroll_area.setWidgetResizable(True)

        widget = QWidget()
        widget.setLayout(self.grid_layout)
        scroll_area.setWidget(widget)

        main_layout.addWidget(scroll_area)
        main_layout.addWidget(self.add_button)

        self.setLayout(main_layout)


    def create_buttons(self):
        """설정 파일에 따라 버튼을 생성합니다."""
        for button_id, config in enumerate(self.button_configs):
            button = StreamDeckButton(config, button_id, self)
            button.setContextMenuPolicy(Qt.ActionsContextMenu)  # 컨텍스트 메뉴 활성화
            edit_action = QAction("편집", button)  # QAction 객체 생성
            edit_action.triggered.connect(lambda checked=False, id=button_id: self.open_config_dialog(id))
            button.addAction(edit_action)  # QAction 객체를 추가
            delete_action = QAction("삭제", button) # QAction 객체 생성
            delete_action.triggered.connect(lambda checked=False, id=button_id: self.delete_button(id))
            button.addAction(delete_action) # QAction 객체를 추가
            self.grid_layout.addWidget(button, button_id // 5, button_id % 5)  # 행/열 자동 배치
            self.buttons[button_id] = button  # 버튼 객체 저장


    def add_new_button(self):
        """새로운 버튼을 추가합니다."""
        new_config = DEFAULT_BUTTON_CONFIG.copy()
        self.button_configs.append(new_config)
        button_id = len(self.button_configs) - 1  # 새로운 버튼 ID
        self.save_config()
        self.create_buttons()  # 모든 버튼을 다시 생성
        self.open_config_dialog(button_id)  # 새 버튼 설정창 열기

    def delete_button(self, button_id):
        """버튼을 삭제합니다."""
        reply = QMessageBox.question(self, '삭제 확인', '정말로 삭제하시겠습니까?',
                                     QMessageBox.Yes | QMessageBox.No, QMessageBox.No)

        if reply == QMessageBox.Yes:
            del self.button_configs[button_id]
            self.save_config()
            # 레이아웃에서 위젯을 제거하고 삭제
            button_to_remove = self.buttons.pop(button_id)  # 딕셔너리에서 제거
            self.grid_layout.removeWidget(button_to_remove)
            button_to_remove.deleteLater()
            self.clear_layout(self.grid_layout)  # 레이아웃 정리
            self.create_buttons() # 버튼 다시 생성


    def clear_layout(self, layout):
        """레이아웃 내의 모든 위젯을 제거합니다."""
        while layout.count():
            item = layout.takeAt(0)
            widget = item.widget()
            if widget is not None:
                widget.deleteLater()
            else:
                self.clear_layout(item.layout())

    def open_config_dialog(self, button_id):
        """버튼 설정 대화 상자를 엽니다."""
        config_dialog = ConfigDialog(self.button_configs[button_id], button_id, self)
        config_dialog.show()

    def update_button(self, button_id, config):
        """버튼의 설정을 업데이트합니다."""
        self.button_configs[button_id] = config
        self.buttons[button_id].config = config  # StreamDeckButton의 config 업데이트
        self.buttons[button_id].update_button() # StreamDeckButton의 UI 업데이트
        self.save_config()


    def load_config(self):
        """설정 파일에서 설정을 로드합니다."""
        try:
            with open(CONFIG_FILE, "r") as f:
                return json.load(f)
        except FileNotFoundError:
            return [DEFAULT_BUTTON_CONFIG.copy()] # 기본 설정으로 시작
        except json.JSONDecodeError:
            QMessageBox.warning(self, "경고", "설정 파일이 손상되었습니다. 기본 설정으로 시작합니다.")
            return [DEFAULT_BUTTON_CONFIG.copy()]

    def save_config(self):
        """현재 설정을 설정 파일에 저장합니다."""
        try:
            with open(CONFIG_FILE, "w") as f:
                json.dump(self.button_configs, f, indent=4)
        except Exception as e:
             QMessageBox.critical(self, "Error", f"설정 저장 오류: {e}")

    def closeEvent(self, event):
        """윈도우가 닫힐 때 설정을 저장합니다."""
        self.save_config()
        event.accept() # 닫기 진행



if __name__ == "__main__":
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())