#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
# Interpreter version: brython (http://brython.info) (like python3)
#
"""
This module contains class for controlling of some of the HTML elements
(<input>, <input class="typeahead">, <textarea>, <select>).
"""
# Imports =====================================================================
from browser import window
from browser import document

from .dropdown_handler import DropdownHandler
from .placeholder_handler import PlaceholderHandler


# Functions & classes =========================================================
class InputController(object):
    """
    Shared behavior for basic input elements.

    This class allows the inputs, textareas and selects to be set using same
    data format of lists of dicts containing values and their sources.
    """
    # this is used to track what kind of elements were added by typeahead
    _set_by_typeahead = set()

    @staticmethod
    def _set_input(el, value):
        """
        Set content of given `el` to `value`.

        Args:
            el (obj): El reference to input you wish to set.
            value (obj/list): Value to which the `el` will be set.
        """
        if isinstance(value, dict):
            el.value = value["val"]
        elif type(value) in [list, tuple]:
            el.value = ", ".join(item["val"] for item in value)
        else:
            el.value = value

    @staticmethod
    def _set_textarea(el, value):
        """
        Set content of given textarea element `el` to `value`.

        Args:
            el (obj): Reference to textarea element you wish to set.
            value (obj/list): Value to which the `el` will be set.
        """
        if isinstance(value, dict):
            el.text = value["val"]
        elif type(value) in [list, tuple]:
            el.text = "\n\n".join(
                "-- %s --\n%s" % (item["source"], item["val"])
                for item in value
            )
        else:
            el.text = value

    @classmethod
    def _set_typeahead(cls, el, value):
        """
        Convert given `el` to typeahead input and set it to `value`.

        This method also sets the dropdown icons and descriptors.

        Args:
            el (obj): Element reference to the input you want to convert to
                typeahead.
            value (list): List of dicts with two keys: ``source`` and ``val``.
        """
        PlaceholderHandler.reset_placeholder_dropdown(el)

        # if there is no elements, show alert icon in glyph
        if not value and not el.value:
            DropdownHandler.set_dropdown_glyph(el.id, "glyphicon-alert")
            return

        # if there is only one element, don't use typeahead, just put the
        # information to the input, set different dropdown glyph and put source
        # to the dropdown
        if len(value) == 1:
            source = value[0]["source"].strip()
            dropdown_el = DropdownHandler.set_dropdown_glyph(
                el.id,
                "glyphicon-eye-open"
            )
            dropdown_content = "<span class='gray_text'>&nbsp;(%s)</span>"

            # save the source to the dropdown menu
            if source:
                dropdown_el.html = dropdown_content % source[::-1]

            el.value = value[0]["val"]
            return

        # get reference to parent element
        parent_id = el.parent.id
        if "typeahead" not in parent_id.lower():
            parent_id = el.parent.parent.id

        if parent_id in cls._set_by_typeahead:
            window.destroy_typeahead_tag("#" + parent_id)

        # if there are multiple elements, put them to the typeahead and show
        # dropdown glyph
        window.make_typeahead_tag("#" + parent_id, value)
        DropdownHandler.set_dropdown_glyph(el.id, "glyphicon-menu-down")
        PlaceholderHandler.set_placeholder_dropdown(el)
        cls._set_by_typeahead.add(parent_id)

    @classmethod
    def _reset_typeaheads(cls):
        """
        Reset all values set by typeahead back to default.
        """
        for el_id in cls._set_by_typeahead:
            window.destroy_typeahead_tag("#" + el_id)

        cls._set_by_typeahead = set()

    @classmethod
    def set_el(cls, el, value):
        """
        Set given `el` tag element to `value`.

        Automatically choose proper method to set the `value` based on the type
        of the `el`.

        Args:
            el (obj): Element reference to the input you want to convert to
                typeahead.
            value (list): List of dicts with two keys: ``source`` and ``val``.
        """
        if not el:
            return

        tag_name = el.elt.tagName.lower()
        if tag_name == "textarea":
            cls._set_textarea(el, value)
        elif tag_name == "input":
            if "typeahead" in el.class_name.lower():
                cls._set_typeahead(el, value)
            else:
                cls._set_input(el, value)
        elif tag_name == "select":
            el.value = value
        else:
            raise ValueError(
                "Setter for %s (%s) not implemented!" % (tag_name, el.id)
            )

    @staticmethod
    def get_el(el):
        """
        Get value of given `el` tag element.

        Automatically choose proper method to set the `value` based on the type
        of the `el`.

        Args:
            el (obj): Element reference to the input you want to convert to
                typeahead.

        Returns:
            str: Value of the object.
        """
        tag_name = el.elt.tagName.lower()
        if tag_name in {"input", "textarea", "select"}:
            return el.value
        else:
            raise ValueError(
                "Getter for %s (%s) not implemented!" % (tag_name, el.id)
            )
