# -*- coding: UTF-8 -*-
# based on: https://github.com/gnunn1/tilix/blob/master/data/nautilus/open-tilix.py

from gettext import gettext, textdomain
from subprocess import call
try:
    from urllib import unquote
    from urlparse import urlparse
except ImportError:
    from urllib.parse import unquote, urlparse

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

TERM_PARAMS = {"alacritty": "--working-directory ",
               "cool-retro-term": "--workdir ",
               "deepin-terminal": "--work-directory ",
               "gnome-terminal": "",
               "guake": "guake --show --new-tab=",
               "hyper": "",
               "kitty": "--directory ",
               "konsole": "--workdir ",
               "mate-terminal": "--working-directory=",
               "mlterm": "--working-directory=",
               "qterminal": "--workdir ",
               "st": "-d ",
               "terminator": "--working-directory=",
               "terminology": "--current-directory ",
               "termite": "-d ",
               "tilix": "-w ",
               "urxvt": "-cd ",
               "xfce4-terminal": "--working-directory="}

NEW_TAB_PARAMS = {"alacritty": None,
                  "cool-retro-term": None,
                  "gnome-terminal": "--tab",
                  "guake": None,
                  "hyper": None,
                  "deepin-terminal": None,
                  "kitty": None,
                  "konsole": "--new-tab",
                  "mate-terminal": "--tab",
                  "mlterm": None,
                  "qterminal": None,
                  "st": None,
                  "terminator": "--new-tab",
                  "terminology": None,
                  "termite": None,
                  "tilix": None,
                  "urxvt": None,
                  "xfce4-terminal": "--tab"}

global terminal
terminal = "gnome-terminal"
new_tab = False
GSETTINGS_PATH = "com.github.stunkymonkey.nautilus-open-any-terminal"
GSETTINGS_KEYBINDINGS = "keybindings"
GSETTINGS_TERMINAL = "terminal"
GSETTINGS_NEW_TAB = "new-tab"
REMOTE_URI_SCHEME = ["ftp", "sftp"]
textdomain("nautilus-open-any-terminal")
_ = gettext


def _checkdecode(s):
    """Decode string assuming utf encoding if it's bytes, else return unmodified"""
    return s.decode('utf-8') if isinstance(s, bytes) else s


def open_terminal_in_file(filename):
    if filename:
        # print('{0} {1} {2} "{3}" &'.format(terminal, NEW_TAB_PARAMS[terminal], TERM_PARAMS[terminal], filename))
        # escape filename quotations
        filename = filename.replace('"', '\\"')
        if new_tab:
            call('{0} {1} {2}"{3}" &'.format(terminal, NEW_TAB_PARAMS[
                 terminal], TERM_PARAMS[terminal], filename), shell=True)
        else:
            call('{0} {1}"{2}" &'.format(terminal, TERM_PARAMS[terminal], filename), shell=True)
    else:
        call("{0} &".format(terminal), shell=True)


def set_terminal_args(*args):
    global new_tab
    value = _gsettings.get_string(GSETTINGS_TERMINAL)
    newer_tab = _gsettings.get_boolean(GSETTINGS_NEW_TAB)
    if value in TERM_PARAMS:
        global terminal
        terminal = value
        if newer_tab and NEW_TAB_PARAMS[terminal] is not None:
            new_tab = newer_tab
            new_tab_text = "opening in a new tab"
        else:
            new_tab_text = "opening a new window"
        if newer_tab and NEW_TAB_PARAMS[terminal] is None:
            new_tab_text += " (terminal does not support tabs)"
        print('open-any-terminal: terminal is set to "{0}" {1}'.format(terminal, new_tab_text))
    else:
        print('open-any-terminal: unknown terminal "{0}"'.format(value))


class OpenAnyTerminalShortcutProvider(GObject.GObject, Nautilus.LocationWidgetProvider):

    def __init__(self):
        source = Gio.SettingsSchemaSource.get_default()
        if source.lookup(GSETTINGS_PATH, True):
            self._gsettings = Gio.Settings.new(GSETTINGS_PATH)
            self._gsettings.connect("changed", self._bind_shortcut)
            self._create_accel_group()
        self._window = None
        self._uri = None

    def _create_accel_group(self):
        self._accel_group = Gtk.AccelGroup()
        shortcut = self._gsettings.get_string(GSETTINGS_KEYBINDINGS)
        key, mod = Gtk.accelerator_parse(shortcut)
        self._accel_group.connect(key, mod, Gtk.AccelFlags.VISIBLE,
                                  self._open_terminal)

    def _bind_shortcut(self, gsettings, key):
        if key == GSETTINGS_KEYBINDINGS:
            self._accel_group.disconnect(self._open_terminal)
            self._create_accel_group()

    def _open_terminal(self, *args):
        filename = unquote(self._uri[7:])
        open_terminal_in_file(filename)

    def get_widget(self, uri, window):
        self._uri = uri
        if self._window:
            self._window.remove_accel_group(self._accel_group)
        if self._gsettings:
            window.add_accel_group(self._accel_group)
        self._window = window
        return None


class OpenAnyTerminalExtension(GObject.GObject, Nautilus.MenuProvider):

    def _open_terminal(self, file_):
        if file_.get_uri_scheme() in REMOTE_URI_SCHEME:
            result = urlparse(file_.get_uri())
            if result.username:
                value = "ssh -t {0}@{1}".format(result.username,
                                                result.hostname)
            else:
                value = "ssh -t {0}".format(result.hostname)
            if result.port:
                value = "{0} -p {1}".format(value, result.port)
            if file_.is_directory():
                value = '{0} cd "{1}" ; $SHELL'.format(value, result.path)

            call('{0} -e "{1}" &'.format(terminal, value), shell=True)
        else:
            filename = Gio.File.new_for_uri(file_.get_uri()).get_path()
            open_terminal_in_file(filename)

    def _menu_activate_cb(self, menu, file_):
        self._open_terminal(file_)

    def _menu_background_activate_cb(self, menu, file_):
        self._open_terminal(file_)

    def get_file_items(self, window, files):
        if len(files) != 1:
            return
        items = []
        file_ = files[0]

        if file_.is_directory():

            if file_.get_uri_scheme() in REMOTE_URI_SCHEME:
                uri = _checkdecode(file_.get_uri())
                item = Nautilus.MenuItem(name="NautilusPython::open_remote_item",
                                         label=_(u'Open Remote {}').format(terminal.title()),
                                         tip=_(u'Open Remote {} In {}').format(terminal.title(), uri))
                item.connect("activate", self._menu_activate_cb, file_)
                items.append(item)

            filename = _checkdecode(file_.get_name())
            item = Nautilus.MenuItem(name="NautilusPython::open_file_item",
                                     label=_(u'Open In {}').format(terminal.title()),
                                     tip=_(u'Open {} In {}').format(terminal.title(), filename))
            item.connect("activate", self._menu_activate_cb, file_)
            items.append(item)

        return items

    def get_background_items(self, window, file_):
        items = []
        if file_.get_uri_scheme() in REMOTE_URI_SCHEME:
            item = Nautilus.MenuItem(name="NautilusPython::open_bg_remote_item",
                                     label=_(u'Open Remote {} Here').format(terminal.title()),
                                     tip=_(u'Open Remote {} In This Directory').format(terminal.title()))
            item.connect("activate", self._menu_activate_cb, file_)
            items.append(item)

        item = Nautilus.MenuItem(name="NautilusPython::open_bg_file_item",
                                 label=_(u'In {} öffnen').format(terminal.title()),
                                 tip=_(u'Open {} In This Directory').format(terminal.title()))
        item.connect("activate", self._menu_background_activate_cb, file_)
        items.append(item)
        return items


source = Gio.SettingsSchemaSource.get_default()
if source.lookup(GSETTINGS_PATH, True):
    _gsettings = Gio.Settings.new(GSETTINGS_PATH)
    _gsettings.connect("changed", set_terminal_args)
    value = _gsettings.get_string(GSETTINGS_TERMINAL)
    if value in TERM_PARAMS:
        terminal = value
    if _gsettings.get_boolean(GSETTINGS_NEW_TAB):
        new_tab = bool(NEW_TAB_PARAMS[value] is not None)
