"""library_main_dialog.py - The library dialog window."""

import os
from gi.repository import Gdk, Gtk

from mcomix.preferences import prefs
from mcomix import i18n
from mcomix import tools
from mcomix import log
from mcomix import file_chooser_library_dialog
from mcomix import status
from mcomix.library import backend as library_backend
from mcomix.library import book_area as library_book_area
from mcomix.library import collection_area as library_collection_area
from mcomix.library import control_area as library_control_area
from mcomix.library import add_progress_dialog as library_add_progress_dialog

_dialog = None
# The "All books" collection is not a real collection stored in the library,
# but is represented by this ID in the library's TreeModels.
_COLLECTION_ALL = -1

class _LibraryDialog(Gtk.Window):

    """The library window. Automatically creates and uses a new
    library_backend.LibraryBackend when opened.
    """

    def __init__(self, window, file_handler):
        super(_LibraryDialog, self).__init__(Gtk.WindowType.TOPLEVEL)

        self._window = window

        self.resize(prefs['lib window width'], prefs['lib window height'])
        self.set_title(_('Library'))
        self.connect('delete_event', self.close)
        self.connect('key-press-event', self._key_press_event)

        self.filter_string = None
        self._file_handler = file_handler
        self._statusbar = Gtk.Statusbar()
        self.backend = library_backend.LibraryBackend()
        self.book_area = library_book_area._BookArea(self)
        self.control_area = library_control_area._ControlArea(self)
        self.collection_area = library_collection_area._CollectionArea(self)

        self.backend.watchlist.new_files_found += self._new_files_found

        table = Gtk.Table(2, 2, False)
        table.attach(self.collection_area, 0, 1, 0, 1, Gtk.AttachOptions.FILL,
            Gtk.AttachOptions.EXPAND|Gtk.AttachOptions.FILL)
        table.attach(self.book_area, 1, 2, 0, 1, Gtk.AttachOptions.EXPAND|Gtk.AttachOptions.FILL,
            Gtk.AttachOptions.EXPAND|Gtk.AttachOptions.FILL)
        table.attach(self.control_area, 0, 2, 1, 2, Gtk.AttachOptions.EXPAND|Gtk.AttachOptions.FILL,
            Gtk.AttachOptions.FILL)

        if prefs['show statusbar']:
            table.attach(self._statusbar, 0, 2, 2, 3, Gtk.AttachOptions.FILL, Gtk.AttachOptions.FILL)

        self.add(table)
        self.show_all()
        self.present()

    def open_book(self, books, keep_library_open=False):
        """Open the book with ID <book>."""

        paths = [ self.backend.get_book_path(book) for book in books ]

        if not keep_library_open:
            self.hide()

        self._window.present()

        if len(paths) > 1:
            self._file_handler.open_file(paths)
        elif len(paths) == 1:
            self._file_handler.open_file(paths[0])

    def scan_for_new_files(self):
        """ Start scanning for new files from the watch list. """

        if len(self.backend.watchlist.get_watchlist()) > 0:
            self.set_status_message(_("Scanning for new books..."))
            self.backend.watchlist.scan_for_new_files()

    def _new_files_found(self, filelist, watchentry):
        """ Called after the scan for new files finished. """

        if len(filelist) > 0:
            if watchentry.collection.id is not None:
                collection_name = watchentry.collection.name
            else:
                collection_name = None

            self.add_books(filelist, collection_name)

            if len(filelist) == 1:
                message = _("Added new book '%(bookname)s' "
                    "from directory '%(directory)s'.")
            else:
                message = _("Added %(count)d new books "
                    "from directory '%(directory)s'.")

            self.set_status_message(message % {'directory': watchentry.directory,
                'count': len(filelist), 'bookname': os.path.basename(filelist[0])})
        else:
            self.set_status_message(
                _("No new books found in directory '%s'.") % watchentry.directory)

    def get_status_bar(self):
        """ Returns the window's status bar. """
        return self._statusbar

    def set_status_message(self, message):
        """Set a specific message on the statusbar, replacing whatever was
        there earlier.
        """
        self._statusbar.pop(0)
        self._statusbar.push(0,
            ' ' * status.Statusbar.SPACING + '%s' % i18n.to_unicode(message))

    def close(self, *args):
        """Close the library and do required cleanup tasks."""
        prefs['lib window width'], prefs['lib window height'] = self.get_size()
        self.backend.watchlist.new_files_found -= self._new_files_found
        self.book_area.stop_update()
        self.book_area.close()
        file_chooser_library_dialog.close_library_filechooser_dialog()
        _close_dialog()

    def add_books(self, paths, collection_name=None):
        """Add the books at <paths> to the library. If <collection_name>
        is not None, it is the name of a (new or existing) collection the
        books should be put in.
        """
        if collection_name is None:
            collection_id = self.collection_area.get_current_collection()
        else:
            collection = self.backend.get_collection_by_name(collection_name)

            if collection is None: # Collection by that name doesn't exist.
                self.backend.add_collection(collection_name)
                collection = self.backend.get_collection_by_name(
                    collection_name)

            collection_id = collection.id

        library_add_progress_dialog._AddLibraryProgressDialog(self, self._window, paths, collection_id)

        if collection_id is not None:
            prefs['last library collection'] = collection_id

    def _key_press_event(self, widget, event, *args):
        """ Handle key press events for closing the library on Escape press. """

        if event.keyval == Gdk.KEY_Escape:
            self.hide()


def open_dialog(action, window):
    """ Shows the library window. If sqlite is not available, this method
    does nothing and returns False. Otherwise, True is returned. """
    global _dialog

    if _dialog is None:

        if library_backend.dbapi2 is None:
            text = _('! You need an sqlite wrapper to use the library.')
            window.osd.show(text)
            log.error(text)
            return False

        else:
            _dialog = _LibraryDialog(window, window.filehandler)

    else:
        _dialog.present()

    if prefs['scan for new books on library startup']:
        _dialog.scan_for_new_files()

    return True


def _close_dialog(*args):
    global _dialog

    if _dialog is not None:
        _dialog.destroy()
        _dialog = None
        tools.garbage_collect()

# vim: expandtab:sw=4:ts=4
