# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4

###############################################################################
# OpenLP - Open Source Lyrics Projection                                      #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2014 Raoul Snyman                                        #
# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan      #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub,      #
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer.   #
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru,          #
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith,             #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock,              #
# Frode Woldsund, Martin Zibricky                                             #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it     #
# under the terms of the GNU General Public License as published by the Free  #
# Software Foundation; version 2 of the License.                              #
#                                                                             #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    #
# more details.                                                               #
#                                                                             #
# You should have received a copy of the GNU General Public License along     #
# with this program; if not, write to the Free Software Foundation, Inc., 59  #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
###############################################################################

import logging
import os

from PyQt4 import QtCore, QtGui

from openlp.core.lib import MediaManagerItem, build_icon, SettingsManager, \
    translate, check_item_selected, Receiver, ItemCapabilities, create_thumb, \
    validate_thumb
from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
    create_horizontal_adjusting_combo_box
from openlp.core.lib.settings import Settings
from openlp.core.utils import locale_compare
from openlp.plugins.presentations.lib import MessageListener

log = logging.getLogger(__name__)

ERROR = QtGui.QImage(u':/general/general_delete.png')


class PresentationMediaItem(MediaManagerItem):
    """
    This is the Presentation media manager item for Presentation Items.
    It can present files using Openoffice and Powerpoint
    """
    log.info(u'Presentations Media Item loaded')

    def __init__(self, parent, plugin, icon, controllers):
        """
        Constructor. Setup defaults
        """
        self.controllers = controllers
        self.IconPath = u'presentations/presentation'
        self.Automatic = u''
        MediaManagerItem.__init__(self, parent, plugin, icon)
        self.message_listener = MessageListener(self)
        self.hasSearch = True
        self.singleServiceItem = False
        QtCore.QObject.connect(Receiver.get_receiver(),
            QtCore.SIGNAL(u'mediaitem_presentation_rebuild'), self.rebuild)
        # Allow DnD from the desktop
        self.listView.activateDnD()

    def retranslateUi(self):
        """
        The name of the plugin media displayed in UI
        """
        self.onNewPrompt = translate('PresentationPlugin.MediaItem',
            'Select Presentation(s)')
        self.Automatic = translate('PresentationPlugin.MediaItem',
            'Automatic')
        self.displayTypeLabel.setText(
            translate('PresentationPlugin.MediaItem', 'Present using:'))

    def buildFileMaskString(self):
        """
        Build the list of file extensions to be used in the Open file dialog
        """
        fileType = u''
        for controller in self.controllers:
            if self.controllers[controller].enabled():
                types = self.controllers[controller].supports + \
                    self.controllers[controller].alsosupports
                for type_ in types:
                    if fileType.find(type_) == -1:
                        fileType += u'*.%s ' % type_
                        self.plugin.serviceManager.supportedSuffixes(type_)
        self.onNewFileMasks = unicode(translate('PresentationPlugin.MediaItem',
            'Presentations (%s)')) % fileType

    def requiredIcons(self):
        """
        Set which icons the media manager tab should show
        """
        MediaManagerItem.requiredIcons(self)
        self.hasFileIcon = True
        self.hasNewIcon = False
        self.hasEditIcon = False

    def addEndHeaderBar(self):
        """
        Display custom media manager items for presentations
        """
        self.presentationWidget = QtGui.QWidget(self)
        self.presentationWidget.setObjectName(u'presentationWidget')
        self.displayLayout = QtGui.QFormLayout(self.presentationWidget)
        self.displayLayout.setMargin(self.displayLayout.spacing())
        self.displayLayout.setObjectName(u'displayLayout')
        self.displayTypeLabel = QtGui.QLabel(self.presentationWidget)
        self.displayTypeLabel.setObjectName(u'displayTypeLabel')
        self.displayTypeComboBox = create_horizontal_adjusting_combo_box(
            self.presentationWidget, u'displayTypeComboBox')
        self.displayTypeLabel.setBuddy(self.displayTypeComboBox)
        self.displayLayout.addRow(self.displayTypeLabel,
            self.displayTypeComboBox)
        # Add the Presentation widget to the page layout
        self.pageLayout.addWidget(self.presentationWidget)

    def initialise(self):
        """
        Populate the media manager tab
        """
        self.listView.setIconSize(QtCore.QSize(88, 50))
        files = SettingsManager.load_list(
            self.settingsSection, u'presentations')
        self.loadList(files, True)
        self.populateDisplayTypes()

    def rebuild(self):
        """
        Rebuild the tab in the media manager when changes are made in
        the settings
        """
        self.populateDisplayTypes()
        self.buildFileMaskString()

    def populateDisplayTypes(self):
        """
        Load the combobox with the enabled presentation controllers,
        allowing user to select a specific app if settings allow
        """
        self.displayTypeComboBox.clear()
        for item in self.controllers:
            # load the drop down selection
            if self.controllers[item].enabled():
                self.displayTypeComboBox.addItem(item)
        if self.displayTypeComboBox.count() > 1:
            self.displayTypeComboBox.insertItem(0, self.Automatic, userData=u'automatic')
            self.displayTypeComboBox.setCurrentIndex(0)
        if Settings().value(self.settingsSection + u'/override app',
            QtCore.QVariant(QtCore.Qt.Unchecked)) == QtCore.Qt.Checked:
            self.presentationWidget.show()
        else:
            self.presentationWidget.hide()

    def loadList(self, files, initialLoad=False):
        """
        Add presentations into the media manager
        This is called both on initial load of the plugin to populate with
        existing files, and when the user adds new files via the media manager
        """
        currlist = self.getFileList()
        titles = [os.path.split(file)[1] for file in currlist]
        Receiver.send_message(u'cursor_busy')
        if not initialLoad:
            Receiver.send_message(u'cursor_busy')
            self.plugin.formParent.displayProgressBar(len(files))
        # Sort the presentations by its filename considering language specific
        # characters.
        files.sort(cmp=locale_compare,
            key=lambda filename: os.path.split(unicode(filename))[1])
        for file in files:
            if not initialLoad:
                self.plugin.formParent.incrementProgressBar()
            if currlist.count(file) > 0:
                continue
            filename = os.path.split(unicode(file))[1]
            if not os.path.exists(file):
                item_name = QtGui.QListWidgetItem(filename)
                item_name.setIcon(build_icon(ERROR))
                item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
                item_name.setToolTip(file)
                self.listView.addItem(item_name)
            else:
                if titles.count(filename) > 0:
                    if not initialLoad:
                        critical_error_message_box(
                            translate('PresentationPlugin.MediaItem',
                            'File Exists'),
                            translate('PresentationPlugin.MediaItem',
                            'A presentation with that filename already exists.')
                            )
                    continue
                controller_name = self.findControllerByType(filename)
                if controller_name:
                    controller = self.controllers[controller_name]
                    doc = controller.add_document(unicode(file))
                    thumb = os.path.join(doc.get_thumbnail_folder(),
                        u'icon.png')
                    preview = doc.get_thumbnail_path(1, True)
                    if not preview and not initialLoad:
                        doc.load_presentation()
                        preview = doc.get_thumbnail_path(1, True)
                    doc.close_presentation()
                    if not (preview and os.path.exists(preview)):
                        icon = build_icon(u':/general/general_delete.png')
                    else:
                        if validate_thumb(preview, thumb):
                            icon = build_icon(thumb)
                        else:
                            icon = create_thumb(preview, thumb)
                else:
                    if initialLoad:
                        icon = build_icon(u':/general/general_delete.png')
                    else:
                        critical_error_message_box(UiStrings().UnsupportedFile,
                            translate('PresentationPlugin.MediaItem',
                            'This type of presentation is not supported.'))
                        continue
                item_name = QtGui.QListWidgetItem(filename)
                item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
                item_name.setIcon(icon)
                item_name.setToolTip(file)
                self.listView.addItem(item_name)
        Receiver.send_message(u'cursor_normal')
        if not initialLoad:
            self.plugin.formParent.finishedProgressBar()
            Receiver.send_message(u'cursor_normal')

    def onDeleteClick(self):
        """
        Remove a presentation item from the list
        """
        if check_item_selected(self.listView, UiStrings().SelectDelete):
            items = self.listView.selectedIndexes()
            row_list = [item.row() for item in items]
            row_list.sort(reverse=True)
            Receiver.send_message(u'cursor_busy')
            self.plugin.formParent.displayProgressBar(len(row_list))
            for item in items:
                filepath = unicode(item.data(
                    QtCore.Qt.UserRole).toString())
                for cidx in self.controllers:
                    doc = self.controllers[cidx].add_document(filepath)
                    doc.presentation_deleted()
                    doc.close_presentation()
                self.plugin.formParent.incrementProgressBar()
            self.plugin.formParent.finishedProgressBar()
            Receiver.send_message(u'cursor_normal')
            for row in row_list:
                self.listView.takeItem(row)
            SettingsManager.set_list(self.settingsSection,
                u'presentations', self.getFileList())

    def generateSlideData(self, service_item, item=None, xmlVersion=False,
        remote=False):
        """
        Load the relevant information for displaying the presentation
        in the slidecontroller. In the case of powerpoints, an image
        for each slide
        """
        if item:
            items = [item]
        else:
            items = self.listView.selectedItems()
            if len(items) > 1:
                return False
        service_item.title = unicode(self.displayTypeComboBox.currentText())
        service_item.shortname = unicode(self.displayTypeComboBox.currentText())
        service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay)
        service_item.add_capability(ItemCapabilities.HasDetailedTitleDisplay)
        if not service_item.shortname:
            return False
        for bitem in items:
            filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
            if os.path.exists(filename):
                if self.displayTypeComboBox.itemData(
                    self.displayTypeComboBox.currentIndex()) == u'automatic':
                    service_item.shortname = self.findControllerByType(filename)
                    if not service_item.shortname:
                        return False
                controller = self.controllers[service_item.shortname]
                (path, name) = os.path.split(filename)
                doc = controller.add_document(filename)
                if doc.get_thumbnail_path(1, True) is None:
                    doc.load_presentation()
                i = 1
                img = doc.get_thumbnail_path(i, True)
                if img:
                    while img:
                        service_item.add_from_command(path, name, img)
                        i = i + 1
                        img = doc.get_thumbnail_path(i, True)
                    doc.close_presentation()
                    return True
                else:
                    # File is no longer present
                    if not remote:
                        critical_error_message_box(
                            translate('PresentationPlugin.MediaItem',
                            'Missing Presentation'),
                            unicode(translate(
                            'PresentationPlugin.MediaItem',
                            'The presentation %s is incomplete,'
                            ' please reload.')) % filename)
                    return False
            else:
                # File is no longer present
                if not remote:
                    critical_error_message_box(
                        translate('PresentationPlugin.MediaItem',
                        'Missing Presentation'),
                        unicode(translate('PresentationPlugin.MediaItem',
                        'The presentation %s no longer exists.')) % filename)
                return False

    def findControllerByType(self, filename):
        """
        Determine the default application controller to use for the selected
        file type. This is used if "Automatic" is set as the preferred
        controller. Find the first (alphabetic) enabled controller which
        "supports" the extension. If none found, then look for a controller
        which "also supports" it instead.
        """
        filetype = os.path.splitext(filename)[1][1:]
        if not filetype:
            return None
        for controller in self.controllers:
            if self.controllers[controller].enabled():
                if filetype in self.controllers[controller].supports:
                    return controller
        for controller in self.controllers:
            if self.controllers[controller].enabled():
                if filetype in self.controllers[controller].alsosupports:
                    return controller
        return None

    def search(self, string, showError):
        files = SettingsManager.load_list(
            self.settingsSection, u'presentations')
        results = []
        string = string.lower()
        for file in files:
            filename = os.path.split(unicode(file))[1]
            if filename.lower().find(string) > -1:
                results.append([file, filename])
        return results
