"""
Пример 4: Команды (Command)

Демонстрация использования @command:
- Привязка к кнопкам с автоматической блокировкой
- Привязка к сигналам
- Sync и async команды
"""

import sys
import asyncio
from qtpy.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QPushButton, QLabel, QProgressBar
)
from qtmvvm import BaseViewModel, command


class MainViewModel(BaseViewModel):
    """ViewModel с командами"""
    counter: int = 0
    status: str = "Готов"

    @command
    def increment(self):
        """Команда увеличения счётчика"""
        self.counter += 1
        self.status = f"Увеличено: {self.counter}"

    @command
    def decrement(self):
        """Команда уменьшения счётчика"""
        self.counter -= 1
        self.status = f"Уменьшено: {self.counter}"

    @command
    async def long_running_task(self):
        """Длительная асинхронная операция"""
        # Обновление свойств в async команде должно быть в главном потоке
        print("Выполнение...")
        self.status = f'Выполнение'
        for i in range(5):
            print(f"Тест: {i}")
            await asyncio.sleep(0.5)
            self.status = f'Прогресс: {i + 1}/5'
        self.status = f'Готово'


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Пример 4: Команды")

        self.vm = MainViewModel()

        # Виджеты
        self.counter_label = QLabel("Счётчик: 0")
        self.status_label = QLabel("Статус: Готов")
        
        self.inc_button = QPushButton("Увеличить (+)")
        self.dec_button = QPushButton("Уменьшить (-)")
        self.async_button = QPushButton("Запустить долгую задачу")
        
        self.progress = QProgressBar()
        self.progress.setRange(0, 0)  # Indeterminate mode
        self.progress.setVisible(False)

        # Привязка команд к кнопкам (operator <<)
        # Кнопка автоматически блокируется на время выполнения
        self.vm.increment << self.inc_button
        self.vm.decrement << self.dec_button
        self.vm.long_running_task << self.async_button

        # Сигналы для обновления UI
        self.vm.counter.valueChanged.connect(
            lambda v: self.counter_label.setText(f"Счётчик: {v}")
        )
        self.vm.status.valueChanged.connect(
            lambda v: self.status_label.setText(f"Статус: {v}")
        )

        # Показывать прогресс во время выполнения async команды
        self.vm.long_running_task.started.connect(
            lambda: self.progress.setVisible(True)
        )
        self.vm.long_running_task.finished.connect(
            lambda: self.progress.setVisible(False)
        )

        # Компоновка
        layout = QVBoxLayout()
        layout.addWidget(self.counter_label)
        layout.addWidget(self.status_label)
        layout.addWidget(self.progress)
        layout.addWidget(self.inc_button)
        layout.addWidget(self.dec_button)
        layout.addWidget(self.async_button)
        self.setLayout(layout)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    main = MainWindow()
    main.show()
    def except_hook(cls, exception, traceback):
        sys.__excepthook__(cls, exception, traceback)
    sys.excepthook = except_hook
    sys.exit(app.exec())
