# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
from __python__ import hash_literals, bound_methods

from dom import ensure_id, unique_id, clear
from elementmaker import E
from session import local_storage
from popups import CompletionPopup
from utils import uniq

class EditWithComplete:

    def __init__(self, name, placeholder=None, tooltip=None, parent=None, input_type='text', onenterkey=None):
        inpt = E.input(type=input_type, name=name, title=tooltip or '', placeholder=placeholder or '', autocomplete='off')
        self.input_id = ensure_id(inpt)
        self.onenterkey = onenterkey
        self.completion_popup = CompletionPopup(parent=parent, onselect=self.apply_completion)
        inpt.addEventListener('keydown', self.onkeydown)
        inpt.addEventListener('input', self.oninput)
        self.completion_popup.add_associated_widget(inpt)
        if parent:
            parent.appendChild(inpt)

    @property
    def text_input(self):
        return document.getElementById(self.input_id)

    def apply_completion(self, text):
        if text:
            ti = self.text_input
            ti.value = text
            ti.focus()
            return True

    def onkeydown(self, event):
        if self.completion_popup.is_visible and self.completion_popup.handle_keydown(event):
            event.preventDefault(), event.stopPropagation()
            return
        if event.key is 'Enter':
            if self.completion_popup.is_visible:
                if self.apply_completion(self.completion_popup.current_text):
                    self.completion_popup.hide()
                    event.preventDefault(), event.stopPropagation()
                    return
            if self.onenterkey:
                event.preventDefault(), event.stopPropagation()
                self.onenterkey()
        elif event.key is 'Tab':
            if self.completion_popup.is_visible:
                if self.apply_completion(self.completion_popup.current_text):
                    self.completion_popup.hide()
                else:
                    self.completion_popup.move_highlight()
                event.preventDefault(), event.stopPropagation()
        elif event.key is 'ArrowDown':
            ti = self.text_input
            if not ti.value:
                self.completion_popup.set_query('')
                self.completion_popup.popup(ti)
                event.preventDefault(), event.stopPropagation()

    def oninput(self, event):
        ti = self.text_input
        self.completion_popup.set_query(ti.value or '')
        self.completion_popup.popup(ti)

    def hide_completion_popup(self):
        self.completion_popup.hide()

    def add_associated_widget(self, widget_or_id):
        self.completion_popup.add_associated_widget(widget_or_id)

    def set_all_items(self, items):
        self.completion_popup.set_all_items(items)


def create_search_bar(action, name, tooltip=None, placeholder=None, button=None, history_size=100, associated_widgets=None):
    parent = E.div(style="display:flex")
    ewc = EditWithComplete(name, parent=parent, tooltip=tooltip, placeholder=placeholder, input_type='search')
    parent.lastChild.style.width = '100%'
    history_name = 'search-bar-history-' + name

    def update_completion_items():
        items = local_storage().get(history_name)
        if items?.length:
            ewc.set_all_items(items)
    update_completion_items()

    def trigger():
        text = ewc.text_input.value
        ewc.hide_completion_popup()
        action(text)
        if text and text.strip():
            items = local_storage().get(history_name) or v'[]'
            idx = items.indexOf(text)
            if idx > -1:
                items.splice(idx, 1)
            items.unshift(text)
            local_storage().set(history_name, uniq(items[:history_size]))
            update_completion_items()
    ewc.onenterkey = trigger
    parent.querySelector('input').addEventListener('search', trigger)

    if button:
        ewc.add_associated_widget(button)
        button.addEventListener('click', trigger)
    if associated_widgets is not None:
        for w in associated_widgets:
            ewc.add_associated_widget(w)
    return parent


def create_simple_input_with_history_native(name, tooltip=None, placeholder=None, history_size=100, input_type='text'):
    # cannot use in standalone viewer because of: https://bugreports.qt.io/browse/QTBUG-54433
    dl_id = unique_id()
    dl = document.createElement('datalist')
    dl.id = dl_id
    history_name = f'simple_input_history_{name}'

    def update_completion_items(x):
        items = local_storage().get(history_name)
        dl = x or document.getElementById(dl_id)
        if dl:
            clear(dl)
            if items?.length:
                for item in items:
                    dl.appendChild(E.option(value=item))

    def save_completion_items():
        text = document.getElementById(dl_id).nextSibling.value
        if text and text.strip():
            items = local_storage().get(history_name) or v'[]'
            idx = items.indexOf(text)
            if idx > -1:
                items.splice(idx, 1)
            items.unshift(text)
            local_storage().set(history_name, uniq(items[:history_size]))
            update_completion_items()

    update_completion_items(dl)
    ans = E.span(
        data_calibre_history_input='1',
        dl,
        E.input(type=input_type, name=name, list=dl_id, title=tooltip or '', placeholder=placeholder or ''),
    )
    ans.addEventListener('save_history', save_completion_items)
    return ans


def create_simple_input_with_history(name, tooltip=None, placeholder=None, history_size=100, input_type='text'):
    # to use simply add the returned element to the DOM and when you want to
    # save a new completion item, use dispatchEvent to send a 'save_history'
    # event to it.
    parent = E.span(data_calibre_history_input='1')
    ewc = EditWithComplete(name, parent=parent, tooltip=tooltip, placeholder=placeholder, input_type=input_type)
    history_name = f'simple_input_history_{name}'

    def update_completion_items():
        items = local_storage().get(history_name)
        if items?.length:
            ewc.set_all_items(items)
    update_completion_items()

    def save_completion_items():
        text = ewc.text_input.value
        if text and text.strip():
            items = local_storage().get(history_name) or v'[]'
            idx = items.indexOf(text)
            if idx > -1:
                items.splice(idx, 1)
            items.unshift(text)
            local_storage().set(history_name, uniq(items[:history_size]))
            update_completion_items()

    parent.addEventListener('save_history', save_completion_items)
    return parent
# }}}


def main(container):
    container.appendChild(create_search_bar(print, 'test-search-bar', placeholder='Testing search bar'))
    container.firstChild.lastChild.focus()
    # ewc = EditWithComplete(parent=container, placeholder='Testing edit with complete')
    # ewc.set_all_items('a a1 a11 a12 a13 b b1 b2 b3'.split(' '))
    # ewc.text_input.focus()
