# -*- coding: UTF-8 -*-

__revision__ = '$Id$'

# Copyright (c) 2005-2011 Vasco Nunes, Piotr Ożarowski

# 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; either version 2 of the License, or
# (at your option) any later version.
#
# 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 Library 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
# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA

# You may use and distribute this software under the terms of the
# GNU General Public License, version 2 or later

import logging
import os
from gi.repository import Gtk
from gi.repository import GdkPixbuf
from sqlalchemy.sql.expression import Select
import db
import gutils
import sql
from gettext import gettext as _

log = logging.getLogger("Griffith")


def on_tree_selection(tree_selection, self):
    counts = tree_selection.count_selected_rows()
    treeview_selection_on_event(self, self.widgets['treeview'])
    treemodel, selected = tree_selection.get_selected_rows()
    self.selected_iter = [treemodel.get_iter(path) for path in selected]

    if counts == 1:
        # TODO: rewrite me
        self.widgets['menu']['clone'].set_sensitive(True)
        self.widgets['menu']['make_cover'].set_sensitive(True)
        self.widgets['menu']['loan'].set_sensitive(True)
        self.widgets['menu']['edit'].set_sensitive(True)
        self.widgets['popups']['edit'].set_sensitive(True)
        self.widgets['popups']['loan'].set_sensitive(True)
        self.widgets['popups']['clone'].set_sensitive(True)
        self.widgets['popups']['print_cover'].set_sensitive(True)
    else:
        set_details(self)
        # lets make some options unavailable when multi selection is active.
        # for now.
        # TODO: rewrite me
        self.widgets['menu']['clone'].set_sensitive(False)
        self.widgets['menu']['make_cover'].set_sensitive(False)
        self.widgets['menu']['loan'].set_sensitive(False)
        self.widgets['menu']['edit'].set_sensitive(False)
        self.widgets['popups']['edit'].set_sensitive(False)
        self.widgets['popups']['loan'].set_sensitive(False)
        self.widgets['popups']['clone'].set_sensitive(False)
        self.widgets['popups']['print_cover'].set_sensitive(False)
    treeview_clicked(self)


def foreach_treeview_selected(model, _path, iter_obj, selected):
    selected.append(model.get_value(iter_obj, 0))


def treeview_selection_on_event(self, treeview, _iter=False):
    self.selected = []
    treeview.get_selection().selected_foreach(
        foreach_treeview_selected, self.selected)
    # return selected


def treeview_clicked(self):
    if self.initialized is False:
        return False
    if len(self.selected) == 1:
        movie = self.db.session.query(db.Movie).filter_by(
            number=int(self.selected[0])).first()
        if self.widgets['poster_window'].props.visible:
            # poster window is visible
            filename = None
            if movie.poster_md5:
                filename = gutils.get_image_fname(movie.poster_md5, self.db)
            if not filename:
                filename = gutils.get_defaultimage_fname(self)
            self.widgets['big_poster'].set_from_file(filename)
        # for ext in self.extensions:
        #     ext.maintree_clicked(treeselection, movie)
        set_details(self, movie)
    else:
        return False


def set_details(self, item=None):  # {{{
    if item is None:
        item = {}
    if 'movie_id' in item and item['movie_id']:
        self._movie_id = item['movie_id']
    else:
        self._movie_id = None
    w = self.widgets['movie']

    if 'number' in item and item['number']:
        w['number'].set_text(str(int(item['number'])))
    else:
        w['number'].set_text('')
    if 'title' in item and item['title']:
        title_enc = gutils.html_encode(item['title'])
        w['title'].set_markup(f"<b><span size='large'>{title_enc}</span></b>")
    else:
        w['title'].set_text('')
    if 'o_title' in item and item['o_title']:
        o_title_enc = gutils.html_encode(item['o_title'])
        w['o_title'].set_markup(
            f"<span size='medium'><i>{o_title_enc}</i></span>")
    else:
        w['o_title'].set_text('')
    if 'director' in item and item['director']:
        director_enc = gutils.html_encode(item['director'])
        w['director'].set_markup(f"<i>{director_enc}</i>")
    else:
        w['director'].set_text('')
    if 'plot' in item and item['plot']:
        w['plot'].set_text(str(item['plot']))
    else:
        w['plot'].set_text('')
    if 'year' in item and item['year']:
        w['year'].set_text(str(item['year']))
    else:
        w['year'].set_text('')
    if 'resolution' in item and item['resolution']:
        if self.config.get('use_resolution_alias', True):
            w['resolution'].set_text(item['resolution'])
        elif ('height' in item and item['height'] and 'width' in item
              and item['width']):
            w['resolution'].set_text("%dx%d" % (item['width'], item['height']))
        else:  # fallback to 'resolution'
            w['resolution'].set_text(item['resolution'])
    else:
        w['resolution'].set_text('')
        pass
    if 'runtime' in item and item['runtime']:
        w['runtime'].set_text(str(int(item['runtime'])))
    else:
        w['runtime'].set_text('x')
    if 'cameraman' in item and item['cameraman']:
        w['cameraman'].set_markup("<i>%s</i>" % gutils.html_encode(item['cameraman']))
    else:
        w['cameraman'].set_text('')
    if 'screenplay' in item and item['screenplay']:
        w['screenplay'].set_markup("<i>%s</i>" % gutils.html_encode(item['screenplay']))
    else:
        w['screenplay'].set_text('')
    if 'cast' in item and item['cast']:
        w['cast'].set_text(str(item['cast']))
    else:
        w['cast'].set_text('')
    if 'country' in item and item['country']:
        w['country'].set_markup("<i>%s</i>" % gutils.html_encode(item['country']))
    else:
        w['country'].set_text('')
    if 'genre' in item and item['genre']:
        w['genre'].set_markup("<i>%s</i>" % gutils.html_encode(item['genre']))
    else:
        w['genre'].set_text('')
    if 'cond' in item and item['cond']:
        if str(item['cond']) in [str(i) for i in range(len(self._conditions))]:
            w['condition'].set_markup("<i>%s</i>" % self._conditions[item['cond']])
        else:
            w['condition'].set_text('')
            log.info("Wrong value in 'condition' field (movie_id=%s, cond=%s)" % (item['movie_id'], item['cond']))
    else:
        w['condition'].set_text('')
    if 'region' in item and item['region']:
        if item['region'] < len(self._regions):
            w['region'].set_markup("<i>%s</i>" % gutils.html_encode(self._regions[item['region']]))
            if int(item['region']) < 12:
                w['region'].set_tooltip_text(self._regions[int(item['region'])])
        else:
            log.info("Wrong value in 'region' field (movie_id=%s, region=%s)" % (item['movie_id'], item['region']))
            w['region'].set_text('')
            w['region'].set_tooltip_text(self._regions[0])  # N/A
    else:
        w['region'].set_text('')
        w['region'].set_tooltip_text(self._regions[0])  # N/A
    if 'layers' in item and item['layers']:
        if str(item['layers']) in [str(i) for i in range(len(self._layers))]:
            w['layers'].set_markup("<i>%s</i>" % self._layers[item['layers']])
        else:
            log.info("Wrong value in 'layers' field (movie_id=%s, layers=%s)" % (item['movie_id'], item['layers']))
            w['layers'].set_text('')
    else:
        w['layers'].set_text('')
    if 'color' in item and item['color']:
        if str(item['color']) in [str(i) for i in range(len(self._colors))]:
            w['color'].set_markup("<i>%s</i>" % self._colors[item['color']])
        else:
            log.info("Wrong value in 'color' field (movie_id=%s, color=%s)" % (item['movie_id'], item['color']))
            w['color'].set_markup('')
    else:
        w['color'].set_markup('')
    if 'classification' in item and item['classification']:
        w['classification'].set_markup("<i>%s</i>" % gutils.html_encode(item['classification']))
    else:
        w['classification'].set_text('')
    if 'studio' in item and item['studio']:
        w['studio'].set_markup("<i>%s</i>" % gutils.html_encode(item['studio']))
    else:
        w['studio'].set_text('')
    if 'o_site' in item and item['o_site']:
        self._o_site_url = str(item['o_site'])
        w['go_o_site_button'].set_sensitive(True)
    else:
        self._o_site_url = None
        w['go_o_site_button'].set_sensitive(False)
    if 'site' in item and item['site']:
        self._site_url = str(item['site'])
        w['go_site_button'].set_sensitive(True)
    else:
        self._site_url = None
        w['go_site_button'].set_sensitive(False)
    if 'trailer' in item and item['trailer']:
        self._trailer_url = str(item.trailer)
        w['go_trailer_button'].set_sensitive(True)
    else:
        self._trailer_url = None
        w['go_trailer_button'].set_sensitive(False)
    if 'seen' in item and item['seen']:
        w['seen_icon'].set_from_file(os.path.join(self.locations['images'], 'seen.png'))
    else:
        w['seen_icon'].set_from_file(os.path.join(self.locations['images'], 'unseen.png'))
    if 'notes' in item and item['notes']:
        w['notes'].set_text(str(item.notes))
    else:
        w['notes'].set_text('')
    tmp = ''
    if 'media_num' in item and item['media_num']:
        tmp = str(item.media_num)
    else:
        tmp = '0'
    if 'medium_id' in item and item['medium_id']:
        if item.medium is not None:
            tmp += ' x ' + item.medium.name
        else:
            pass
    w['medium'].set_markup("<i>%s</i>" % gutils.html_encode(tmp))
    if 'vcodec_id' in item:
        if item.vcodec is not None:
            w['vcodec'].set_markup("<i>%s</i>" % gutils.html_encode(item.vcodec.name))
        else:
            w['vcodec'].set_text('')
    else:
        w['vcodec'].set_text('')
    # TODO: add widgets in main and edit windows
    # if 'ratio_id' in item:
    #    if item.ratio is not None:
    #        w['ratio'].set_markup("<i>%s</i>" % gutils.html_encode(item.ratio.name))
    #    else:
    #        w['ratio'].set_text('')
    # else:
    #     w['ratio'].set_text('')

    # poster
    if 'poster_md5' in item and item['poster_md5']:
        filename = gutils.get_image_fname(item['poster_md5'], self.db, 'm')
        if filename and os.path.isfile(filename):
            image_path = filename
            self.widgets['add']['delete_poster'].set_sensitive(True)
            w['picture_button'].set_sensitive(True)
        else:
            image_path = gutils.get_defaultimage_fname(self)
            self.widgets['add']['delete_poster'].set_sensitive(False)
            w['picture_button'].set_sensitive(False)
    else:
        image_path = gutils.get_defaultimage_fname(self)
        self.widgets['add']['delete_poster'].set_sensitive(False)
        w['picture_button'].set_sensitive(False)
    # w['picture'].set_from_pixbuf(GdkPixbuf.Pixbuf.new_from_file_at_size(image_path, 100, 140))
    w['picture'].set_from_pixbuf(GdkPixbuf.Pixbuf.new_from_file_at_size(image_path, 200, 280))
    # rating
    rimage = int(self.config.get('rating_image', 0))
    if rimage:
        prefix = ''
    else:
        prefix = 'meter'
    if 'rating' in item and item['rating']:
        rating_file = "%s/%s0%d.png" % (self.locations['images'], prefix, item['rating'])
    else:
        rating_file = "%s/%s0%d.png" % (self.locations['images'], prefix, 0)
    handler = w['image_rating'].set_from_pixbuf(GdkPixbuf.Pixbuf.new_from_file(rating_file))
    gutils.garbage(handler)

    # check loan status and adjust buttons and history box
    if 'loaned' in item and item['loaned'] is True:
        self.widgets['popups']['loan'].set_sensitive(False)
        self.widgets['popups']['email'].set_sensitive(True)
        self.widgets['popups']['return'].set_sensitive(True)
        self.widgets['menu']['loan'].set_sensitive(False)
        self.widgets['menu']['email'].set_sensitive(True)
        self.widgets['menu']['return'].set_sensitive(True)
        w['loan_button'].set_sensitive(False)
        w['email_reminder_button'].set_sensitive(True)
        w['return_button'].set_sensitive(True)

        if getattr(item, 'loan_details', None) is None:
            log.warning(f"movie has no loan data, changing 'loaned' flag to "
                        f"False (movie_id: {item['movie_id']})")
            item.loaned = False
        else:
            self.person_name = item.loan_details.person.name
            self.person_email = item.loan_details.person.email
            self.loan_date = str(item.loan_details.date)
            w['loan_info'].set_use_markup(False)
            w['loan_info'].set_label(_("This movie has been loaned to %s on %s")
                                     % (self.person_name, self.loan_date[:10]))
    if 'loaned' in item and not item['loaned']:  # "loaned" status can be
        # changed above, so don't use "else:" in this line
        self.widgets['popups']['loan'].set_sensitive(True)
        self.widgets['popups']['email'].set_sensitive(False)
        self.widgets['popups']['return'].set_sensitive(False)
        self.widgets['menu']['loan'].set_sensitive(True)
        self.widgets['menu']['email'].set_sensitive(False)
        self.widgets['menu']['return'].set_sensitive(False)
        w['return_button'].set_sensitive(False)
        w['email_reminder_button'].set_sensitive(False)
        w['loan_button'].set_sensitive(True)
        w['loan_info'].set_markup("<b>%s</b>" % _("Movie not loaned"))

    # loan history
    self.loans_treemodel.clear()
    if getattr(item, 'loan_history', None) is not None:
        for loan in item.loan_history:
            myiter = self.loans_treemodel.append(None)
            self.loans_treemodel.set_value(myiter, 0, '%s' % str(loan.date)[:10])
            if loan.return_date and loan.return_date != '':
                self.loans_treemodel.set_value(myiter, 1, str(loan.return_date)[:10])
            else:
                self.loans_treemodel.set_value(myiter, 1, "---")
            if loan.person:
                person = self.db.session.query(db.Person.name).filter_by(person_id=loan.person.person_id).first()
                self.loans_treemodel.set_value(myiter, 2, person.name)

    # volumes/collections
    if 'volume_id' in item and item['volume_id'] is not None:
        if 'volume' in item and item['volume']:
            w['volume'].set_markup("<b>%s</b>" % gutils.html_encode(item['volume'].name))
            w['show_volume_button'].set_sensitive(True)
        else:
            w['volume'].set_text('')
            w['show_volume_button'].set_sensitive(False)
    else:
        w['volume'].set_text('')
        w['show_volume_button'].set_sensitive(False)
    if 'collection_id' in item and item['collection_id'] is not None:
        if 'collection' in item and item['collection']:
            w['collection'].set_markup("<b>%s</b>" % gutils.html_encode(item['collection'].name))
            w['show_collection_button'].set_sensitive(True)
        else:
            w['collection'].set_text('')
            w['show_collection_button'].set_sensitive(False)
    else:
        w['collection'].set_text('')
        w['show_collection_button'].set_sensitive(False)

    # languages
    for i in w['audio_vbox'].get_children():
        i.destroy()
    for i in w['subtitle_vbox'].get_children():
        i.destroy()
    if 'languages' in item and len(item['languages']) > 0:
        for i in item['languages']:
            if i.type == 3:  # subtitles
                if i.subformat:
                    tmp = "%s - %s" % (i.language.name, i.subformat.name)
                else:
                    tmp = "%s" % i.language.name
                w['subtitle_vbox'].pack_start(Gtk.Label(tmp), True, True, 0)
            else:
                language = i.language.name
                if i.type is not None and len(self._lang_types[i.type]) > 0:
                    language += " <i>%s</i>" % self._lang_types[i.type]
                tmp = ''
                if i.achannel:
                    tmp = i.achannel.name
                if i.acodec:
                    if len(tmp) > 0:
                        tmp += ", %s" % i.acodec.name
                    else:
                        tmp = i.acodec.name
                if len(tmp) > 0:
                    tmp = "%s (%s)" % (language, tmp)
                else:
                    tmp = language
                widget = Gtk.Label(label=tmp)
                widget.set_use_markup(True)
                w['audio_vbox'].pack_start(widget, True, True, 0)
    w['audio_vbox'].show_all()
    w['subtitle_vbox'].show_all()
    # tags
    if 'tags' in item:
        tmp = ''
        for tag in item['tags']:
            tmp += "%s, " % tag.name
        tmp = tmp[:-2]  # cut last comma
        w['tags'].set_text(tmp)
    # }}}


def populate(self, movies=None, where=None, qf=True):  # {{{
    # don't try to fill movie list if Griffith is not initialized yet
    if self.initialized is False:
        return False

    if qf and (movies is None or isinstance(movies, Select)):
        if not where:  # due to possible 'seen', 'loaned', 'collection_id' in where
            import advfilter

            # saved in advfilter
            name = self.widgets['filter']['advfilter'].get_active_text()[:-3]  # :-3 due to additional '   ' in the name
            if name:
                cond = self.db.session.query(db.Filter).filter_by(name=name).first()
                if not cond:
                    cond = advfilter.get_def_conditions()
                else:
                    cond = cond.data
            else:
                cond = advfilter.get_def_conditions()
            # add sorting from config
            sort_column_name = self.config.get('sortby', 'number', section='mainlist')
            sort_reverse = self.config.get('sortby_reverse', False, section='mainlist')
            if sort_reverse:
                cond['sort_by'] = {sort_column_name + ' DESC'}
            else:
                cond['sort_by'] = {sort_column_name}

            # seen / loaned
            if self.widgets['menu']['loaned_movies'].get_active():
                cond['loaned'] = True
            if self.widgets['menu']['not_seen_movies'].get_active():
                cond["seen"] = False
            # collection
            pos = self.widgets['filter']['collection'].get_active()
            if pos >= 0:
                col_id = self.collection_combo_ids[pos]
                if col_id > 0:
                    cond["collections"].add(col_id)

            movies = advfilter.create_select_query(self, None, cond, movies)
        else:
            # select sort column
            sort_column_name = self.config.get('sortby', 'number', section='mainlist')
            sort_reverse = self.config.get('sortby_reverse', False, section='mainlist')
            # explicit conditions, only empty dictionary needed to add the order by values
            cond = {}
            if sort_reverse:
                cond['sort_by'] = {sort_column_name + ' DESC'}
            else:
                cond['sort_by'] = {sort_column_name}
            movies = sql.update_whereclause(movies, cond)

        # additional whereclause (volume_id, collection_id, ...)
        if where:
            for i in where:
                if i in db.Movie:
                    movies = movies.where(db.Movie[i] == where[i])
        movies = self.db.session.execute(movies).fetchall()

    self.total = len(movies)
    # disable refreshing while inserting
    self.widgets['treeview'].freeze_child_notify()
    self.widgets['treeview'].set_model(None)

    # save user sort column
    sort_column_id, order = self.treemodel.get_sort_column_id()

    # new treemodel (faster and prevents some problems)
    self.treemodel = Gtk.TreeStore(str, GdkPixbuf.Pixbuf, str, str, str, str, bool, str, str, int, str, str)

    # check preferences to hide or show columns
    if self.config.get('number', True, 'mainlist') is True:
        self.number_column.set_visible(True)
    else:
        self.number_column.set_visible(False)
    if self.config.get('otitle', True, 'mainlist') is True:
        self.otitle_column.set_visible(True)
    else:
        self.otitle_column.set_visible(False)
    if self.config.get('title', True, 'mainlist') is True:
        self.title_column.set_visible(True)
    else:
        self.title_column.set_visible(False)
    if self.config.get('director', True, 'mainlist') is True:
        self.director_column.set_visible(True)
    else:
        self.director_column.set_visible(False)
    if self.config.get('image', True, 'mainlist') is True:
        self.image_column.set_visible(True)
    else:
        self.image_column.set_visible(False)
    if self.config.get('genre', True, 'mainlist') is True:
        self.genre_column.set_visible(True)
    else:
        self.genre_column.set_visible(False)
    if self.config.get('seen', True, 'mainlist') is True:
        self.seen_column.set_visible(True)
    else:
        self.seen_column.set_visible(False)
    if self.config.get('year', True, 'mainlist') is True:
        self.year_column.set_visible(True)
    else:
        self.year_column.set_visible(False)
    if self.config.get('runtime', True, 'mainlist') is True:
        self.runtime_column.set_visible(True)
    else:
        self.runtime_column.set_visible(False)
    if self.config.get('rating', True, 'mainlist') is True:
        self.rating_column.set_visible(True)
    else:
        self.rating_column.set_visible(False)
    if self.config.get('created', True, 'mainlist') is True:
        self.created_column.set_visible(True)
    else:
        self.created_column.set_visible(False)
    if self.config.get('updated', True, 'mainlist') is True:
        self.updated_column.set_visible(True)
    else:
        self.updated_column.set_visible(False)

    for movie in movies:
        addmovie(self, movie)

    # restore user sort column
    if sort_column_id is not None:
        self.treemodel.set_sort_column_id(sort_column_id, order)

    # add new treemodel and allow refreshs again
    self.widgets['treeview'].set_model(self.treemodel)
    self.widgets['treeview'].thaw_child_notify()
    if self.total:
        self.widgets['treeview'].set_cursor_on_cell(Gtk.TreePath.new_from_indices((0,)), None, None, False)
    self.count_statusbar()
# }}}


def addmovie(self, movie):  # {{{
    myiter = self.treemodel.append(None)
    setmovie(self, movie, myiter)
    return myiter
# }}}


def setmovie(self, movie, iter_obj, treemodel=None):  # {{{
    if not treemodel:
        treemodel = self.treemodel

    treemodel.set_value(iter_obj, 0, '%004d' % int(movie.number))

    if self.config.get('image', True, section='mainlist') is True:
        filename = None
        if movie.poster_md5:
            filename = gutils.get_image_fname(movie.poster_md5, self.db, "s")
        if not filename:
            filename = os.path.join(self.locations['images'], 'default_thumbnail.png')

        self.Image.set_from_file(filename)
        try:
            pixbuf = self.Image.get_pixbuf()
            treemodel.set_value(iter_obj, 1, pixbuf)
        except Exception as exc:
            log.exception("can't load the image %s" % filename)
            log.info(f"[E021]Caught too broad try-exception"
                     f" {type(exc).__name__}, '{exc}'")

    treemodel.set_value(iter_obj, 2, movie.o_title)
    treemodel.set_value(iter_obj, 3, movie.title)
    treemodel.set_value(iter_obj, 4, movie.director)
    treemodel.set_value(iter_obj, 5, movie.genre)
    treemodel.set_value(iter_obj, 6, movie.seen)
    if movie.year is not None and (isinstance(movie.year, int) or isinstance(movie.year, int)):
        treemodel.set_value(iter_obj, 7, str(movie.year))
    if movie.runtime is not None and (isinstance(movie.runtime, int) or isinstance(movie.runtime, int)):
        treemodel.set_value(iter_obj, 8, '%003d' % movie.runtime + _(' min'))
    if movie.rating is not None and (isinstance(movie.rating, int) or isinstance(movie.rating, int)):
        treemodel.set_value(iter_obj, 9, movie.rating)
    if movie.created:
        treemodel.set_value(iter_obj, 10, movie.created.strftime('%Y-%m-%d %H:%M'))
    if movie.updated:
        treemodel.set_value(iter_obj, 11, movie.updated.strftime('%Y-%m-%d %H:%M'))
    return iter_obj
# }}}


def select(self, iter_obj, ensurevisible=True):  # {{{
    if iter_obj:
        self.widgets['treeview'].get_selection().select_iter(iter_obj)
        if ensurevisible:
            self.widgets['treeview'].scroll_to_cell(
                self.treemodel.get_path(iter_obj))
    else:
        self.widgets['treeview'].get_selection().unselect_all()
    self.treeview_clicked()
# }}}

# vim: fdm=marker
