# -----------------------------------------------------------------------------
# Copyright (c) 2012 - 2019, Anaconda, Inc. and Intake contributors
# All rights reserved.
#
# The full license is in the LICENSE file, distributed with this software.
# -----------------------------------------------------------------------------
import panel as pn

from ..base import MAX_WIDTH, Base


class SearchInputs(Base):
    """Input areas to control search parameters

    Attributes
    ----------
    text: str
        text to use in search. Displayed in text_widget
    depth: int or 'All'
        depth of nestedness to use in search. Displayed in depth_widget.
    children: list of panel objects
        children that will be used to populate the panel when visible
    panel: panel layout object
        instance of a panel layout (row or column) that contains children
        when visible
    watchers: list of param watchers
        watchers that are set on children - cleaned up when visible
        is set to false.
    """

    def __init__(self, **kwargs):
        self.panel = pn.Row(name="Search Inputs", height_policy="min", margin=0)
        super().__init__(**kwargs)

    def setup(self):
        text_label = pn.pane.Markdown("Search Text:", align="center")
        depth_label = pn.pane.Markdown("Depth:", align="center")
        self.text_widget = pn.widgets.TextInput(placeholder="Set of words", width_policy="max", align="center")
        self.depth_widget = pn.widgets.Select(options=["1", "2", "3", "4", "5", "All"], width=80, height=30, align="center")

        self.children = [text_label, self.text_widget, depth_label, self.depth_widget]

    @property
    def text(self):
        """Text to use in search. Displayed in text_widget"""
        return self.text_widget.value

    @text.setter
    def text(self, text):
        self.text_widget.value = text

    @property
    def depth(self):
        """Depth of nestedness to use in search. Displayed in depth_widget"""
        return int(self.depth_widget.value) if self.depth_widget.value != "All" else 99

    @depth.setter
    def depth(self, depth):
        if isinstance(depth, int):
            depth = str(depth) if depth <= 5 else "All"
        self.depth_widget.value = depth

    def __getstate__(self):
        """Serialize the current state of the object"""
        return {
            "text": self.text,
            "depth": self.depth,
        }

    def __setstate__(self, state):
        """Set the current state of the object from the serialized version.
        Works inplace. See ``__getstate__`` to get serialized version and
        ``from_state`` to create a new object."""
        self.text = state["text"]
        self.depth = state["depth"]
        return self


class Search(Base):
    """Search panel for searching a list of catalogs

    Parameters
    ----------
    cats: list of catalogs
        catalogs that will be searched
    done_callback: function with cats as input
        function that is called when new cats have been generated
        via the search functionality

    Attributes
    ----------
    children: list of panel objects
        children that will be used to populate the panel when visible
    panel: panel layout object
        instance of a panel layout (row or column) that contains children
        when visible
    watchers: list of param watchers
        watchers that are set on children - cleaned up when visible
        is set to false.
    """

    def __init__(self, cats, done_callback=None, **kwargs):
        self.cats = cats
        self.done_callback = done_callback
        self.panel = pn.Row(name="Search", height_policy="min", width_policy="max", max_width=MAX_WIDTH, margin=0)
        self.inputs = SearchInputs()
        super().__init__(**kwargs)

    def setup(self):
        self.widget = pn.widgets.Button(name="🔍", width=50, align="center")

        self.watchers = [self.widget.param.watch(self.do_search, "clicks")]

        self.children = [self.inputs.panel, self.widget]

    def do_search(self, arg=None):
        """Do search and close panel"""
        new_cats = []
        for cat in self.cats:
            new_cat = cat.search(self.inputs.text, depth=self.inputs.depth)
            if len(list(new_cat)) > 0:
                new_cats.append(new_cat)
        if len(new_cats) > 0:
            self.done_callback(new_cats)
            self.visible = False

    def __getstate__(self, include_cats=True):
        """Serialize the current state of the object. Set include_cats
        to False when using with another panel that will include cats."""
        state = {"visible": self.visible, "inputs": self.inputs.__getstate__()}
        if include_cats:
            state["cats"] = [cat.__getstate__() for cat in self.cats]
        return state

    def __setstate__(self, state):
        """Set the current state of the object from the serialized version.
        Works inplace. See ``__getstate__`` to get serialized version and
        ``from_state`` to create a new object."""
        if "cats" in state:
            self.cats = state["cats"]
        self.visible = state.get("visible", True)
        self.inputs.__setstate__(state["inputs"])
        return self
