r"""
Installation requirements:
    pip install trame trame-vuetify pandas
"""

import pandas as pd

from trame.app import TrameApp
from trame.ui.vuetify3 import SinglePageLayout
from trame.widgets import html
from trame.widgets import vuetify3 as v3
from trame.decorators import change


class DataframeTable(TrameApp):
    def __init__(self, server=None):
        super().__init__(server)
        self.state.setdefault("active_ui", None)
        self.load_data()
        self.configure_table()
        self._build_ui()

    # --------------------------------------------------------------------------------
    # Loading dataframe
    # --------------------------------------------------------------------------------
    def load_data(self):
        data = [
            {
                "name": "Frozen Yogurt",
                "calories": 200,
                "fat": 6,
                "carbs": 24,
                "protein": 4,
                "iron": "1%",
                "glutenfree": True,
            },
            {
                "name": "Ice cream sandwich",
                "calories": 200,
                "fat": 9,
                "carbs": 37,
                "protein": 4.3,
                "iron": "1%",
                "glutenfree": False,
            },
            {
                "name": "Eclair",
                "calories": 300,
                "fat": 16,
                "carbs": 23,
                "protein": 6,
                "iron": "7%",
                "glutenfree": False,
            },
            {
                "name": "Cupcake",
                "calories": 300,
                "fat": 3.7,
                "carbs": 67,
                "protein": 4.3,
                "iron": "8%",
                "glutenfree": True,
            },
            {
                "name": "Gingerbread",
                "calories": 400,
                "fat": 16,
                "carbs": 49,
                "protein": 3.9,
                "iron": "16%",
                "glutenfree": True,
            },
            {
                "name": "Jelly bean",
                "calories": 400,
                "fat": 0,
                "carbs": 94,
                "protein": 0,
                "iron": "0%",
                "glutenfree": False,
            },
            {
                "name": "Lollipop",
                "calories": 400,
                "fat": 0.2,
                "carbs": 98,
                "protein": 0,
                "iron": "2%",
                "glutenfree": True,
            },
            {
                "name": "Honeycomb",
                "calories": 400,
                "fat": 3.2,
                "carbs": 87,
                "protein": 6.5,
                "iron": "45%",
                "glutenfree": True,
            },
            {
                "name": "Donut",
                "calories": 500,
                "fat": 25,
                "carbs": 51,
                "protein": 4.9,
                "iron": "22%",
                "glutenfree": True,
            },
            {
                "name": "KitKat",
                "calories": 500,
                "fat": 26,
                "carbs": 65,
                "protein": 7,
                "iron": "6%",
                "glutenfree": True,
            },
        ]

        self.frame = pd.DataFrame.from_dict(data)

    # --------------------------------------------------------------------------------
    # Configure table columns and options
    # --------------------------------------------------------------------------------

    def configure_table(self):
        # fmt: off
        self.headers = [
            {"key": "name", "title": "Dessert", "align": "start", "sortable": False},
            {"key": "calories", "title": "Calories"},
            {"key": "fat", "title": "Fat (g)"},
            {"key": "carbs", "title": "Carbs (g)"},
            {"key": "protein", "title": "Protein (g)"},
            {"key": "iron", "title": "Iron (%)"},
            {"key": "glutenfree", "title": "Gluten-Free"},
        ]

        self.state.setdefault("group_by", [{"key": "glutenfree", "order": "asc"}])

        # fmt: on
        _, self.rows = v3.dataframe_to_grid(self.frame)

        self.table = {
            "group_by": ("group_by",),
            "headers": ("headers", self.headers),
            "items": ("rows", self.rows),
            "search": ("query", ""),
            "classes": "elevation-1 ma-4",
            "multi_sort": True,
            "dense": True,
            "items_per_page": 10,
        }

    # --------------------------------------------------------------------------------
    # GUI
    # --------------------------------------------------------------------------------

    @change("rows")
    def update_values(self, rows, **kwargs):
        print("rows changed")

    def _build_ui(self):
        with SinglePageLayout(self.server) as self.ui:
            self.ui.title.set_text("Vuetify table example")
            with self.ui.toolbar:
                v3.VSpacer()
                v3.VTextField(
                    v_model=("query", ""),
                    placeholder="Search",
                    density="compact",
                    hide_details=True,
                )

            with self.ui.content:
                self.state.rows = self.rows
                with v3.VDataTable(**self.table):
                    with v3.Template(
                        v_slot_group_header="{ item, columns, toggleGroup, isGroupOpen }",
                    ):
                        with html.Tr():
                            with html.Td(colspan=("columns.length",)):
                                v3.VBtn(
                                    icon=("isGroupOpen(item) ? '$expand' : '$next'",),
                                    size="small",
                                    variant="text",
                                    click="toggleGroup(item)",
                                )
                                html.Span(
                                    "{{ item.value ?'Gluten free' : 'Contains gluten' }}"
                                )

                    with v3.Template(
                        calories="{ item }",
                        __properties=[
                            ("calories", "v-slot:item.calories"),
                        ],
                    ):
                        v3.VChip(
                            "{{ item.calories }}",
                            color=("item.color",),
                            dark=True,
                        )
                    with v3.Template(
                        glutenfree="{ item }",
                        __properties=[
                            ("glutenfree", "v-slot:item.glutenfree"),
                        ],
                    ):
                        v3.VCheckbox(
                            "{{ item.glutenfree }}",
                            v_model=("item.glutenfree",),
                            disabled=False,
                            input="flushState('rows')",
                        )


def main():
    dfTable = DataframeTable()
    dfTable.server.start()


if __name__ == "__main__":
    main()
