# -*- coding: utf-8 -*-
#
# Copyright 2016 Continuum Analytics, Inc.
# May be copied and distributed freely only as part of an Anaconda or
# Miniconda installation.
#

"""
Widgets to list videos available to launch on the learning tab.
"""

# Standard library imports
from __future__ import absolute_import, division
import sys
import random

# Third party imports
from qtpy.QtCore import Qt, Signal, QPoint, QSize, QTimer, QUrl
from qtpy.QtGui import QPixmap, QDesktopServices
from qtpy.QtWidgets import (QAbstractItemView, QHBoxLayout, QListWidget,
                            QListWidgetItem, QVBoxLayout, QApplication)

# Local imports
from anaconda_navigator.widgets.dialogs import DialogBase
from anaconda_navigator.images import VIDEO_ICON_PATH
from anaconda_navigator.widgets import (WidgetBase, ButtonBase,
                                        QLabel, LabelLinks)
from anaconda_navigator.utils.analytics import GATracker
from anaconda_navigator.utils.logs import logger
from anaconda_navigator.utils.styles import load_style_sheet


# --- Widgets used in styling
# -----------------------------------------------------------------------------
class WidgetContent(WidgetBase):
    pass


class LabelContentIcon(QLabel):
    pass


class LabelContentText(LabelLinks):
    pass


class ButtonContentInformation(ButtonBase):
    pass


class ButtonContent(ButtonBase):
    pass


def wrapText(string, max_lines=1):
    """
    Return a string broken into number of max_lines.
    Truncate the title and add an ellipsis ("...") if max_lines have been
    reached, or there are no whitespaces to break on.
    """
    #TODO: Get width in pixels from actual measurement of widget.
    # the widget_width below was set arbitrarily.
    # widget_width = self.button_view.width()
    widget_width = 100

    stacked_lines = []
    string_length = len(string)
    string_buffer = ''

    # returns the broken lines with /n's as a single string
    def formatted_lines():
        formatted_string = ''
        if len(stacked_lines) > 0:
            for index, line in enumerate(stacked_lines):
                if index == len(stacked_lines)-1:
                    formatted_string += line
                else:
                    formatted_string += line + '\n'
        return formatted_string

    for index, char in enumerate(string):
        label = QLabel(string_buffer)
        fontmetrics = label.fontMetrics()
        real_width_in_pixels = fontmetrics.width(label.text())

        # if it's the last line and it fits the width
        if (index == (string_length - 1)) and (real_width_in_pixels <= widget_width):
            string_buffer += char
            stacked_lines.append(string_buffer)
            return formatted_lines()

        # otherwise, check length of string against width tolerance
        if real_width_in_pixels > widget_width:

            # if it's the last allowable line, add ellipsis and return
            if (len(stacked_lines) + 1) == max_lines:
                truncated_string = string_buffer[:-3] + '...'
                stacked_lines.append(truncated_string)
                return formatted_lines()

            # otherwise, check for a previous whitespace on which to break
            else:
                string_buffer += char
                pos = string_buffer.rfind(' ')
                # if there is no whitespace, set an ellipsis and return
                if pos <= 0:
                    truncated_string = string_buffer[:-3] + '...'
                    stacked_lines.append(truncated_string)
                    return formatted_lines()

                # otherwise, break on the whitespace and reset to last index
                # position
                else:
                    truncated_string = string_buffer[:pos]
                    stacked_lines.append(truncated_string)
                    string_buffer = string_buffer[(pos + 1):]                
        else:
            string_buffer += char

    return formatted_lines()


# --- Main widgets
# -----------------------------------------------------------------------------
class ListWidgetContent(QListWidget):
    """
    List Widget holding available videos in the learning tab.
    """
    sig_view_video = Signal(str, str)

    def __init__(self, *args, **kwargs):
        self._main = kwargs.pop('main', None)
        super(ListWidgetContent, self).__init__(*args, **kwargs)

        self.tracker = GATracker()
        self._items = []
        self.setObjectName('VideoListWidget')
        self.setResizeMode(QListWidget.Adjust)
        self.setMovement(QListWidget.Static)
        self.setFrameStyle(QListWidget.Plain)
        self.setSelectionMode(QAbstractItemView.NoSelection)
        self.setViewMode(QListWidget.IconMode)
        self.setFocusPolicy(Qt.NoFocus)
        self.setUniformItemSizes(True)

    def addItem(self, item):
        """
        Add a content item to the list.
        """
        super(ListWidgetContent, self).addItem(item)
        self._items.append(item)
        self.setItemWidget(item, item.widget)
        uri = item.uri
        title = item.title
        item.button_view.clicked.connect(lambda: self.launch(uri, title))

    def launch(self, uri, title):
        """
        Emit signal with youtube video identifier string.
        """
        qurl = QUrl(uri)
        QDesktopServices.openUrl(qurl)
        self.tracker.track_event('content', 'click', uri)
        self.sig_view_video.emit(uri, title)

    def update_style_sheet(self, style_sheet=None):
        """
        """
        if style_sheet is None:
            style_sheet = load_style_sheet()

        for item in self._items:
            try:
                item_widget = self.itemWidget(item)
                item_widget.setStyleSheet(style_sheet)
                item.setSizeHint(item_widget.sizeHint())
            except Exception:
                # This error is just in case the C++ object has been
                # deleted and it is not crucial to log.
                pass
        self.update()
        self.repaint()


class LabelContentInformation(DialogBase):
    def __init__(self, text):
        DialogBase.__init__(self)

        # Widgets
        self.label = LabelLinks(text)

        # Widget setup
        self.label.setWordWrap(True)
        self.label.setTextFormat(Qt.RichText)
        self.label.setTextInteractionFlags(Qt.TextBrowserInteraction)
        self.label.setOpenExternalLinks(True)
        self.label.setFocus()
        self.label.focusOutEvent = self.focusOutEvent
        self.frame_title_bar.setVisible(False)
        self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint)

        # Layout
        layout = QHBoxLayout(self)
        layout.addWidget(self.label)
        self.setLayout(layout)

    def focusOutEvent(self, *args):
        self.close()


class ListItemContent(QListWidgetItem):
    """
    Widget to build an item for the content listing.
    """
    def __init__(self, title='', description='', uri='',
                 authors=[], venue='', path='', year='',
                 summary='', banner='', tags='', subtitle='', date='',
                 pixmap=None):
        super(ListItemContent, self).__init__()

        self.title = title
        self.uri = uri
        self.authors = authors
        self.venue = venue
        self.banner = banner
        self.year = year
        self.path = path
        self.tags = tags
        self.subtitle = subtitle
        self.date = date
        self.summary = summary
        self.timer_pixmap = QTimer()
        self.pixmaps = {}
        self.pixmap = pixmap
        self.label = None

        # Widgets
        self.widget = WidgetContent()
        self.button_information = ButtonContentInformation('more...',
                                                           parent=self.widget)
        self.button_view = ButtonContent(parent=self.widget)
        self.label_icon = LabelContentIcon(parent=self.widget)
        self.label_text = LabelContentText(summary, parent=self.widget)

        # Widget setup
        valid_tags = ['documentation', 'webinar', 'event', 'video', 'training',
                      'forum', 'social']
        tag = 'notag'
        if len(tags) >= 1:
            filter_tags = [t.lower() for t in tags if t.lower() in valid_tags]
            if filter_tags:
                tag = filter_tags[0].lower()

        self.button_view.setObjectName(tag)
        self.button_view.setText((wrapText(title, 3)))
        self.button_information.setObjectName(tag)
        self.label_icon.setAlignment(Qt.AlignCenter)
        self.label_text.setAlignment(Qt.AlignCenter)
        self.label_text.setWordWrap(True)
        self.timer_pixmap.setInterval(random.randint(950, 1050))
        if pixmap:
            self.label_icon.setPixmap(QPixmap(VIDEO_ICON_PATH).scaled(
                100, 60, Qt.KeepAspectRatio, Qt.FastTransformation)
                )

        # Layout
        if title and uri:
            self.widget_layout = QVBoxLayout(self.widget)
            self.widget_layout.addWidget(self.label_icon, 0, Qt.AlignCenter)
            self.widget_layout.addWidget(self.button_view, 0, Qt.AlignCenter)
            self.widget_layout.addWidget(self.label_text, 0, Qt.AlignCenter)
            self.widget_layout.addWidget(self.button_information, 0,
                                         Qt.AlignRight)
            self.setSizeHint(QSize(180, 190))
#            self.setSizeHint(QSize(180, 250))
            self.widget.setLayout(self.widget_layout)
        if summary:
            tt = ('<p><b>'+title+'</b></p><p>'+subtitle+'</p>'
                  '<p>'+date+'</p>'+'<div>'+summary+'</div>')
            self.label = LabelContentInformation(tt)

        if not self.label:
            self.button_information.setDisabled(True)

        # Signals
        self.button_information.clicked.connect(self.show_information)
        self.timer_pixmap.timeout.connect(self.update_thumbnail)

        # Setup
        self.timer_pixmap.start()

    def show_information(self):
        if self.label:
            self.label.move(-1000, 0)
            self.label.show()
            app = QApplication.instance()
            geo = app.desktop().screenGeometry(self.button_information)
            w, h = geo.right(), geo.bottom()
            pos = self.button_information.mapToGlobal(QPoint(0, 0))
            x, y = pos.x()+10, pos.y()+10
            x = min(x, w - self.label.width())
            y = min(y, h - self.label.height())
            self.label.move(x, y)

    def update_thumbnail(self, pixmap=None):
        """
        Update thumbnails image.
        """
        pixmap = self.pixmaps.get(self.path, None)
        if pixmap and not pixmap.isNull():
            self.pixmap = pixmap
            self.label_icon.setPixmap(self.pixmap.scaled(
                100, 60, Qt.KeepAspectRatio, Qt.SmoothTransformation)
                )
            self.timer_pixmap.stop()


def test():
    from anaconda_navigator.utils.qthelpers import qapplication
    from anaconda_navigator.utils.py3compat import to_text_string
    app = qapplication(test_time=3)
    l = ListWidgetContent()
    for i in range(1000):
        w = ListItemContent(
            title='Querying 1.7 Billion Reddit Comments with Anaconda '
                  'Platform Tools on Hadoop.',
            description="",
            uri='aC7dzF1vY7A' + to_text_string(i),
            )
        l.addItem(w)
    l.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    test()
