#!/usr/bin/env python

import os
import sys
from PyQt4 import QtCore, QtGui
from ui.main_window import Ui_MainWindow
from ui.download_item import Ui_DownloadItem
from youtube_dl import YoutubeDL



class QYoutubeDL(QtCore.QThread):
    """
    Wraps YoutubeDL in a QThread.
    Emits progressChanged signal on progress_hook calls.
    """
    progressChanged = QtCore.pyqtSignal(dict)

    def __init__(self, parent=None, ydl=None):
        QtCore.QThread.__init__(self, parent)
        self.urls = []
        self.ydl = ydl
        self.ydl.add_progress_hook(self.progress_hook)

    def progress_hook(self, pr):
        """
        * filename: The final filename
        * status: One of "downloading" and "finished"

        It can also have some of the following entries:

        * downloaded_bytes: Bytes on disks
        * total_bytes: Total bytes, None if unknown
        * tmpfilename: The filename we're currently writing to
        * eta: The estimated time in seconds, None if unknown
        * speed: The download speed in bytes/second, None if unknown
        """
        self.progressChanged.emit(pr)

    def run(self):
        self.ydl.download(self.urls)


class DownloadItem(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.ui = Ui_DownloadItem()
        self.ui.setupUi(self)

    def onProgressChanged(self, pr):
        print "pr:", pr
        downloaded_bytes = pr['downloaded_bytes']
        total_bytes = pr['total_bytes']
        percentage = 50
        if total_bytes:
            percentage = 100 * downloaded_bytes / total_bytes
        self.ui.progressBar.setValue(percentage)


class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.custom_setup_ui()
        self.connect_signals()

    def connect_signals(self):
        """
        Connects signals that are not implicitly defined.
        """
        self.ui.browsePushButton.clicked.connect(self.selectFile)

    def custom_setup_ui(self):
        self.readSettings()

    def writeSettings(self):
        """
        Saves the user preferred output directory value.
        """
        settings = QtCore.QSettings()
        output_directory = self.ui.outputDirLineEdit.text()
        settings.setValue("output_directory", output_directory)

    def readSettings(self):
        """
        Restores the last output directory value.
        """
        settings = QtCore.QSettings()
        # defaults to the current directory path
        current_dir_abspath = os.path.abspath('')
        defaultValue = QtCore.QString(current_dir_abspath)
        # Warning:
        # QSettings.value can return different types (QVariant types) depending on the platform it's running on,
        # so the safest way to use it is always casting the result to the desired type, e.g.: int(settings.value("myKey")).
        output_directory = settings.value("output_directory", defaultValue=defaultValue).toString()
        self.ui.outputDirLineEdit.setText(output_directory)

    def closeEvent(self, event):
        self.writeSettings()
        event.accept()

    # http://stackoverflow.com/questions/14311578/event-signal-is-emmitted-twice-every-time
    @QtCore.pyqtSlot()
    def on_downloadPushButton_clicked(self):
        url = str(self.ui.urlLineEdit.text())
        directory = str(self.ui.outputDirLineEdit.text())
        item, download_item = self.add_download_item(url)
        self.start_download(url, directory, download_item.onProgressChanged)

    def add_download_item(self, url):
        """
        Adds custom progress bar widget to the downloadListWidget.
        """
        download_item = DownloadItem()
        download_item.ui.urlLabel.setText(url)
        item = QtGui.QListWidgetItem()
        self.ui.downloadListWidget.addItem(item)
        self.ui.downloadListWidget.setItemWidget(item, download_item)
        item.setSizeHint(
            QtCore.QSize(self.ui.downloadListWidget.sizeHint().width(), 80))
        return (item, download_item)


    def start_download(self, url, directory, onProgressChanged):
        """
        Starts the QYoutubeDL thread and hooks progress bar.
        """
        if directory:
            directory = os.path.abspath(directory) + '/'
        ydl_options = {
            'outtmpl': directory + u'%(title)s-%(id)s.%(ext)s',
        }
        with YoutubeDL(ydl_options) as ydl:
            qydl = QYoutubeDL(ydl=ydl)
            ydl.add_default_info_extractors()
            # ydl.add_progress_hook(progress_hook)
            # ydl.download([url])
            # TODO: keep the qydl instance until the thread finishes
            qydl.urls = [url]
            qydl.progressChanged.connect(onProgressChanged)
            qydl.start()

    def selectFile(self):
        self.ui.outputDirLineEdit.setText(QtGui.QFileDialog.getExistingDirectory())


if __name__ == "__main__":
    QtCore.QCoreApplication.setOrganizationName("youtube-dl-qt")
    QtCore.QCoreApplication.setApplicationName("youtube-dl-qt")
    app = QtGui.QApplication(sys.argv)
    myapp = MainWindow()
    myapp.show()
    sys.exit(app.exec_())
