"""
Components/Chip
===============

.. seealso::

    `Material Design spec, Chips <https://material.io/components/chips>`_

.. rubric:: Chips are compact elements that represent an input, attribute, or action.

.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chips.png
    :align: center

Usage
-----

.. code-block:: python

    from kivy.lang import Builder

    from kivymd.app import MDApp

    KV = '''
    MDScreen:

        MDChip:
            text: "Portland"
            pos_hint: {"center_x": .5, "center_y": .5}
            on_release: app.on_release_chip(self)
    '''


    class Test(MDApp):
        def build(self):
            return Builder.load_string(KV)

        def on_release_chip(self, instance_check):
            print(instance_check)


    Test().run()

.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/ordinary-chip.png
    :align: center

Use with right icon
-------------------

.. code-block:: kv

    MDChip:
        text: "Portland"
        icon_right: "close-circle-outline"

.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-with-right-icon.png
    :align: center

Use with left icon
------------------

.. code-block:: kv

    MDChip:
        text: "Portland"
        icon_left: "map-marker"

.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-with-left-icon.png
    :align: center

Use with custom left icon
-------------------------

.. code-block:: kv

    MDChip:
        text: "Portland"
        icon_left: "avatar.png"

.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-with-custom-left-icon.png
    :align: center

Use with left and right icon
----------------------------

.. code-block:: kv

    MDChip:
        text: "Portland"
        icon_left: "avatar.png"
        icon_right: "close-circle-outline"

.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-with-left-right-icon.png
    :align: center

Use with outline
----------------

.. code-block:: kv

    MDChip:
        text: "Portland"
        icon_left: "avatar.png"
        icon_right: "close-circle-outline"
        line_color: app.theme_cls.disabled_hint_text_color

.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-with-outline.png
    :align: center

Use with custom color
---------------------

.. code-block:: kv

    MDChip:
        text: "Portland"
        icon_left: "avatar.png"
        icon_right: "close-circle-outline"
        line_color: app.theme_cls.disabled_hint_text_color
        md_bg_color: 1, 0, 0, .5

.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-with-custom-color.png
    :align: center

Use with elevation
------------------

.. code-block:: kv

    MDChip:
        text: "Portland"
        icon_left: "avatar.png"
        icon_right: "close-circle-outline"
        line_color: app.theme_cls.disabled_hint_text_color
        md_bg_color: 1, 0, 0, .5
        elevation: 4

.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-with-elevation.png
    :align: center

Behavior
========

Long press on the chip, it will be marked.
When you click on the marked chip, the mark will be removed:

.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-activate.gif
    :align: center

Examples
========

Multiple choose
---------------

Selecting a single choice chip automatically deselects all other chips in the set.

.. code-block:: python

    from kivy.animation import Animation
    from kivy.lang import Builder

    from kivymd.uix.screen import MDScreen
    from kivymd.uix.chip import MDChip
    from kivymd.app import MDApp

    KV = '''
    <MyScreen>

        MDBoxLayout:
            orientation: "vertical"
            adaptive_size: True
            spacing: "12dp"
            padding: "56dp"
            pos_hint: {"center_x": .5, "center_y": .5}

            MDLabel:
                text: "Multiple choice"
                bold: True
                font_style: "H5"
                adaptive_size: True

            MDBoxLayout:
                id: chip_box
                adaptive_size: True
                spacing: "8dp"

                MyChip:
                    text: "Elevator"
                    on_press: if self.active: root.removes_marks_all_chips()

                MyChip:
                    text: "Washer / Dryer"
                    on_press: if self.active: root.removes_marks_all_chips()

                MyChip:
                    text: "Fireplace"
                    on_press: if self.active: root.removes_marks_all_chips()


    ScreenManager:

        MyScreen:
    '''


    class MyChip(MDChip):
        icon_check_color = (0, 0, 0, 1)
        text_color = (0, 0, 0, 0.5)
        _no_ripple_effect = True

        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            self.bind(active=self.set_chip_bg_color)
            self.bind(active=self.set_chip_text_color)

        def set_chip_bg_color(self, instance_chip, active_value: int):
            '''
            Will be called every time the chip is activated/deactivated.
            Sets the background color of the chip.
            '''

            self.md_bg_color = (
                (0, 0, 0, 0.4)
                if active_value
                else (
                    self.theme_cls.bg_darkest
                    if self.theme_cls.theme_style == "Light"
                    else (
                        self.theme_cls.bg_light
                        if not self.disabled
                        else self.theme_cls.disabled_hint_text_color
                    )
                )
            )

        def set_chip_text_color(self, instance_chip, active_value: int):
            Animation(
                color=(0, 0, 0, 1) if active_value else (0, 0, 0, 0.5), d=0.2
            ).start(self.ids.label)


    class MyScreen(MDScreen):
        def removes_marks_all_chips(self):
            for instance_chip in self.ids.chip_box.children:
                if instance_chip.active:
                    instance_chip.active = False


    class Test(MDApp):
        def build(self):
            return Builder.load_string(KV)


    Test().run()

.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-multiple-choose.gif
    :align: center

Only choose
-----------

Only one chip will be selected.

.. code-block:: python

    KV = '''
    <MyScreen>

        [...]

            MDBoxLayout:
                id: chip_box
                adaptive_size: True
                spacing: "8dp"

                MyChip:
                    text: "Elevator"
                    on_active: if self.active: root.removes_marks_all_chips(self)

                MyChip:
                    text: "Washer / Dryer"
                    on_active: if self.active: root.removes_marks_all_chips(self)

                MyChip:
                    text: "Fireplace"
                    on_active: if self.active: root.removes_marks_all_chips(self)


    [...]
    '''


    class MyScreen(MDScreen):
        def removes_marks_all_chips(self, selected_instance_chip):
            for instance_chip in self.ids.chip_box.children:
                if instance_chip != selected_instance_chip:
                    instance_chip.active = False

.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-only-choose.gif
    :align: center
"""

__all__ = ("MDChip",)

import os

from kivy.animation import Animation
from kivy.lang import Builder
from kivy.metrics import dp
from kivy.properties import BooleanProperty, ColorProperty, StringProperty
from kivy.uix.behaviors import ButtonBehavior

from kivymd import uix_path
from kivymd.theming import ThemableBehavior
from kivymd.uix.behaviors import (
    CommonElevationBehavior,
    RectangularRippleBehavior,
    ScaleBehavior,
    TouchBehavior,
)
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.label import MDIcon

with open(
    os.path.join(uix_path, "chip", "chip.kv"), encoding="utf-8"
) as kv_file:
    Builder.load_string(kv_file.read())


class MDChip(
    MDBoxLayout,
    ThemableBehavior,
    RectangularRippleBehavior,
    ButtonBehavior,
    CommonElevationBehavior,
    TouchBehavior,
):
    text = StringProperty()
    """
    Chip text.

    :attr:`text` is an :class:`~kivy.properties.StringProperty`
    and defaults to `''`.
    """

    icon_left = StringProperty()
    """
    Chip left icon.

    .. versionadded:: 1.0.0

    :attr:`icon_left` is an :class:`~kivy.properties.StringProperty`
    and defaults to `''`.
    """

    icon_right = StringProperty()
    """
    Chip right icon.

    .. versionadded:: 1.0.0

    :attr:`icon_right` is an :class:`~kivy.properties.StringProperty`
    and defaults to `''`.
    """

    text_color = ColorProperty(None)
    """
    Chip's text color in (r, g, b, a) or string format.

    :attr:`text_color` is an :class:`~kivy.properties.ColorProperty`
    and defaults to `None`.
    """

    icon_right_color = ColorProperty(None)
    """
    Chip's right icon color in (r, g, b, a) or string format.

    .. versionadded:: 1.0.0

    :attr:`icon_right_color` is an :class:`~kivy.properties.ColorProperty`
    and defaults to `None`.
    """

    icon_left_color = ColorProperty(None)
    """
    Chip's left icon color in (r, g, b, a) or string format.

    .. versionadded:: 1.0.0

    :attr:`icon_left_color` is an :class:`~kivy.properties.ColorProperty`
    and defaults to `None`.
    """

    icon_check_color = ColorProperty(None)
    """
    Chip's check icon color in (r, g, b, a) or string format.

    .. versionadded:: 1.0.0

    :attr:`icon_check_color` is an :class:`~kivy.properties.ColorProperty`
    and defaults to `None`.
    """

    active = BooleanProperty(False)
    """
    Whether the check is marked or not.

    .. versionadded:: 1.0.0

    :attr:`active` is an :class:`~kivy.properties.BooleanProperty`
    and defaults to `False`.
    """

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def on_long_touch(self, *args) -> None:
        if self.active:
            return
        self.active = True if not self.active else False

    def on_active(self, instance_check, active_value: bool) -> None:
        if active_value:
            self.do_animation_check((0, 0, 0, 0.4), 1)
        else:
            self.do_animation_check((0, 0, 0, 0), 0)

    def do_animation_check(self, md_bg_color: list, scale_value: int) -> None:
        Animation(md_bg_color=md_bg_color, t="out_sine", d=0.1).start(
            self.ids.icon_left_box
        )
        Animation(
            scale_value_x=scale_value,
            scale_value_y=scale_value,
            scale_value_z=scale_value,
            t="out_sine",
            d=0.1,
        ).start(self.ids.check_icon)

        if not self.icon_left:
            if scale_value:
                self.ids.check_icon.x = -dp(4)
                Animation(size=(dp(24), dp(24)), t="out_sine", d=0.1).start(
                    self.ids.relative_box
                )
            else:
                self.ids.check_icon.x = 0
                Animation(size=(0, 0), t="out_sine", d=0.1).start(
                    self.ids.relative_box
                )

    def on_press(self, *args):
        if self.active:
            self.active = False


class MDScalableCheckIcon(MDIcon, ScaleBehavior):
    pos_hint = {"center_y": 0.5}


if __name__ == "__main__":
    from kivymd.app import MDApp
    from kivymd.uix.screen import MDScreen

    KV = """
<MyScreen>

    MDBoxLayout:
        orientation: "vertical"
        adaptive_size: True
        spacing: "12dp"
        padding: "56dp"
        pos_hint: {"center_x": .5, "center_y": .5}

        MDLabel:
            text: "Multiple choose"
            bold: True
            font_style: "H5"
            adaptive_size: True

        MDBoxLayout:
            id: chip_box
            adaptive_size: True
            spacing: "8dp"

            MyChip:
                text: "Elevator"
                on_press: if self.active: root.removes_marks_all_chips()

            MyChip:
                text: "Washer / Dryer"
                on_press: if self.active: root.removes_marks_all_chips()

            MyChip:
                text: "Fireplace"
                on_press: if self.active: root.removes_marks_all_chips()

        MDSeparator:

        MDLabel:
            text: "Only choose"
            bold: True
            font_style: "H5"
            adaptive_size: True

        MDBoxLayout:
            id: chip_only_box
            adaptive_size: True
            spacing: "8dp"

            MyChip:
                text: "Elevator"
                on_active: if self.active: root.removes_marks_all_chips(self, False)

            MyChip:
                text: "Washer / Dryer"
                on_active: if self.active: root.removes_marks_all_chips(self, False)

            MyChip:
                text: "Fireplace"
                on_active: if self.active: root.removes_marks_all_chips(self, False)


ScreenManager:

    MyScreen:
    """

    class MyChip(MDChip):
        icon_check_color = (0, 0, 0, 1)
        text_color = (0, 0, 0, 0.5)
        _no_ripple_effect = True

        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            self.bind(active=self.set_chip_bg_color)
            self.bind(active=self.set_chip_text_color)

        def set_chip_bg_color(self, instance_chip, active_value: int):
            """
            Will be called every time the chip is activated/deactivated.
            Sets the background color of the chip.
            """

            self.md_bg_color = (
                (0, 0, 0, 0.4)
                if active_value
                else (
                    self.theme_cls.bg_darkest
                    if self.theme_cls.theme_style == "Light"
                    else (
                        self.theme_cls.bg_light
                        if not self.disabled
                        else self.theme_cls.disabled_hint_text_color
                    )
                )
            )

        def set_chip_text_color(self, instance_chip, active_value: int):
            Animation(
                color=(0, 0, 0, 1) if active_value else (0, 0, 0, 0.5), d=0.2
            ).start(self.ids.label)

    class MyScreen(MDScreen):
        def removes_marks_all_chips(
            self, selected_instance_chip=None, multiple=True
        ):
            if multiple:
                for instance_chip in self.ids.chip_box.children:
                    if instance_chip.active:
                        instance_chip.active = False
            else:
                for instance_chip in self.ids.chip_only_box.children:
                    if instance_chip != selected_instance_chip:
                        instance_chip.active = False

    class Test(MDApp):
        def build(self):
            return Builder.load_string(KV)

    Test().run()
