from gi.repository import Gtk, Gdk, GtkSource, GObject
from gettext import gettext as _
from notorious.file_manager import FileManager
from notorious.confManager import ConfManager
from datetime import datetime

# without this line Gtk.Builder doesn't accept GtkSourceView from glade file
GObject.type_register(GtkSource.View)


class NotoriousUI(Gtk.Bin):
    def __init__(self, search_entry, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.confman = ConfManager()
        self.builder = Gtk.Builder.new_from_resource(
            '/org/gabmus/notorious/ui/main_ui.glade'
        )
        self.ui_box = self.builder.get_object('ui_box')

        self.search_entry = search_entry
        self.results_listbox = self.builder.get_object(
            'search_results_listbox'
        )
        self.results_listbox_revealer = self.builder.get_object(
            'results_listbox_revealer'
        )
        self.source_style_scheme_manager = \
            GtkSource.StyleSchemeManager.get_default()
        self.source_language_manager = GtkSource.LanguageManager.get_default()
        self.source_lang_markdown = self.source_language_manager.get_language(
            'markdown'
        )
        self.source_buffer = GtkSource.Buffer()
        self.on_dark_mode_changed()
        # THIS IS SLOW!
        self.source_buffer.set_language(self.source_lang_markdown)
        self.on_enable_syntax_highlighting_changed()
        self.confman.connect(
            'markdown_syntax_highlighting_changed',
            self.on_enable_syntax_highlighting_changed
        )
        self.confman.connect(
            'dark_mode_changed',
            self.on_dark_mode_changed
        )
        self.confman.connect(
            'editor_color_scheme_changed',
            self.change_color_scheme
        )
        self.source_view = self.builder.get_object(
            'sourceview'
        )
        self.source_view.set_buffer(self.source_buffer)

        self.source_view.connect(
            'key-press-event',
            self.on_source_view_key_press_event
        )

        self.file_manager = FileManager(
            self.search_entry,
            self.results_listbox,
            self.source_buffer,
            self.source_view,
            self.results_listbox_revealer
        )

        self.note_changed_infobar = self.builder.get_object(
            'note_changed_infobar'
        )

        self.file_manager.connect(
            'note_changed',
            self.on_note_changed
        )

        self.infobar_note_changed_label = self.builder.get_object(
            'infobar_note_changed_label'
        )
        self.infobar_reload_note_btn = self.builder.get_object(
            'infobar_reload_note_btn'
        )
        self.infobar_overwrite_note_btn = self.builder.get_object(
            'infobar_overwrite_note_btn'
        )
        self.infobar_reload_note_btn.connect('clicked', self.on_reload_note)
        self.infobar_overwrite_note_btn.connect(
            'clicked',
            self.on_overwrite_note
        )

        self.menu_popover = Gtk.PopoverMenu()
        self.menu_builder = Gtk.Builder.new_from_resource(
            '/org/gabmus/notorious/ui/note_listbox_menu.xml'
        )
        self.menu = self.menu_builder.get_object('noteListboxMenu')
        # self.delete_menu_item = self.menu.get_children()[1]
        # self.rename_menu_item = self.menu.get_children()[1]
        # self.delete_menu_item.connect(
        #     'activate',
        #     self.on_delete
        # )
        # self.rename_menu_item.connect(
        #     'activate',
        #     lambda *args: print('rename')
        # )
        self.menu_popover.bind_model(self.menu)
        self.menu_popover.set_relative_to(self.results_listbox)
        self.menu_popover.set_modal(True)

        self.results_listbox.connect(
            'button-press-event',
            self.on_results_listbox_button_press_event
        )
        self.results_listbox.connect(
            'key-press-event',
            self.on_results_listbox_key_press_event
        )
        self.longpress = Gtk.GestureLongPress.new(self.results_listbox)
        self.longpress.set_propagation_phase(Gtk.PropagationPhase.TARGET)
        self.longpress.set_touch_only(False)
        self.longpress.connect(
            'pressed',
            self.on_results_listbox_right_click,
            self
        )
        self.rightclicked_row = None

        self.add(self.ui_box)

    def on_note_changed(self, *args):
        self.infobar_note_changed_label.set_text(
            _('Note "{0}" has changed').format(
                self.file_manager.currently_open_file.split('/')[-1]
            )
        )
        self.note_changed_infobar.set_revealed(True)

    def on_reload_note(self, *args):
        self.file_manager.reload_note()
        self.note_changed_infobar.set_revealed(False)

    def on_overwrite_note(self, *args):
        self.file_manager.overwrite_note()
        self.note_changed_infobar.set_revealed(False)

    def on_results_listbox_right_click(self, e_or_g, x, y, *args):
        row = self.results_listbox.get_row_at_y(y)
        if row:
            self.menu_popover.set_relative_to(row)
            self.menu_popover.popup()
            self.rightclicked_row = row

    def on_results_listbox_button_press_event(self, widget, event):
        # right click
        if event.type == Gdk.EventType.BUTTON_PRESS and event.button == 3:
            self.on_results_listbox_right_click(event, event.x, event.y)

    def on_results_listbox_key_press_event(self, widget, event):
        if (
                event.state & Gdk.ModifierType.CONTROL_MASK
        ) == Gdk.ModifierType.CONTROL_MASK:
            move_selection = None
            if event.keyval == Gdk.KEY_j:
                move_selection = 'down'
            elif event.keyval == Gdk.KEY_k:
                move_selection = 'up'
            if move_selection in ('down', 'up'):
                target_row = self.results_listbox.get_row_at_index(
                    (
                        self.results_listbox.get_selected_row() or
                        self.results_listbox.get_row_at_index(0)
                    ).get_index() + (-1 if move_selection == 'up' else 1)
                )
                if target_row in self.results_listbox.get_children():
                    self.results_listbox.select_row(
                        target_row
                    )

    def on_enable_syntax_highlighting_changed(self, *args):
        self.source_buffer.set_highlight_syntax(
            self.confman.conf['show_markdown_syntax_highlighting']
        )

    def on_source_view_key_press_event(self, widget, event):
        if event.keyval == Gdk.KEY_Escape:
            self.search_entry.grab_focus()
        elif (
                event.state & Gdk.ModifierType.CONTROL_MASK
        ) == Gdk.ModifierType.CONTROL_MASK:
            if event.keyval == Gdk.KEY_t:
                self.source_buffer.insert_at_cursor(
                    datetime.now().isoformat(sep=' ', timespec='seconds')
                )

    def on_dark_mode_changed(self, *args):
        Gtk.Settings.get_default().set_property(
            'gtk-application-prefer-dark-theme',
            self.confman.conf['dark_mode']
        )
        self.change_color_scheme()

    def change_color_scheme(self, *args):
        available_schemes = self.source_style_scheme_manager.get_scheme_ids()
        color_scheme = self.confman.conf['editor_color_scheme']
        if color_scheme == 'default' or color_scheme not in available_schemes:
            if 'builder' in available_schemes:
                color_scheme = (
                    'builder' +
                    '-dark' if self.confman.conf['dark_mode'] else ''
                )
            else:
                color_scheme = (
                    'oblivion'
                    if self.confman.conf['dark_mode']
                    else 'tango'
                )
        self.source_buffer.set_style_scheme(
            self.source_style_scheme_manager.get_scheme(color_scheme)
        )
