"""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."""
    res = text.count(f"{index} linestart",
                     f"{index} lineend",
                     "displaylines")
    return res[0] if res else 0

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 True:
            lineinfo = text.dlineinfo(index)
            if lineinfo is None:
                break
            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 _linenumbers_drag_scrolling(parent):  # htest #
    from idlelib.idle_test.test_sidebar import Dummy_editwin

    toplevel = tk.Toplevel(parent)
    text_frame = tk.Frame(toplevel)
    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(toplevel, '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(_linenumbers_drag_scrolling)
