"""Line numbering implementation for IDLE as an extension.
Includes BaseSideBar which can be extended for other sidebar based extensions
"""
import contextlib
import functools
import itertools

import tkinter as tk
from tkinter.font import Font
from idlelib.config import idleConf
from idlelib.delegator import Delegator
from idlelib import macosx


def get_lineno(text, index):
    """Return the line number of an index in a Tk text widget."""
    text_index = text.index(index)
    return int(float(text_index)) if text_index else None


def get_end_linenumber(text):
    """Return the number of the last line in a Tk text widget."""
    return get_lineno(text, 'end-1c')


def get_displaylines(text, index):
    """Display height, in lines, of a logical line in a Tk text widget."""
    return text.count(f"{index} linestart",
                      f"{index} lineend",
                      "displaylines", return_ints=True)

def get_widget_padding(widget):
    """Get the total padding of a Tk widget, including its border."""
    # TODO: use also in codecontext.py
    manager = widget.winfo_manager()
    if manager == 'pack':
        info = widget.pack_info()
    elif manager == 'grid':
        info = widget.grid_info()
    else:
        raise ValueError(f"Unsupported geometry manager: {manager}")

    # All values are passed through getint(), since some
    # values may be pixel objects, which can't simply be added to ints.
    padx = sum(map(widget.tk.getint, [
        info['padx'],
        widget.cget('padx'),
        widget.cget('border'),
    ]))
    pady = sum(map(widget.tk.getint, [
        info['pady'],
        widget.cget('pady'),
        widget.cget('border'),
    ]))
    return padx, pady


@contextlib.contextmanager
def temp_enable_text_widget(text):
    text.configure(state=tk.NORMAL)
    try:
        yield
    finally:
        text.configure(state=tk.DISABLED)


class BaseSideBar:
    """A base class for sidebars using Text."""
    def __init__(self, editwin):
        self.editwin = editwin
        self.parent = editwin.text_frame
        self.text = editwin.text

        self.is_shown = False

        self.main_widget = self.init_widgets()

        self.bind_events()

        self.update_font()
        self.update_colors()

    def init_widgets(self):
        """Initialize the sidebar's widgets, returning the main widget."""
        raise NotImplementedError

    def update_font(self):
        """Update the sidebar text font, usually after config changes."""
        raise NotImplementedError

    def update_colors(self):
        """Update the sidebar text colors, usually after config changes."""
        raise NotImplementedError

    def grid(self):
        """Layout the widget, always using grid layout."""
        raise NotImplementedError

    def show_sidebar(self):
        if not self.is_shown:
            self.grid()
            self.is_shown = True

    def hide_sidebar(self):
        if self.is_shown:
            self.main_widget.grid_forget()
            self.is_shown = False

    def yscroll_event(self, *args, **kwargs):
        """Hook for vertical scrolling for sub-classes to override."""
        raise NotImplementedError

    def redirect_yscroll_event(self, *args, **kwargs):
        """Redirect vertical scrolling to the main editor text widget.

        The scroll bar is also updated.
        """
        self.editwin.vbar.set(*args)
        return self.yscroll_event(*args, **kwargs)

    def redirect_focusin_event(self, event):
        """Redirect focus-in events to the main editor text widget."""
        self.text.focus_set()
        return 'break'

    def redirect_mousebutton_event(self, event, event_name):
        """Redirect mouse button events to the main editor text widget."""
        self.text.focus_set()
        self.text.event_generate(event_name, x=0, y=event.y)
        return 'break'

    def redirect_mousewheel_event(self, event):
        """Redirect mouse wheel events to the editwin text widget."""
        self.text.event_generate('<MouseWheel>',
                                 x=0, y=event.y, delta=event.delta)
        return 'break'

    def bind_events(self):
        self.text['yscrollcommand'] = self.redirect_yscroll_event

        # Ensure focus is always redirected to the main editor text widget.
        self.main_widget.bind('<FocusIn>', self.redirect_focusin_event)

        # Redirect mouse scrolling to the main editor text widget.
        #
        # Note that without this, scrolling with the mouse only scrolls
        # the line numbers.
        self.main_widget.bind('<MouseWheel>', self.redirect_mousewheel_event)

        # Redirect mouse button events to the main editor text widget,
        # except for the left mouse button (1).
        #
        # Note: X-11 sends Button-4 and Button-5 events for the scroll wheel.
        def bind_mouse_event(event_name, target_event_name):
            handler = functools.partial(self.redirect_mousebutton_event,
                                        event_name=target_event_name)
            self.main_widget.bind(event_name, handler)

        for button in [2, 3, 4, 5]:
            for event_name in (f'<Button-{button}>',
                               f'<ButtonRelease-{button}>',
                               f'<B{button}-Motion>',
                               ):
                bind_mouse_event(event_name, target_event_name=event_name)

            # Convert double- and triple-click events to normal click events,
            # since event_generate() doesn't allow generating such events.
            for event_name in (f'<Double-Button-{button}>',
                               f'<Triple-Button-{button}>',
                               ):
                bind_mouse_event(event_name,
                                 target_event_name=f'<Button-{button}>')

        # start_line is set upon <Button-1> to allow selecting a range of rows
        # by dragging.  It is cleared upon <ButtonRelease-1>.
        start_line = None

        # last_y is initially set upon <B1-Leave> and is continuously updated
        # upon <B1-Motion>, until <B1-Enter> or the mouse button is released.
        # It is used in text_auto_scroll(), which is called repeatedly and
        # does have a mouse event available.
        last_y = None

        # auto_scrolling_after_id is set whenever text_auto_scroll is
        # scheduled via .after().  It is used to stop the auto-scrolling
        # upon <B1-Enter>, as well as to avoid scheduling the function several
        # times in parallel.
        auto_scrolling_after_id = None

        def drag_update_selection_and_insert_mark(y_coord):
            """Helper function for drag and selection event handlers."""
            lineno = get_lineno(self.text, f"@0,{y_coord}")
            a, b = sorted([start_line, lineno])
            self.text.tag_remove("sel", "1.0", "end")
            self.text.tag_add("sel", f"{a}.0", f"{b+1}.0")
            self.text.mark_set("insert",
                               f"{lineno if lineno == a else lineno + 1}.0")

        def b1_mousedown_handler(event):
            nonlocal start_line
            nonlocal last_y
            start_line = int(float(self.text.index(f"@0,{event.y}")))
            last_y = event.y

            drag_update_selection_and_insert_mark(event.y)
        self.main_widget.bind('<Button-1>', b1_mousedown_handler)

        def b1_mouseup_handler(event):
            # On mouse up, we're no longer dragging.  Set the shared persistent
            # variables to None to represent this.
            nonlocal start_line
            nonlocal last_y
            start_line = None
            last_y = None
            self.text.event_generate('<ButtonRelease-1>', x=0, y=event.y)
        self.main_widget.bind('<ButtonRelease-1>', b1_mouseup_handler)

        def b1_drag_handler(event):
            nonlocal last_y
            if last_y is None:  # i.e. if not currently dragging
                return
            last_y = event.y
            drag_update_selection_and_insert_mark(event.y)
        self.main_widget.bind('<B1-Motion>', b1_drag_handler)

        def text_auto_scroll():
            """Mimic Text auto-scrolling when dragging outside of it."""
            # See: https://github.com/tcltk/tk/blob/064ff9941b4b80b85916a8afe86a6c21fd388b54/library/text.tcl#L670
            nonlocal auto_scrolling_after_id
            y = last_y
            if y is None:
                self.main_widget.after_cancel(auto_scrolling_after_id)
                auto_scrolling_after_id = None
                return
            elif y < 0:
                self.text.yview_scroll(-1 + y, 'pixels')
                drag_update_selection_and_insert_mark(y)
            elif y > self.main_widget.winfo_height():
                self.text.yview_scroll(1 + y - self.main_widget.winfo_height(),
                                       'pixels')
                drag_update_selection_and_insert_mark(y)
            auto_scrolling_after_id = \
                self.main_widget.after(50, text_auto_scroll)

        def b1_leave_handler(event):
            # Schedule the initial call to text_auto_scroll(), if not already
            # scheduled.
            nonlocal auto_scrolling_after_id
            if auto_scrolling_after_id is None:
                nonlocal last_y
                last_y = event.y
                auto_scrolling_after_id = \
                    self.main_widget.after(0, text_auto_scroll)
        self.main_widget.bind('<B1-Leave>', b1_leave_handler)

        def b1_enter_handler(event):
            # Cancel the scheduling of text_auto_scroll(), if it exists.
            nonlocal auto_scrolling_after_id
            if auto_scrolling_after_id is not None:
                self.main_widget.after_cancel(auto_scrolling_after_id)
                auto_scrolling_after_id = None
        self.main_widget.bind('<B1-Enter>', b1_enter_handler)


class EndLineDelegator(Delegator):
    """Generate callbacks with the current end line number.

    The provided callback is called after every insert and delete.
    """
    def __init__(self, changed_callback):
        Delegator.__init__(self)
        self.changed_callback = changed_callback

    def insert(self, index, chars, tags=None):
        self.delegate.insert(index, chars, tags)
        self.changed_callback(get_end_linenumber(self.delegate))

    def delete(self, index1, index2=None):
        self.delegate.delete(index1, index2)
        self.changed_callback(get_end_linenumber(self.delegate))


class LineNumbers(BaseSideBar):
    """Line numbers support for editor windows."""
    def __init__(self, editwin):
        super().__init__(editwin)

        end_line_delegator = EndLineDelegator(self.update_sidebar_text)
        # Insert the delegator after the undo delegator, so that line numbers
        # are properly updated after undo and redo actions.
        self.editwin.per.insertfilterafter(end_line_delegator,
                                           after=self.editwin.undo)

    def init_widgets(self):
        _padx, pady = get_widget_padding(self.text)
        self.sidebar_text = tk.Text(self.parent, width=1, wrap=tk.NONE,
                                    padx=2, pady=pady,
                                    borderwidth=0, highlightthickness=0)
        self.sidebar_text.config(state=tk.DISABLED)

        self.prev_end = 1
        self._sidebar_width_type = type(self.sidebar_text['width'])
        with temp_enable_text_widget(self.sidebar_text):
            self.sidebar_text.insert('insert', '1', 'linenumber')
        self.sidebar_text.config(takefocus=False, exportselection=False)
        self.sidebar_text.tag_config('linenumber', justify=tk.RIGHT)

        end = get_end_linenumber(self.text)
        self.update_sidebar_text(end)

        return self.sidebar_text

    def grid(self):
        self.sidebar_text.grid(row=1, column=0, sticky=tk.NSEW)

    def update_font(self):
        font = idleConf.GetFont(self.text, 'main', 'EditorWindow')
        self.sidebar_text['font'] = font

    def update_colors(self):
        """Update the sidebar text colors, usually after config changes."""
        colors = idleConf.GetHighlight(idleConf.CurrentTheme(), 'linenumber')
        foreground = colors['foreground']
        background = colors['background']
        self.sidebar_text.config(
            fg=foreground, bg=background,
            selectforeground=foreground, selectbackground=background,
            inactiveselectbackground=background,
        )

    def update_sidebar_text(self, end):
        """
        Perform the following action:
        Each line sidebar_text contains the linenumber for that line
        Synchronize with editwin.text so that both sidebar_text and
        editwin.text contain the same number of lines"""
        if end == self.prev_end:
            return

        width_difference = len(str(end)) - len(str(self.prev_end))
        if width_difference:
            cur_width = int(float(self.sidebar_text['width']))
            new_width = cur_width + width_difference
            self.sidebar_text['width'] = self._sidebar_width_type(new_width)

        with temp_enable_text_widget(self.sidebar_text):
            if end > self.prev_end:
                new_text = '\n'.join(itertools.chain(
                    [''],
                    map(str, range(self.prev_end + 1, end + 1)),
                ))
                self.sidebar_text.insert(f'end -1c', new_text, 'linenumber')
            else:
                self.sidebar_text.delete(f'{end+1}.0 -1c', 'end -1c')

        self.prev_end = end

    def yscroll_event(self, *args, **kwargs):
        self.sidebar_text.yview_moveto(args[0])
        return 'break'


class WrappedLineHeightChangeDelegator(Delegator):
    def __init__(self, callback):
        """
        callback - Callable, will be called when an insert, delete or replace
                   action on the text widget may require updating the shell
                   sidebar.
        """
        Delegator.__init__(self)
        self.callback = callback

    def insert(self, index, chars, tags=None):
        is_single_line = '\n' not in chars
        if is_single_line:
            before_displaylines = get_displaylines(self, index)

        self.delegate.insert(index, chars, tags)

        if is_single_line:
            after_displaylines = get_displaylines(self, index)
            if after_displaylines == before_displaylines:
                return  # no need to update the sidebar

        self.callback()

    def delete(self, index1, index2=None):
        if index2 is None:
            index2 = index1 + "+1c"
        is_single_line = get_lineno(self, index1) == get_lineno(self, index2)
        if is_single_line:
            before_displaylines = get_displaylines(self, index1)

        self.delegate.delete(index1, index2)

        if is_single_line:
            after_displaylines = get_displaylines(self, index1)
            if after_displaylines == before_displaylines:
                return  # no need to update the sidebar

        self.callback()


class ShellSidebar(BaseSideBar):
    """Sidebar for the PyShell window, for prompts etc."""
    def __init__(self, editwin):
        self.canvas = None
        self.line_prompts = {}

        super().__init__(editwin)

        change_delegator = \
            WrappedLineHeightChangeDelegator(self.change_callback)
        # Insert the TextChangeDelegator after the last delegator, so that
        # the sidebar reflects final changes to the text widget contents.
        d = self.editwin.per.top
        if d.delegate is not self.text:
            while d.delegate is not self.editwin.per.bottom:
                d = d.delegate
        self.editwin.per.insertfilterafter(change_delegator, after=d)

        self.is_shown = True

    def init_widgets(self):
        self.canvas = tk.Canvas(self.parent, width=30,
                                borderwidth=0, highlightthickness=0,
                                takefocus=False)
        self.update_sidebar()
        self.grid()
        return self.canvas

    def bind_events(self):
        super().bind_events()

        self.main_widget.bind(
            # AquaTk defines <2> as the right button, not <3>.
            "<Button-2>" if macosx.isAquaTk() else "<Button-3>",
            self.context_menu_event,
        )

    def context_menu_event(self, event):
        rmenu = tk.Menu(self.main_widget, tearoff=0)
        has_selection = bool(self.text.tag_nextrange('sel', '1.0'))
        def mkcmd(eventname):
            return lambda: self.text.event_generate(eventname)
        rmenu.add_command(label='Copy',
                          command=mkcmd('<<copy>>'),
                          state='normal' if has_selection else 'disabled')
        rmenu.add_command(label='Copy with prompts',
                          command=mkcmd('<<copy-with-prompts>>'),
                          state='normal' if has_selection else 'disabled')
        rmenu.tk_popup(event.x_root, event.y_root)
        return "break"

    def grid(self):
        self.canvas.grid(row=1, column=0, sticky=tk.NSEW, padx=2, pady=0)

    def change_callback(self):
        if self.is_shown:
            self.update_sidebar()

    def update_sidebar(self):
        text = self.text
        text_tagnames = text.tag_names
        canvas = self.canvas
        line_prompts = self.line_prompts = {}

        canvas.delete(tk.ALL)

        index = text.index("@0,0")
        if index.split('.', 1)[1] != '0':
            index = text.index(f'{index}+1line linestart')
        while (lineinfo := text.dlineinfo(index)) is not None:
            y = lineinfo[1]
            prev_newline_tagnames = text_tagnames(f"{index} linestart -1c")
            prompt = (
                '>>>' if "console" in prev_newline_tagnames else
                '...' if "stdin" in prev_newline_tagnames else
                None
            )
            if prompt:
                canvas.create_text(2, y, anchor=tk.NW, text=prompt,
                                   font=self.font, fill=self.colors[0])
                lineno = get_lineno(text, index)
                line_prompts[lineno] = prompt
            index = text.index(f'{index}+1line')

    def yscroll_event(self, *args, **kwargs):
        """Redirect vertical scrolling to the main editor text widget.

        The scroll bar is also updated.
        """
        self.change_callback()
        return 'break'

    def update_font(self):
        """Update the sidebar text font, usually after config changes."""
        font = idleConf.GetFont(self.text, 'main', 'EditorWindow')
        tk_font = Font(self.text, font=font)
        char_width = max(tk_font.measure(char) for char in ['>', '.'])
        self.canvas.configure(width=char_width * 3 + 4)
        self.font = font
        self.change_callback()

    def update_colors(self):
        """Update the sidebar text colors, usually after config changes."""
        linenumbers_colors = idleConf.GetHighlight(idleConf.CurrentTheme(), 'linenumber')
        prompt_colors = idleConf.GetHighlight(idleConf.CurrentTheme(), 'console')
        foreground = prompt_colors['foreground']
        background = linenumbers_colors['background']
        self.colors = (foreground, background)
        self.canvas.configure(background=background)
        self.change_callback()


def _sidebar_number_scrolling(parent):  # htest #
    from idlelib.idle_test.test_sidebar import Dummy_editwin

    top = tk.Toplevel(parent)
    text_frame = tk.Frame(top)
    text_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
    text_frame.rowconfigure(1, weight=1)
    text_frame.columnconfigure(1, weight=1)

    font = idleConf.GetFont(top, 'main', 'EditorWindow')
    text = tk.Text(text_frame, width=80, height=24, wrap=tk.NONE, font=font)
    text.grid(row=1, column=1, sticky=tk.NSEW)

    editwin = Dummy_editwin(text)
    editwin.vbar = tk.Scrollbar(text_frame)

    linenumbers = LineNumbers(editwin)
    linenumbers.show_sidebar()

    text.insert('1.0', '\n'.join('a'*i for i in range(1, 101)))


if __name__ == '__main__':
    from unittest import main
    main('idlelib.idle_test.test_sidebar', verbosity=2, exit=False)

    from idlelib.idle_test.htest import run
    run(_sidebar_number_scrolling)
