import logging
from threading import Thread
from typing import List

from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon, QPixmap, QCursor
from PyQt5.QtWidgets import QDialog, QLabel, QPushButton, QToolBar, QVBoxLayout, QProgressBar, QApplication

from bauh.api.abstract.cache import MemoryCache
from bauh.api.http import HttpClient
from bauh.view.qt import qt_utils, styles
from bauh.view.qt.components import new_spacer
from bauh.view.qt.thread import AnimateProgress
from bauh.view.qt.view_model import PackageView
from bauh.view.util.translation import I18n


class ScreenshotsDialog(QDialog):

    MAX_HEIGHT = 600
    MAX_WIDTH = 800

    def __init__(self, pkg: PackageView, http_client: HttpClient, icon_cache: MemoryCache, i18n: I18n, screenshots: List[QPixmap], logger: logging.Logger):
        super(ScreenshotsDialog, self).__init__()
        self.setWindowTitle(str(pkg))
        self.screenshots = screenshots
        self.logger = logger
        self.loaded_imgs = []
        self.download_threads = []
        self.resize(1280, 720)
        self.i18n = i18n
        self.http_client = http_client
        self.progress_bar = QProgressBar()
        self.progress_bar.setCursor(QCursor(Qt.WaitCursor))
        self.progress_bar.setStyleSheet(styles.PROGRESS_BAR)
        self.progress_bar.setMaximumHeight(10 if QApplication.instance().style().objectName().lower() == 'windows' else 6)
        self.progress_bar.setTextVisible(False)
        self.thread_progress = AnimateProgress()
        self.thread_progress.signal_change.connect(self._update_progress)
        self.thread_progress.start()

        # THERE ARE CRASHES WITH SOME RARE ICONS ( like insomnia ). IT CAN BE A QT BUG. IN THE MEANTIME, ONLY THE TYPE ICON WILL BE RENDERED
        #
        # icon_data = icon_cache.get(pkg.model.icon_url)
        #
        # if icon_data and icon_data.get('icon'):
        #     self.setWindowIcon(icon_data.get('icon'))
        # else:
        #     self.setWindowIcon(QIcon(pkg.model.get_type_icon_path()))
        self.setWindowIcon(QIcon(pkg.model.get_type_icon_path()))
        self.setLayout(QVBoxLayout())

        self.img = QLabel()
        self.layout().addWidget(self.img)

        self.bottom_bar = QToolBar()

        self.bt_back = QPushButton(' < ' + self.i18n['screenshots.bt_back.label'].capitalize())
        self.bt_back.setCursor(QCursor(Qt.PointingHandCursor))
        self.bt_back.clicked.connect(self.back)
        self.ref_bt_back = self.bottom_bar.addWidget(self.bt_back)
        self.bottom_bar.addWidget(new_spacer(50))

        self.img_label = QLabel()
        self.img_label.setCursor(QCursor(Qt.WaitCursor))
        self.img_label.setStyleSheet('QLabel { font-weight: bold; text-align: center }')
        self.ref_img_label = self.bottom_bar.addWidget(self.img_label)
        self.ref_img_label.setVisible(False)
        self.ref_progress_bar = self.bottom_bar.addWidget(self.progress_bar)
        self.bottom_bar.addWidget(new_spacer(50))

        self.bt_next = QPushButton(self.i18n['screenshots.bt_next.label'].capitalize() + ' > ')
        self.bt_next.setCursor(QCursor(Qt.PointingHandCursor))
        self.bt_next.clicked.connect(self.next)
        self.ref_bt_next = self.bottom_bar.addWidget(self.bt_next)

        self.layout().addWidget(self.bottom_bar)

        self.img_idx = 0

        for idx, s in enumerate(self.screenshots):
            t = Thread(target=self._download_img, args=(idx, s), daemon=True)
            t.start()

        self._load_img()

    def _update_progress(self, val: int):
        self.progress_bar.setValue(val)

    def _load_img(self):
        if len(self.loaded_imgs) > self.img_idx:
            img = self.loaded_imgs[self.img_idx]

            if isinstance(img, QPixmap):
                self.img_label.setText('')
                self.img.setPixmap(img)
            else:
                self.img_label.setText(img)
                self.img.setPixmap(QPixmap())

            self.img.unsetCursor()
            self.thread_progress.stop = True
            self.ref_progress_bar.setVisible(False)
            self.ref_img_label.setVisible(True)
        else:
            self.img.setPixmap(QPixmap())
            self.img.setCursor(QCursor(Qt.WaitCursor))
            self.ref_img_label.setVisible(False)
            self.ref_progress_bar.setVisible(True)
            self.thread_progress.start()

        if len(self.screenshots) == 1:
            self.ref_bt_back.setVisible(False)
            self.ref_bt_next.setVisible(False)
        else:
            self.ref_bt_back.setEnabled(self.img_idx != 0)
            self.ref_bt_next.setEnabled(self.img_idx != len(self.screenshots) - 1)

        self.adjustSize()
        qt_utils.centralize(self)

    def _download_img(self, idx: int, url: str):
        self.logger.info('Downloading image [{}] from {}'.format(idx, url))
        res = self.http_client.get(url)

        if res:
            if not res.content:
                self.logger.warning('Image [{}] from {} has no content'.format(idx, url))
                self.loaded_imgs.append(self.i18n['screenshots.download.no_content'])
                self._load_img()
            else:
                self.logger.info('Image [{}] successfully downloaded'.format(idx))
                pixmap = QPixmap()
                pixmap.loadFromData(res.content)

                if pixmap.size().height() > self.MAX_HEIGHT or pixmap.size().width() > self.MAX_WIDTH:
                    pixmap = pixmap.scaled(self.MAX_WIDTH, self.MAX_HEIGHT, Qt.KeepAspectRatio, Qt.SmoothTransformation)

                self.loaded_imgs.append(pixmap)

                if self.img_idx == idx:
                    self._load_img()
        else:
            self.logger.info("Could not retrieve image [{}] from {}".format(idx, url))
            self.loaded_imgs.append(self.i18n['screenshots.download.no_response'])
            self._load_img()

    def back(self):
        self.img_idx -= 1
        self._load_img()

    def next(self):
        self.img_idx += 1
        self._load_img()


