"""
Components/Pickers
==================

Includes date, time and color picker

`KivyMD` provides the following classes for use:

- MDTimePicker_
- MDDatePicker_
- MDThemePicker_

.. MDTimePicker:
MDTimePicker
------------

.. rubric:: Usage

.. code-block::

    from kivy.lang import Builder

    from kivymd.app import MDApp
    from kivymd.uix.picker import MDTimePicker

    KV = '''
    FloatLayout:

        MDRaisedButton:
            text: "Open time picker"
            pos_hint: {'center_x': .5, 'center_y': .5}
            on_release: app.show_time_picker()
    '''


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

        def show_time_picker(self):
            '''Open time picker dialog.'''

            time_dialog = MDTimePicker()
            time_dialog.open()


    Test().run()

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

Binding method returning set time
---------------------------------

.. code-block:: python

    def show_time_picker(self):
        time_dialog = MDTimePicker()
        time_dialog.bind(time=self.get_time)
        time_dialog.open()

    def get_time(self, instance, time):
        '''
        The method returns the set time.

        :type instance: <kivymd.uix.picker.MDTimePicker object>
        :type time: <class 'datetime.time'>
        '''

        return time

Open time dialog with the specified time
----------------------------------------

Use the :attr:`~MDTimePicker.set_time` method of the
:class:`~MDTimePicker.` class.

.. code-block:: python

    def show_time_picker(self):
        from datetime import datetime

        # Must be a datetime object
        previous_time = datetime.strptime("03:20:00", '%H:%M:%S').time()
        time_dialog = MDTimePicker()
        time_dialog.set_time(previous_time)
        time_dialog.open()

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

.. MDDatePicker:
MDDatePicker
------------

When creating an instance of the :class:`~MDDatePicker` class, you must pass
as a parameter a method that will take one argument - a ``datetime`` object.

.. code-block:: python

    def get_date(self, date):
        '''
        :type date: <class 'datetime.date'>
        '''

    def show_date_picker(self):
        date_dialog = MDDatePicker(callback=self.get_date)
        date_dialog.open()

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

Open date dialog with the specified date
----------------------------------------

.. code-block:: python

    def show_date_picker(self):
        date_dialog = MDDatePicker(
            callback=self.get_date,
            year=2010,
            month=2,
            day=12,
        )
        date_dialog.open()

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

You can set the time interval from and to the set date. All days of the week
that are not included in this range will have the status `disabled`.

.. code-block:: python

    def show_date_picker(self):
        min_date = datetime.strptime("2020:02:15", '%Y:%m:%d').date()
        max_date = datetime.strptime("2020:02:20", '%Y:%m:%d').date()
        date_dialog = MDDatePicker(
            callback=self.get_date,
            min_date=min_date,
            max_date=max_date,
        )
        date_dialog.open()

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

.. MDThemePicker:
MDThemePicker
-------------

.. code-block:: python

    def show_theme_picker(self):
        theme_dialog = MDThemePicker()
        theme_dialog.open()

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

__all__ = (
    "MDTimePicker",
    "MDDatePicker",
    "MDThemePicker",
)

import datetime
import calendar
from datetime import date

from kivy.lang import Builder
from kivy.uix.modalview import ModalView
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import (
    StringProperty,
    NumericProperty,
    ObjectProperty,
    BooleanProperty,
    ListProperty,
    OptionProperty,
)
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.behaviors import ButtonBehavior
from kivy.clock import Clock
from kivy.core.window import Window
from kivy.utils import get_color_from_hex

from kivymd.uix.label import MDLabel
from kivymd.uix.button import MDIconButton
from kivymd.theming import ThemableBehavior
from kivymd.uix.behaviors import (
    SpecificBackgroundColorBehavior,
    CircularRippleBehavior,
    RectangularElevationBehavior,
)
from kivymd.color_definitions import colors, palette

Builder.load_string(
    """
#:import calendar calendar
#:import platform platform


<MDDatePicker>
    cal_layout: cal_layout
    size_hint: (None, None)
    size:
        (dp(328), dp(484)) if self.theme_cls.device_orientation == 'portrait'\
        else (dp(512), dp(304))
    pos_hint: {'center_x': .5, 'center_y': .5}

    canvas:
        Color:
            rgb: app.theme_cls.primary_color
        Rectangle:
            size:
                (dp(328), dp(96))\
                if self.theme_cls.device_orientation == 'portrait'\
                else (dp(168), dp(304))
            pos:
                (root.pos[0], root.pos[1] + root.height - dp(96))\
                if self.theme_cls.device_orientation == 'portrait'\
                else (root.pos[0], root.pos[1] + root.height - dp(304))
        Color:
            rgb: app.theme_cls.bg_normal
        Rectangle:
            size:
                (dp(328), dp(484) - dp(96))\
                if self.theme_cls.device_orientation == 'portrait'\
                else [dp(344), dp(304)]
            pos:
                (root.pos[0], root.pos[1] + root.height - dp(96) - (dp(484) - dp(96)))\
                if self.theme_cls.device_orientation == 'portrait'\
                else (root.pos[0] + dp(168), root.pos[1])

    MDLabel:
        id: label_full_date
        font_style: 'H4'
        text_color: root.specific_text_color
        theme_text_color: 'Custom'
        size_hint: (None, None)
        size:
            (root.width, dp(30))\
            if root.theme_cls.device_orientation == 'portrait'\
            else (dp(168), dp(30))
        pos:
            (root.pos[0] + dp(23), root.pos[1] + root.height - dp(74))\
            if root.theme_cls.device_orientation == 'portrait'\
            else (root.pos[0] + dp(3), root.pos[1] + dp(214))
        line_height: .84
        valign: 'middle'
        text_size:
            (root.width, None)\
            if root.theme_cls.device_orientation == 'portrait'\
            else (dp(149), None)
        bold: True
        text:
            root.fmt_lbl_date(root.sel_year, root.sel_month, root.sel_day,\
            root.theme_cls.device_orientation)

    MDLabel:
        id: label_year
        font_style: 'Subtitle1'
        text_color: root.specific_text_color
        theme_text_color: 'Custom'
        size_hint: (None, None)
        size: root.width, dp(30)
        pos:
            (root.pos[0] + dp(23), root.pos[1] + root.height - dp(40))\
            if root.theme_cls.device_orientation == 'portrait'\
            else (root.pos[0] + dp(16), root.pos[1] + root.height - dp(41))
        valign: 'middle'
        text: str(root.sel_year)

    GridLayout:
        id: cal_layout
        cols: 7
        size:
            (dp(44 * 7), dp(40 * 7))\
            if root.theme_cls.device_orientation == 'portrait'\
            else (dp(46 * 7), dp(32 * 7))
        col_default_width:
            dp(42) if root.theme_cls.device_orientation == 'portrait'\
            else dp(39)
        size_hint: (None, None)
        padding:
            (dp(2), 0) if root.theme_cls.device_orientation == 'portrait'\
            else (dp(7), 0)
        spacing:
            (dp(2), 0) if root.theme_cls.device_orientation == 'portrait'\
            else (dp(7), 0)
        pos:
            (root.pos[0] + dp(10), root.pos[1] + dp(60))\
            if root.theme_cls.device_orientation == 'portrait'\
            else (root.pos[0] + dp(168) + dp(8), root.pos[1] + dp(48))

    MDLabel:
        id: label_month_selector
        font_style: 'Body2'
        text: calendar.month_name[root.month].capitalize() + ' ' + str(root.year)
        size_hint: (None, None)
        size: root.width, dp(30)
        pos: root.pos
        theme_text_color: 'Primary'
        pos_hint:
            {'center_x': .5, 'center_y': .75}\
            if self.theme_cls.device_orientation == 'portrait'\
            else {'center_x': .67, 'center_y': .915}
        valign: "middle"
        halign: "center"

    MDIconButton:
        icon: 'chevron-left'
        theme_text_color: 'Secondary'
        pos_hint:
            {'center_x': .08, 'center_y': .745}\
            if root.theme_cls.device_orientation == 'portrait'\
            else {'center_x': .39, 'center_y': .925}
        on_release: root.change_month('prev')

    MDIconButton:
        icon: 'chevron-right'
        theme_text_color: 'Secondary'
        pos_hint:
            {'center_x': .92, 'center_y': .745}\
            if root.theme_cls.device_orientation == 'portrait'\
            else {'center_x': .94, 'center_y': .925}
        on_release: root.change_month('next')

    MDFlatButton:
        width: dp(32)
        id: ok_button
        pos: root.pos[0] + root.size[0] - self.width - dp(10), root.pos[1] + dp(10)
        text: "OK"
        on_release: root.ok_click()

    MDFlatButton:
        id: cancel_button
        pos: root.pos[0] + root.size[0] - self.width - ok_button.width - dp(10), root.pos[1] + dp(10)
        text: "Cancel"
        on_release: root.dismiss()


<DayButton>
    size_hint: None, None
    size:
        (dp(40), dp(40)) if root.theme_cls.device_orientation == 'portrait'\
        else (dp(32), dp(32))

    MDLabel:
        font_style: 'Caption'
        theme_text_color: 'Custom' if root.is_today and not root.is_selected else 'Primary'
        text_color: root.theme_cls.primary_color
        opposite_colors:
            root.is_selected if root.owner.sel_month == root.owner.month\
            and root.owner.sel_year == root.owner.year\
            and str(self.text) == str(root.owner.sel_day) else False
        size_hint_x: None
        valign: 'middle'
        halign: 'center'
        text: root.text


<WeekdayLabel>
    font_style: 'Caption'
    theme_text_color: 'Secondary'
    size: (dp(40), dp(40)) if root.theme_cls.device_orientation == 'portrait'\
        else (dp(32), dp(32))
    size_hint: None, None
    text_size: self.size
    valign:
        'middle' if root.theme_cls.device_orientation == 'portrait'\
        else 'bottom'
    halign: 'center'


<DaySelector>
    size:
        (dp(40), dp(40)) if root.theme_cls.device_orientation == 'portrait'\
        else (dp(32), dp(32))
    size_hint: (None, None)

    canvas:
        Color:
            rgba: self.theme_cls.primary_color if self.shown else [0, 0, 0, 0]
        Ellipse:
            size:
                (dp(40), dp(40))\
                if root.theme_cls.device_orientation == 'portrait'\
                else (dp(32), dp(32))
            pos:
                self.pos if root.theme_cls.device_orientation == 'portrait'\
                else (self.pos[0], self.pos[1])
"""
)


class DaySelector(ThemableBehavior, AnchorLayout):
    shown = BooleanProperty(False)

    def __init__(self, parent):
        super().__init__()
        self.parent_class = parent
        self.parent_class.add_widget(self, index=7)
        self.selected_widget = None
        Window.bind(on_resize=self.move_resize)

    def update(self):
        parent = self.parent_class
        if parent.sel_month == parent.month and parent.sel_year == parent.year:
            self.shown = True
        else:
            self.shown = False

    def set_widget(self, widget):
        self.selected_widget = widget
        self.pos = widget.pos
        self.move_resize(do_again=True)
        self.update()

    def move_resize(self, window=None, width=None, height=None, do_again=True):
        self.pos = self.selected_widget.pos
        if do_again:
            Clock.schedule_once(
                lambda x: self.move_resize(do_again=False), 0.01
            )


class DayButton(
    ThemableBehavior, CircularRippleBehavior, ButtonBehavior, AnchorLayout
):
    text = StringProperty()
    owner = ObjectProperty()
    is_today = BooleanProperty(False)
    is_selected = BooleanProperty(False)

    def on_release(self):
        self.owner.set_selected_widget(self)


class WeekdayLabel(MDLabel):
    pass


class MDDatePicker(
    FloatLayout,
    ThemableBehavior,
    RectangularElevationBehavior,
    SpecificBackgroundColorBehavior,
    ModalView,
):
    _sel_day_widget = ObjectProperty()
    cal_list = None
    cal_layout = ObjectProperty()
    sel_year = NumericProperty()
    sel_month = NumericProperty()
    sel_day = NumericProperty()
    day = NumericProperty()
    month = NumericProperty()
    year = NumericProperty()
    today = date.today()
    callback = ObjectProperty()
    background_color = ListProperty([0, 0, 0, 0.7])

    class SetDateError(Exception):
        pass

    def __init__(
        self,
        callback,
        year=None,
        month=None,
        day=None,
        firstweekday=0,
        min_date=None,
        max_date=None,
        **kwargs,
    ):
        self.callback = callback
        self.cal = calendar.Calendar(firstweekday)
        self.sel_year = year if year else self.today.year
        self.sel_month = month if month else self.today.month
        self.sel_day = day if day else self.today.day
        self.month = self.sel_month
        self.year = self.sel_year
        self.day = self.sel_day
        self.min_date = min_date
        self.max_date = max_date
        super().__init__(**kwargs)
        self.selector = DaySelector(parent=self)
        self.generate_cal_widgets()
        self.update_cal_matrix(self.sel_year, self.sel_month)
        self.set_month_day(self.sel_day)
        self.selector.update()

    def ok_click(self):
        self.callback(date(self.sel_year, self.sel_month, self.sel_day))
        self.dismiss()

    def fmt_lbl_date(self, year, month, day, orientation):
        d = datetime.date(int(year), int(month), int(day))
        separator = "\n" if orientation == "landscape" else " "
        return (
            d.strftime("%a,").capitalize()
            + separator
            + d.strftime("%b").capitalize()
            + " "
            + str(day).lstrip("0")
        )

    def set_date(self, year, month, day):
        try:
            date(year, month, day)
        except Exception as e:
            if str(e) == "day is out of range for month":
                raise self.SetDateError(
                    " Day %s day is out of range for month %s" % (day, month)
                )
            elif str(e) == "month must be in 1..12":
                raise self.SetDateError(
                    "Month must be between 1 and 12, got %s" % month
                )
            elif str(e) == "year is out of range":
                raise self.SetDateError(
                    "Year must be between %s and %s, got %s"
                    % (datetime.MINYEAR, datetime.MAXYEAR, year)
                )
        else:
            self.sel_year = year
            self.sel_month = month
            self.sel_day = day
            self.month = self.sel_month
            self.year = self.sel_year
            self.day = self.sel_day
            self.update_cal_matrix(self.sel_year, self.sel_month)
            self.set_month_day(self.sel_day)
            self.selector.update()

    def set_selected_widget(self, widget):
        if self._sel_day_widget:
            self._sel_day_widget.is_selected = False
        widget.is_selected = True
        self.sel_month = int(self.month)
        self.sel_year = int(self.year)
        self.sel_day = int(widget.text)
        self._sel_day_widget = widget
        self.selector.set_widget(widget)

    def set_month_day(self, day):
        for idx in range(len(self.cal_list)):
            if str(day) == str(self.cal_list[idx].text):
                self._sel_day_widget = self.cal_list[idx]
                self.sel_day = int(self.cal_list[idx].text)
                if self._sel_day_widget:
                    self._sel_day_widget.is_selected = False
                self._sel_day_widget = self.cal_list[idx]
                self.cal_list[idx].is_selected = True
                self.selector.set_widget(self.cal_list[idx])

    def update_cal_matrix(self, year, month):
        try:
            dates = [x for x in self.cal.itermonthdates(year, month)]
        except ValueError as e:
            if str(e) == "year is out of range":
                pass
        else:
            self.year = year
            self.month = month
            for idx in range(len(self.cal_list)):
                if idx >= len(dates) or dates[idx].month != month:
                    self.cal_list[idx].disabled = True
                    self.cal_list[idx].text = ""
                else:
                    if self.min_date and self.max_date:
                        self.cal_list[idx].disabled = (
                            True
                            if (
                                dates[idx] < self.min_date
                                or dates[idx] > self.max_date
                            )
                            else False
                        )
                    elif self.min_date:
                        if isinstance(self.min_date, date):
                            self.cal_list[idx].disabled = (
                                True if dates[idx] < self.min_date else False
                            )
                        else:
                            raise ValueError(
                                "min_date must be of type {} or None, got {}".format(
                                    date, type(self.min_date)
                                )
                            )
                    elif self.max_date:
                        if isinstance(self.max_date, date):
                            self.cal_list[idx].disabled = (
                                True if dates[idx] > self.max_date else False
                            )
                        else:
                            raise ValueError(
                                "max_date must be of type {} or None, got {}".format(
                                    date, type(self.min_date)
                                )
                            )
                    else:
                        self.cal_list[idx].disabled = False
                    self.cal_list[idx].text = str(dates[idx].day)
                    self.cal_list[idx].is_today = dates[idx] == self.today
            self.selector.update()

    def generate_cal_widgets(self):
        cal_list = []
        for day in self.cal.iterweekdays():
            self.cal_layout.add_widget(
                WeekdayLabel(text=calendar.day_abbr[day][0].upper())
            )
        for i in range(6 * 7):  # 6 weeks, 7 days a week
            db = DayButton(owner=self)
            cal_list.append(db)
            self.cal_layout.add_widget(db)
        self.cal_list = cal_list

    def change_month(self, operation):
        op = 1 if operation is "next" else -1
        sl, sy = self.month, self.year
        m = 12 if sl + op == 0 else 1 if sl + op == 13 else sl + op
        y = sy - 1 if sl + op == 0 else sy + 1 if sl + op == 13 else sy
        self.update_cal_matrix(y, m)


Builder.load_string(
    """
#:import CircularTimePicker kivymd.vendor.circularTimePicker.CircularTimePicker
#:import dp kivy.metrics.dp


<MDTimePicker>
    size_hint: (None, None)
    size: (dp(270), dp(335) + dp(95))
    pos_hint: {'center_x': .5, 'center_y': .5}

    canvas:
        Color:
            rgba: self.theme_cls.bg_light
        Rectangle:
            size: (dp(270), dp(335))
            pos: (root.pos[0], root.pos[1] + root.height - dp(335) - dp(95))
        Color:
            rgba: self.theme_cls.primary_color
        Rectangle:
            size: (dp(270), dp(95))
            pos: (root.pos[0], root.pos[1] + root.height - dp(95))
        Color:
            rgba: self.theme_cls.bg_dark
        Ellipse:
            size: (dp(220), dp(220))
            pos:
                root.pos[0] + dp(270) / 2 - dp(220) / 2, root.pos[1]\
                + root.height - (dp(335) / 2 + dp(95)) - dp(220) / 2 + dp(35)

    CircularTimePicker:
        id: time_picker
        pos: (dp(270) / 2) - (self.width / 2), root.height - self.height
        size_hint: (.8, .8)
        pos_hint: {'center_x': .5, 'center_y': .585}

    MDFlatButton:
        width: dp(32)
        id: ok_button
        pos:
            root.pos[0] + root.size[0] - self.width - dp(10),\
            root.pos[1] + dp(10)
        text: "OK"
        on_release: root.close_ok()

    MDFlatButton:
        id: cancel_button
        pos:
            root.pos[0] + root.size[0] - self.width - ok_button.width\
            - dp(10), root.pos[1] + dp(10)
        text: "Cancel"
        on_release: root.close_cancel()
"""
)


class MDTimePicker(
    ThemableBehavior, FloatLayout, ModalView, RectangularElevationBehavior
):
    time = ObjectProperty()
    """
    Users method. Must take two parameters:

    .. code-block:: python

        def get_time(self, instance, time):
            '''
            The method returns the set time.

            :type instance: <kivymd.uix.picker.MDTimePicker object>
            :type time: <class 'datetime.time'>
            '''

            return time

    :attr:`time` is an :class:`~kivy.properties.ObjectProperty`
    and defaults to `None`.
    """

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.current_time = self.ids.time_picker.time

    def set_time(self, time):
        """
        Sets user time.

        :type time: <class 'datetime.time'>
        """

        try:
            self.ids.time_picker.set_time(time)
        except AttributeError:
            raise TypeError(
                "MDTimePicker._set_time must receive a datetime object, "
                'not a "' + type(time).__name__ + '"'
            )

    def close_cancel(self):
        self.dismiss()

    def close_ok(self):
        self.current_time = self.ids.time_picker.time
        self.time = self.current_time
        self.dismiss()


Builder.load_string(
    """
<Tab@BoxLayout+MDTabsBase>


<ColorSelector>
    size: dp(40), dp(40)
    pos: self.pos
    size_hint: (None, None)
    canvas:
        Color:
            rgba: root.rgb_hex(root.color_name)
        Ellipse:
            size: self.size
            pos: self.pos


<AccentColorSelector@ColorSelector>
    on_release: app.theme_cls.accent_palette = root.color_name


<PrimaryColorSelector@ColorSelector>
    on_release: app.theme_cls.primary_palette = root.color_name


<MDThemePicker>
    size_hint: (None, None)
    size: dp(284), dp(120) + dp(290)
    pos_hint: {'center_x': .5, 'center_y': .5}

    canvas:
        Color:
            rgb: app.theme_cls.primary_color
        Rectangle:
            size: self.width, dp(120)
            pos: root.pos[0], root.pos[1] + root.height - dp(120)
        Color:
            rgb: app.theme_cls.bg_normal
        Rectangle:
            size: self.width, dp(290)
            pos: root.pos[0], root.pos[1] + root.height - (dp(120) + dp(290))


    MDFlatButton:
        id: close_button
        pos: root.pos[0] + root.size[0] - self.width - dp(10), root.pos[1] + dp(10)
        text: "Close"
        on_release: root.dismiss()

    MDLabel:
        id: title
        font_style: "H5"
        text: "Change theme"
        size_hint: (None, None)
        size: dp(160), dp(50)
        pos_hint: {'center_x': .5, 'center_y': .9}
        theme_text_color: 'Custom'
        text_color: root.specific_text_color

    MDTabs:
        size_hint: (None, None)
        size: root.width, root.height - dp(135)
        pos_hint: {'center_x': .5, 'center_y': .475}
        id: tab_panel

        Tab:
            id: theme_tab
            text: "Theme"

            BoxLayout:
                spacing: dp(4)
                padding: dp(4)
                size_hint: (None, None)
                size: dp(270), root.height  # -dp(120)
                pos_hint: {'center_x': .532, 'center_y': .89}
                orientation: 'vertical'

                BoxLayout:
                    size_hint: (None, None)
                    pos_hint: {'center_x': .5, 'center_y': .5}
                    size: dp(230), dp(40)
                    pos: self.pos
                    halign: 'center'
                    orientation: 'horizontal'

                    BoxLayout:
                        PrimaryColorSelector:
                            color_name: 'Red'
                    BoxLayout:
                        PrimaryColorSelector:
                            color_name: 'Pink'
                    BoxLayout:
                        PrimaryColorSelector:
                            color_name: 'Purple'
                    BoxLayout:
                        PrimaryColorSelector:
                            color_name: 'DeepPurple'

                BoxLayout:
                    size_hint: (None, None)
                    pos_hint: {'center_x': .5, 'center_y': .5}
                    size: dp(230), dp(40)
                    pos: self.pos
                    halign: 'center'
                    orientation: 'horizontal'

                    BoxLayout:
                        PrimaryColorSelector:
                            color_name: 'Indigo'
                    BoxLayout:
                        PrimaryColorSelector:
                            color_name: 'Blue'
                    BoxLayout:
                        PrimaryColorSelector:
                            color_name: 'LightBlue'
                    BoxLayout:
                        PrimaryColorSelector:
                            color_name: 'Cyan'

                BoxLayout:
                    size_hint: (None, None)
                    pos_hint: {'center_x': .5, 'center_y': .5}
                    size: dp(230), dp(40)
                    pos: self.pos
                    halign: 'center'
                    orientation: 'horizontal'
                    padding: 0, 0, 0, dp(1)

                    BoxLayout:
                        PrimaryColorSelector:
                            color_name: 'Teal'
                    BoxLayout:
                        PrimaryColorSelector:
                            color_name: 'Green'
                    BoxLayout:
                        PrimaryColorSelector:
                            color_name: 'LightGreen'
                    BoxLayout:
                        PrimaryColorSelector:
                            color_name: 'Lime'

                BoxLayout:
                    size_hint: (None, None)
                    pos_hint: {'center_x': .5, 'center_y': .5}
                    size: dp(230), dp(40)
                    pos: self.pos
                    orientation: 'horizontal'
                    halign: 'center'
                    padding: 0, 0, 0, dp(1)

                    BoxLayout:
                        PrimaryColorSelector:
                            color_name: 'Yellow'
                    BoxLayout:
                        PrimaryColorSelector:
                            color_name: 'Amber'
                    BoxLayout:
                        PrimaryColorSelector:
                            color_name: 'Orange'
                    BoxLayout:
                        PrimaryColorSelector:
                            color_name: 'DeepOrange'

                BoxLayout:
                    size_hint: (None, None)
                    pos_hint: {'center_x': .5, 'center_y': .5}
                    size: dp(230), dp(40)
                    #pos: self.pos
                    orientation: 'horizontal'
                    padding: 0, 0, 0, dp(1)

                    BoxLayout:
                        PrimaryColorSelector:
                            color_name: 'Brown'
                    BoxLayout:
                        PrimaryColorSelector:
                            color_name: 'Gray'
                    BoxLayout:
                        PrimaryColorSelector:
                            color_name: 'BlueGray'
                    BoxLayout:
                        MDIconButton:
                            size: dp(40), dp(40)
                            size_hint: (None, None)
                            canvas:
                                Color:
                                    rgba: app.theme_cls.bg_normal
                                Ellipse:
                                    size: self.size
                                    pos: self.pos
                            disabled: True

        Tab:
            id: accent_tab
            text: "Accent"

            BoxLayout:
                spacing: dp(4)
                padding: dp(4)
                size_hint: (None, None)
                size: dp(270), root.height  # -dp(120)
                pos_hint: {'center_x': .532, 'center_y': .89}
                orientation: 'vertical'

                BoxLayout:
                    size_hint: (None, None)
                    pos_hint: {'center_x': .5, 'center_y': .5}
                    size: dp(230), dp(40)
                    pos: self.pos
                    halign: 'center'
                    orientation: 'horizontal'

                    BoxLayout:
                        AccentColorSelector:
                            color_name: 'Red'
                    BoxLayout:
                        AccentColorSelector:
                            color_name: 'Pink'
                    BoxLayout:
                        AccentColorSelector:
                            color_name: 'Purple'
                    BoxLayout:
                        AccentColorSelector:
                            color_name: 'DeepPurple'

                BoxLayout:
                    size_hint: (None, None)
                    pos_hint: {'center_x': .5, 'center_y': .5}
                    size: dp(230), dp(40)
                    pos: self.pos
                    halign: 'center'
                    orientation: 'horizontal'

                    BoxLayout:
                        AccentColorSelector:
                            color_name: 'Indigo'
                    BoxLayout:
                        AccentColorSelector:
                            color_name: 'Blue'
                    BoxLayout:
                        AccentColorSelector:
                            color_name: 'LightBlue'
                    BoxLayout:
                        AccentColorSelector:
                            color_name: 'Cyan'

                BoxLayout:
                    size_hint: (None, None)
                    pos_hint: {'center_x': .5, 'center_y': .5}
                    size: dp(230), dp(40)
                    pos: self.pos
                    halign: 'center'
                    orientation: 'horizontal'
                    padding: 0, 0, 0, dp(1)

                    BoxLayout:
                        AccentColorSelector:
                            color_name: 'Teal'
                    BoxLayout:
                        AccentColorSelector:
                            color_name: 'Green'
                    BoxLayout:
                        AccentColorSelector:
                            color_name: 'LightGreen'
                    BoxLayout:
                        AccentColorSelector:
                            color_name: 'Lime'

                BoxLayout:
                    size_hint: (None, None)
                    pos_hint: {'center_x': .5, 'center_y': .5}
                    size: dp(230), dp(40)
                    pos: self.pos
                    orientation: 'horizontal'
                    halign: 'center'
                    padding: 0, 0, 0, dp(1)

                    BoxLayout:
                        AccentColorSelector:
                            color_name: 'Yellow'
                    BoxLayout:
                        AccentColorSelector:
                            color_name: 'Amber'
                    BoxLayout:
                        AccentColorSelector:
                            color_name: 'Orange'
                    BoxLayout:
                        AccentColorSelector:
                            color_name: 'DeepOrange'

                BoxLayout:
                    size_hint: (None, None)
                    pos_hint: {'center_x': .5, 'center_y': .5}
                    size: dp(230), dp(40)
                    #pos: self.pos
                    orientation: 'horizontal'
                    padding: 0, 0, 0, dp(1)

                    BoxLayout:
                        AccentColorSelector:
                            color_name: 'Brown'
                    BoxLayout:
                        AccentColorSelector:
                            color_name: 'Gray'
                    BoxLayout:
                        AccentColorSelector:
                            color_name: 'BlueGray'
                    BoxLayout:
                        MDIconButton:
                            size: dp(40), dp(40)
                            size_hint: (None, None)
                            canvas:
                                Color:
                                    rgba: app.theme_cls.bg_normal
                                Ellipse:
                                    size: self.size
                                    pos: self.pos
                            disabled: True

        Tab:
            id: style_tab
            text: "Style"

            FloatLayout:
                size: self.size
                pos: self.pos

                BoxLayout:
                    size_hint: (None, None)
                    pos_hint: {'center_x': .5, 'center_y': .6}
                    halign: 'center'
                    valign: 'center'
                    spacing: dp(10)
                    width: dp(210)
                    height: dp(100)

                    MDIconButton:
                        size: dp(100), dp(100)
                        size_hint: (None, None)
                        canvas:
                            Color:
                                rgba: 1, 1, 1, 1
                            Ellipse:
                                size: self.size
                                pos: self.pos
                            Color:
                                rgba: 0, 0, 0, 1
                            Line:
                                width: 1.
                                circle: (self.center_x, self.center_y, dp(50))
                        on_release: app.theme_cls.theme_style = 'Light'
                    MDIconButton:
                        size: dp(100), dp(100)
                        pos: self.pos
                        size_hint: (None, None)
                        canvas:
                            Color:
                                rgba: 0, 0, 0, 1
                            Ellipse:
                                size: self.size
                                pos: self.pos
                        on_release: app.theme_cls.theme_style = 'Dark'
"""
)


class ColorSelector(MDIconButton):
    color_name = OptionProperty("Indigo", options=palette)

    def rgb_hex(self, col):
        return get_color_from_hex(colors[col][self.theme_cls.accent_hue])


class MDThemePicker(
    ThemableBehavior,
    FloatLayout,
    ModalView,
    SpecificBackgroundColorBehavior,
    RectangularElevationBehavior,
):
    pass
