#!/usr/bin/python3
# -*- coding: utf-8 -*-
#    nemo-compare --- Context menu extension for Nemo file manager
#    Copyright (C) 2011  Guido Tabbernuk <boamaod@gmail.com>
#
#    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 3 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 General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

import sys
import os
from urllib import parse
import gettext
import locale
import signal
from gi.repository import GLib
signal.signal(signal.SIGINT, signal.SIG_DFL)

# Import the gettext function and alias it as _
from gettext import gettext as _

import gi
gi.require_version('Nemo', '3.0')
from gi.repository import Nemo, GObject, Gio

sys.path.append("/usr/share/nemo-compare")

import utils

class NemoCompareExtension(GObject.GObject, Nemo.MenuProvider, Nemo.NameAndDescProvider):
    '''Class for the extension itself'''

    # to hold an item for later comparison
    for_later = None

    def __init__(self):
        '''Load config'''

        self.config = utils.NemoCompareConfig()
        self.config.load()

    def menu_activate_cb(self, menu, paths):
        '''Telling from amount of paths runs appropriate comparator engine'''
        if len(paths) == 1:
            self.for_later = paths[0]
            return

        cmd = None
        if len(paths) == 2:
            cmd = [self.config.diff_engine] + paths
        elif len(paths) == 3 and len(self.config.diff_engine_3way.strip()) > 0:
            cmd = [self.config.diff_engine_3way] + paths
        elif len(self.config.diff_engine_multi.strip()) > 0:
            cmd = [self.config.diff_engine_multi] + paths

        if cmd is not None:
            GLib.spawn_async(argv=cmd, flags=GLib.SpawnFlags.DEFAULT | GLib.SpawnFlags.SEARCH_PATH)

    def valid_file(self, file):
        '''Tests if the file is valid comparable'''
        if file.get_uri_scheme() == 'file' and file.get_file_type() in (Gio.FileType.DIRECTORY, Gio.FileType.REGULAR, Gio.FileType.SYMBOLIC_LINK):
            return True
        else:
            return False

    def get_file_items(self, window, files):
        '''Main method to detect what choices should be offered in the context menu'''
        paths = []
        for file in files:
            if self.valid_file(file):
                path = parse.unquote(file.get_uri()[7:])
                paths.append(path)

        # no files selected
        if len(paths) < 1:
            return

        # initialize i18n
        locale.setlocale(locale.LC_ALL, '')
        gettext.bindtextdomain("nemo-extensions")
        gettext.textdomain("nemo-extensions")
        _ = gettext.gettext

        item1 = None
        item2 = None
        item3 = None

        # for paths with remembered items
        new_paths = list(paths)

        for_later_relative = None
        if self.for_later is not None:
            if len(paths) >= 1:
                for_later_relative = os.path.relpath(self.for_later, os.path.dirname(paths[0]))
            else:
                for_later_relative = self.for_later

        # exactly one file selected
        if len(paths) == 1:

            # and one was already selected for later comparison
            if self.for_later is not None:

                # we don't want to compare file to itself
                if self.for_later not in paths:
                    item1 = Nemo.MenuItem(
                        name="NemoCompareExtension::CompareTo",
                        label=_('Compare to: ') + for_later_relative,
                        tip=_("Compare to the file previously selected")
                    )

                    # compare the one saved for later to the one selected now
                    new_paths.insert(0, self.for_later)

            # if only one file selected, we offer to remember it for later anyway
            item3 = Nemo.MenuItem(
                name="NemoCompareExtension::CompareLater",
                label=_('Compare Later'),
                tip=_("Remember file for later comparison")
            )

        # can always compare, if more than one selected
        else:
            # if we have already remembered one file and add some more, we can do n-way compare
            if self.for_later is not None:
                if self.for_later not in paths:
                    # if multi compare enabled and in case of 2 files selected 3way compare enabled
                    if len(self.config.diff_engine_multi.strip()) > 0 or (len(paths) == 2 and len(self.config.diff_engine_3way.strip()) > 0):
                        item1 = Nemo.MenuItem(
                            name="NemoCompareExtension::MultiCompare",
                            label=_('Compare to: ') + for_later_relative,
                            tip=_("Compare to the file previously selected")
                        )
                        # compare the one saved for later to the ones selected now
                        new_paths.insert(0, self.for_later)

            # if multi compare enabled, we can compare any number
            # if there are two files selected we can always compare
            # if three files selected and 3-way compare is on, we can do it
            if len(self.config.diff_engine_multi.strip()) > 0 or len(paths) == 2 or (len(paths) == 3 and len(self.config.diff_engine_3way.strip()) > 0):
                item2 = Nemo.MenuItem(
                    name="NemoCompareExtension::CompareWithin",
                    label=_('Compare'),
                    tip=_("Compare selected files")
                )

        if item1: item1.connect('activate', self.menu_activate_cb, new_paths)
        if item2: item2.connect('activate', self.menu_activate_cb, paths)
        if item3: item3.connect('activate', self.menu_activate_cb, paths)

        items = [item1, item2, item3]

        while None in items:
            items.remove(None)

        return items

    def get_background_items(self, window, item):
        return []

    def get_name_and_desc(self):
        description = _("Allows file comparison from the context menu")
        return [(f"nemo-compare:::{description}:::nemo-compare-preferences")]
