""" settings dialog

This file is part of Turtle.

Turtle 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.

Turtle 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 Turtle. If not, see <https://www.gnu.org/licenses/>.
"""
import os
from subprocess import check_output
import gi
import pygit2
import turtlevcs
from turtlevcs.dialogs import Notification
from turtlevcs.turtle_app import TurtleApp
try:
    from turtlevcs.turtle_plugin import TurtleServiceConnector
except ImportError:
    pass # not available in flatpak

gi.require_version("Gtk", "4.0")
gi.require_version("Adw", "1")
from gi.repository import Adw
from gi.repository import Gtk, Gio, GLib


@Gtk.Template(filename=f"{os.path.dirname(os.path.abspath(__file__))}/ui/settings.ui")
class SettingsWindow(Adw.PreferencesWindow):
    """ settings dialog """
    __gtype_name__ = "SettingsWindow"

    git_group = Gtk.Template.Child()
    git_name = Gtk.Template.Child()
    git_mail = Gtk.Template.Child()
    git_selected_credentials = Gtk.Template.Child()
    git_credential_ssh = Gtk.Template.Child()
    git_credential_agent = Gtk.Template.Child()
    git_ssh_key = Gtk.Template.Child()
    git_agent = Gtk.Template.Child()
    plugins_enable_everywhere = Gtk.Template.Child()
    plugins_show_emblems = Gtk.Template.Child()
    plugins_show_compare = Gtk.Template.Child()
    dialogs_commit_selection = Gtk.Template.Child()
    dialogs_commit_unversioned = Gtk.Template.Child()
    dialogs_commit_ignored = Gtk.Template.Child()
    dialogs_stage_information = Gtk.Template.Child()
    debugging_full_trace = Gtk.Template.Child()
    service_page = Gtk.Template.Child()
    service_pids = Gtk.Template.Child()
    start_service = Gtk.Template.Child()
    stop_service = Gtk.Template.Child()
    start_service_automatically = Gtk.Template.Child()

    open_dialog = None

    in_repo = False
    repo = None
    settings = None

    def __init__(self, path=None):
        Adw.PreferencesWindow.__init__(self)

        self.settings = turtlevcs.get_settings()

        try:
            if path is not None:
                self.in_repo = True
                self.repo = pygit2.Repository(path)
        except Exception:
            self.in_repo = False

        try:
            if self.in_repo:
                author = turtlevcs.get_author(self.repo)
                self.git_name.set_text(author.name)
                self.git_mail.set_text(author.email)
            else:
                text = "only available inside repo"
                self.git_name.set_text(text)
                self.git_mail.set_text(text)
        except Exception as ex:
            window = Notification(str(ex), title="Could not get author information", parent=self)
            window.set_visible(True)

        self._init_settings()

        is_flatpak = os.getenv("container")
        if is_flatpak:
            self.remove(self.service_page)
        else:
            self._refresh_service_status()

    def _init_settings(self):
        if self.settings:
            # git
            self.settings.bind("ssh-key",
                               self.git_ssh_key,
                               "text",
                               Gio.SettingsBindFlags.DEFAULT)
            self.settings.bind("ssh-instead-agent",
                               self.git_credential_ssh,
                               "active",
                               Gio.SettingsBindFlags.DEFAULT)
            self.settings.bind("agent",
                               self.git_agent,
                               "text",
                               Gio.SettingsBindFlags.DEFAULT)

            self.git_credential_agent.set_active(not self.settings.get_boolean("ssh-instead-agent"))
            self._credential_type_changed_handler(self.git_credential_ssh)

            # plugins
            self.settings.bind("enable-everywhere",
                               self.plugins_enable_everywhere,
                               "active",
                               Gio.SettingsBindFlags.DEFAULT)
            self.settings.bind("show-emblems",
                               self.plugins_show_emblems,
                               "active",
                               Gio.SettingsBindFlags.DEFAULT)
            self.settings.bind("show-compare",
                               self.plugins_show_compare,
                               "active",
                               Gio.SettingsBindFlags.DEFAULT)
            # defaults
            # commit
            self.settings.bind("commit-show-unversioned",
                               self.dialogs_commit_unversioned,
                               "active",
                               Gio.SettingsBindFlags.DEFAULT)
            self.settings.bind("commit-show-ignored",
                               self.dialogs_commit_ignored,
                               "active",
                               Gio.SettingsBindFlags.DEFAULT)
            # cannot bind enum to AdwComboRow, sync it manually
            default_commit_selection = self.settings.get_enum("default-commit-selection")
            self.dialogs_commit_selection.set_selected(default_commit_selection)
            self.dialogs_commit_selection.connect(
                "notify::selected",
                self._on_dialogs_commit_selection_changed)
            # stage
            self.settings.bind("stage-show-information",
                               self.dialogs_stage_information,
                               "active",
                               Gio.SettingsBindFlags.DEFAULT)

            # debugging
            self.settings.bind("full-exception-trace",
                               self.debugging_full_trace,
                               "active",
                               Gio.SettingsBindFlags.DEFAULT)

            # service
            self.settings.bind("start-service-automatically",
                               self.start_service_automatically,
                               "active",
                               Gio.SettingsBindFlags.DEFAULT)

    def _on_dialogs_commit_selection_changed(self, widget, property):
        default_commit_selection = self.dialogs_commit_selection.get_selected()
        self.settings.set_enum("default-commit-selection", default_commit_selection)


    @Gtk.Template.Callback()
    def _credential_type_changed_handler(self, _widget):
        is_ssh = self.git_credential_ssh.get_active()
        self.git_ssh_key.set_sensitive(is_ssh)
        self.git_agent.set_sensitive(not is_ssh)

        self.git_selected_credentials.set_subtitle("Selected credentials: " + ("ssh" if is_ssh else "user agent"))

    @Gtk.Template.Callback()
    def _search_ssh_key(self, _widget):
        if not self.open_dialog:
            self.open_dialog = Gtk.FileChooserNative.new(
                title="Choose an SSH private key",
                parent=self, action=Gtk.FileChooserAction.OPEN)
            self.open_dialog.connect("response", self._search_ssh_key_callback)
        path = self.git_ssh_key.get_text()
        if len(path) > 0 and os.path.exists(path):
            self.open_dialog.set_file(Gio.File.new_for_path(path))
        self.open_dialog.show()

    def _search_ssh_key_callback(self, dialog, response):
        if response == Gtk.ResponseType.ACCEPT:
            path = dialog.get_file().get_path()
            if os.path.exists(path):
                self.git_ssh_key.set_text(path)

    @Gtk.Template.Callback()
    def _refresh_service_status(self, _widget=None):
        output = check_output(["ps", "x"]).decode("utf8")
        processes = output.split("\n")

        pids = []

        for process in processes:
            if "turtle_service.py" in process:
                values = process.strip().split(" ", 1)
                pid = values[0]
                pids.append(pid)

        if len(pids) > 0:
            self.service_pids.set_label(", ".join(pids))
        else:
            self.service_pids.set_label("(unavailable)")

        try:
            is_runnig = True
            turtle_service = TurtleServiceConnector()
            current_pid = turtle_service.get_pid()
        except Exception as _ex:
            is_runnig = False

        self.start_service.set_sensitive(not is_runnig)
        self.stop_service.set_sensitive(is_runnig)

    @Gtk.Template.Callback()
    def _start_service(self, _widget):
        try:
            turtle_service = TurtleServiceConnector()
            turtle_service.restart_service()
        except Exception as _ex:
            pass
        finally:
            GLib.timeout_add(200, self._refresh_service_status)

    @Gtk.Template.Callback()
    def _stop_service(self, _widget):
        try:
            turtle_service = TurtleServiceConnector()
            turtle_service.shutdown()
        except Exception as _ex:
            pass
        finally:
            GLib.timeout_add(200, self._refresh_service_status)


if __name__ == "__main__":
    TurtleApp(SettingsWindow).run()
