""" turtle app

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
import traceback
import gi
import turtlevcs
from turtlevcs.dialogs import Notification
gi.require_version("Gtk", "4.0")
gi.require_version("Adw", "1")
from gi.repository import Adw
from gi.repository import Gtk, Gdk, Gio


class TurtleApp(Adw.Application):
    """ turtle application """

    module = None
    args = None
    path = ""
    window = None

    def __init__(self, module, args):
        Adw.Application.__init__(self)
        self.set_flags(Gio.ApplicationFlags.NON_UNIQUE)
        self.set_application_id(turtlevcs.TURTLE_APP_ID)

        self.module = module
        self.args = args

        if len(self.args) > 0:
            self.path = self.args.pop()
        else:
            self.path = os.getcwd()

        self.connect('activate', self._on_activate)

    def _create_window(self):
        # pylint: disable=import-outside-toplevel
        match self.module:
            case "about":
                from turtlevcs.dialogs.about import create_about_window
                self.window = create_about_window()
            case "add":
                from turtlevcs.dialogs.add import AddWindow, AddFileDialog
                if_file = os.path.isfile(self.path)
                self.window = AddFileDialog(self.path) if if_file else AddWindow(self.path)
            case "checkout":
                from turtlevcs.dialogs.checkout import CheckoutWindow
                self.window = CheckoutWindow(self.path)
            case "clean":
                from turtlevcs.dialogs.clean import CleanWindow
                self.window = CleanWindow(self.path)
            case "clone":
                from turtlevcs.dialogs.clone import CloneWindow
                self.window = CloneWindow(self.path)
            case "commit":
                from turtlevcs.dialogs.commit import CommitWindow
                self.window = CommitWindow(self.path)
            case "create_branch" | "create_tag":
                from turtlevcs.dialogs.create import CreateWindow, CreateType
                self.window = CreateWindow(
                    self.path,
                    CreateType.BRANCH if self.module == "create_branch" else CreateType.TAG)
            case "diff_file":
                from turtlevcs.dialogs.diff_file import DiffFile
                self.window = DiffFile(self.path)
            case "diff":
                from turtlevcs.dialogs.diff import DiffWindow
                self.window = DiffWindow(self.path)
            case "init":
                from turtlevcs.dialogs.init import InitWindow
                self.window = InitWindow(self.path)
            case "log":
                from turtlevcs.dialogs.log import LogWindow
                self.window = LogWindow(self.path)
            case "merge":
                from turtlevcs.dialogs.merge import MergeWindow
                self.window = MergeWindow(self.path)
            case "plugin_installer":
                from turtlevcs.dialogs.plugin_installer import PluginInstaller
                self.window = PluginInstaller()
            case "pull":
                from turtlevcs.dialogs.pull import PullWindow
                self.window = PullWindow(self.path)
            case "push":
                from turtlevcs.dialogs.push import PushWindow
                self.window = PushWindow(self.path)
            case "references":
                from turtlevcs.dialogs.references import ReferencesWindow
                self.window = ReferencesWindow(self.path)
            case "remotes":
                from turtlevcs.dialogs.remotes import RemotesWindow
                self.window = RemotesWindow(self.path)
            case "reset":
                from turtlevcs.dialogs.reset import ResetWindow
                self.window = ResetWindow(self.path)
            case "resolve":
                from turtlevcs.dialogs.resolve import ResolveWindow
                self.window = ResolveWindow(self.path)
            case "revert":
                # we can just reuse the AddWindow, which also supports reverting
                from turtlevcs.dialogs.add import AddWindow
                from turtlevcs.dialogs.revert import RevertFileDialog
                is_file = os.path.isfile(self.path)
                self.window = RevertFileDialog(self.path) if is_file \
                    else AddWindow(self.path, revert_instead_of_add=True)
            case "settings":
                from turtlevcs.dialogs.settings import SettingsWindow
                self.window = SettingsWindow(self.path)
            case "settings_menu":
                from turtlevcs.dialogs.settings import SettingsMenuWindow
                self.window = SettingsMenuWindow()
            case "stage":
                from turtlevcs.dialogs.stage import StageDialog, StageConfirmDialog

                settings = turtlevcs.get_settings()
                show_stage_info = settings.get_boolean("stage-show-information")

                self.window = StageDialog(self.path) if show_stage_info \
                    else StageConfirmDialog(None, self.path)
            case "submodules":
                from turtlevcs.dialogs.submodules import SubmodulesWindow
                self.window = SubmodulesWindow(self.path)
            case "sync":
                from turtlevcs.dialogs.sync import SyncWindow
                self.window = SyncWindow(self.path)
            case "unstage":
                from turtlevcs.dialogs.unstage import UnstageConfirmDialog
                self.window = UnstageConfirmDialog(self.path)
            case "update":
                from turtlevcs.dialogs.update import UpdateWindow
                self.window = UpdateWindow(self.path)

    def _on_activate(self, app):
        try:
            self._create_window()
        except Exception as ex:
            settings = turtlevcs.get_settings()
            full_trace = settings.get_boolean("full-exception-trace")

            error = f"{str(ex)}"

            self.window = Notification(error, title=f"Error in {type(self.window).__name__}")
            self.window.set_default_size(400, -1)

            if full_trace:
                expander = Gtk.Expander()
                overlay = Gtk.Overlay()
                button = Gtk.Button()
                button.set_icon_name("edit-copy-symbolic")
                button.set_halign(Gtk.Align.END)
                button.set_valign(Gtk.Align.END)
                overlay.add_overlay(button)
                label = Gtk.Label()
                trace = traceback.format_exc()
                label.set_label(trace)
                label.set_selectable(True)
                overlay.set_child(label)
                expander.set_label("Details")
                expander.set_child(overlay)
                self.window.set_extra_child(expander)

                def copy_trace(_button):
                    trace = label.get_label()
                    clipboard = Gdk.Display().get_default().get_clipboard()
                    clipboard.set(trace)

                button.connect("clicked", copy_trace)

            # raise exception for debug purposes
            # raise ex

        app.add_window(self.window)
        self.window.set_visible(True)
