#!/usr/bin/python3

import os
import subprocess
import sys

from PyQt5.QtCore import Qt, QObject, pyqtSignal, pyqtSlot, QThread
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QGridLayout, QMainWindow, QPushButton, QLineEdit, \
    QMessageBox, QFileDialog

version = '1.0'


class ThreadWorker(QObject):
    error_signal = pyqtSignal(str)
    start_signal = pyqtSignal()
    progress_signal = pyqtSignal(str)
    success_signal = pyqtSignal()
    finished = pyqtSignal()

    def __init__(self):
        super().__init__()

    def run(self):
        self.start_signal.emit()
        process = subprocess.Popen(
            self.command,
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            text=True,
            bufsize=1
        )

        # Чтение вывода в реальном времени
        while True:
            output = process.stdout.readline()
            if output == "" and process.poll() is not None:
                break
            if output:
                self.progress_signal.emit(output.strip())

        if process.returncode == 0:
            self.success_signal.emit()
        else:
            self.error_signal.emit(output if output else "Не удалось скачать видео.")


class MyWindow(QMainWindow):

    def alert(self, message=''):
        dlg = QMessageBox()
        dlg.setWindowTitle('Внимание!')
        dlg.setText(message)
        dlg.exec_()

    def download(self):
        spoofdpi_is_active = True if subprocess.run(
            'systemctl --user is-active spoofdpi', shell=True, capture_output=True
        ).stdout.decode().strip() == 'active' else False

        if subprocess.run(['systemctl', '--user', 'start', 'spoofdpi']).returncode != 0:
            dlg = QMessageBox()
            dlg.setWindowTitle('Внимание!')
            dlg.setText('Не удалось запустить сервис spoofdpi. Возможно, он не установлен. Установить?')
            dlg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
            if dlg.exec_() == QMessageBox.Ok:
                res = subprocess.run('pkexec dnf in -y spoofdpi', shell=True).returncode
                self.alert('spoofdpi успешно установлен, теперь можно запускать скачивание.' if res == 0 else 'Не удалось установить spoofdpi.')
            return
        url = self.input_field.text().strip()
        if 'youtu.be' in url and not '?' in url and not '&' in url:
            url = url.replace('youtu.be/', 'youtube.com/watch?v=').split('&')[0]
        elif 'youtube.com/watch?v=' in url:
            url = url.split('&')[0]

        os.chdir(self.address_button.text())
        self.thread = QThread()
        self.thread.setTerminationEnabled(True)
        self.worker = ThreadWorker()
        self.worker.command = ["yt-dlp", "--proxy", "http://localhost:8080", '-f', 'b', url]
        self.worker.moveToThread(self.thread)
        self.thread.started.connect(self.worker.run)
        self.worker.progress_signal.connect(self.logging)
        self.worker.finished.connect(self.worker.deleteLater)
        self.worker.finished.connect(self.thread.quit)
        if not spoofdpi_is_active:
            self.thread.finished.connect(self.turn_spoofdpi_off)
        self.thread.finished.connect(self.thread.deleteLater)
        self.worker.error_signal.connect(lambda message: self.alert(f'Возникла ошибка: {message}'))
        self.worker.success_signal.connect(lambda: self.alert('Успешно.'))
        self.thread.start()

    def turn_spoofdpi_off(self):
        subprocess.run('systemctl --user stop spoofdpi', shell=True)

    @pyqtSlot(str)
    def logging(self, string):
        self.status_label.setText(f'Статус: {string.strip()}')

    def select_address(self):
        res = QFileDialog.getExistingDirectory(self, "Выберите путь для сохранения", os.getcwd())
        if res:
            self.address_button.setText(res)

    def cancel_download(self):
        try:
            self.thread.terminate()
            self.worker.deleteLater()
            self.thread.deleteLater()
            self.status_label.setText('Статус: остановлено.')
        except Exception:
            self.status_label.setText('Скачивание не было запущено.')

    def __init__(self):
        QMainWindow.__init__(self)

        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        grid = QGridLayout()
        central_widget.setLayout(grid)

        self.textLabel = QLabel()
        self.textLabel.setText("Введите адрес видео...")
        grid.addWidget(self.textLabel, 0, 0, 1, 2)
        self.textLabel.setAlignment(Qt.AlignCenter)

        self.input_field = QLineEdit()
        grid.addWidget(self.input_field, 1, 0, 1, 2)

        grid.addWidget(QLabel('Сохранить в:'), 3, 0)
        self.address_button = QPushButton(os.getcwd())
        self.address_button.clicked.connect(self.select_address)
        grid.addWidget(self.address_button, 3, 1)

        download_button = QPushButton('Скачать')
        download_button.clicked.connect(self.download)
        grid.addWidget(download_button, 4, 0, 1, 2)

        cancel_button = QPushButton('Отмена')
        cancel_button.clicked.connect(self.cancel_download)
        grid.addWidget(cancel_button, 5, 0, 1, 2)

        self.status_label = QLabel('Статус: ')
        grid.addWidget(self.status_label, 6, 0, 1, 2)

        self.setFixedWidth(800)
        self.setWindowTitle(f"Video Downloader ver. {version}")
        self.setWindowIcon(QIcon(QIcon.fromTheme('go-bottom-symbolic')))
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MyWindow()
    sys.exit(app.exec_())
