
__all__ = ["StyleTreeView"]

from typing import Dict, cast

from ..tree.inspector_tree import ICON_PATH
import omni.ui as ui
import omni.kit.app
import carb.events

from omni.ui_query import OmniUIQuery

from .style_model import StyleModel
from .style_delegate import StyleTreeDelegate
from .resolved_style import ResolvedStyleWidget
from .style_model import StyleEnumProperty, StyleColorProperties

import json
import omni.kit.clipboard


def int32_color_to_hex(value: int) -> str:
    # convert Value from int
    red = value & 255
    green = (value >> 8) & 255
    blue = (value >> 16) & 255
    alpha = (value >> 24) & 255

    def hex_value_only(value: int):
        hex_value = f"{value:#0{4}x}"
        return hex_value[2:].upper()

    hex_color = f"HEX<0x{hex_value_only(alpha)}{hex_value_only(blue)}{hex_value_only(green)}{hex_value_only(red)}>HEX"
    return hex_color


def int_enum_to_constant(value: int, key: str) -> str:
    result = ""
    if key == "corner_flag":
        enum = ui.CornerFlag(value)
        result = f"UI.CONSTANT<ui.CornerFlag.{enum.name}>UI.CONSTANT"
    elif key == "alignment":
        enum = ui.Alignment(value)
        result = f"UI.CONSTANT<ui.Alignment.{enum.name}>UI.CONSTANT"
    elif key == "fill_policy":
        enum = ui.FillPolicy(value)
        result = f"UI.CONSTANT<ui.FillPolicy.{enum.name}>UI.CONSTANT"
    elif key == "draw_mode":
        enum = ui.SliderDrawMode(value)
        result = f"UI.CONSTANT<ui.SliderDrawMode.{enum.name}>UI.CONSTANT"
    elif key == "stack_direction":
        enum = ui.Direction(value)
        result = f"UI.CONSTANT<ui.Direction.{enum.name}>UI.CONSTANT"

    return result


class StyleTreeView:
    """The Stage widget"""

    def __init__(self, **kwargs):
        self._widget = None
        self._model = StyleModel(self)
        self._delegate = StyleTreeDelegate(self._model)
        self._main_stack = ui.VStack()
        self._build_ui()

        app = omni.kit.app.get_app()
        self._update_sub = app.get_message_bus_event_stream().create_subscription_to_pop(
            self.on_selection_changed, name="Inspector Selection Changed"
        )

    def on_selection_changed(self, event: carb.events.IEvent):
        from ..inspector_widget import INSPECTOR_ITEM_SELECTED_ID

        if event.type == INSPECTOR_ITEM_SELECTED_ID:
            selection = OmniUIQuery.find_widget(event.payload["item_path"])
            if selection:
                self.set_widget(selection)

    def toggle_visibility(self):
        self._main_stack.visible = not self._main_stack.visible

    def set_widget(self, widget: ui.Widget):
        self._widget = widget
        # self._resolved_style.set_widget(widget)
        self._model.set_widget(widget)
        self._tree_view.set_expanded(None, True, True)

    def _build_ui(self):
        with self._main_stack:
            ui.Spacer(height=5)
            with ui.HStack(height=0):
                ui.Spacer(width=10)
                ui.Button(
                    image_url=f"{ICON_PATH}/copy.svg",
                    width=20,
                    height=20,
                    style={"margin": 0},
                    clicked_fn=self._copy_style,
                )
                ui.Label("Styles", height=0, style={"font_size": 16}, alignment=ui.Alignment.CENTER)
                ui.Button(
                    image_url=f"{ICON_PATH}/Add.svg",
                    style={"margin": 0},
                    height=20,
                    width=20,
                    clicked_fn=self._add_style,
                )
                ui.Spacer(width=10)

            ui.Spacer(height=3)
            ui.Line(height=1, style={"color": 0xFF222222, "border_width": 1})

            with ui.HStack():
                ui.Spacer(width=5)
                with ui.VStack():
                    # ResolvedStyleWidget: Omni.UI API is Broken
                    # self._resolved_style = ResolvedStyleWidget()
                    # ui.Spacer(height=10)

                    ui.Label("Local Styles", height=0)
                    with ui.ScrollingFrame(
                        horizontal_scrollbar_policy=ui.ScrollBarPolicy.SCROLLBAR_ALWAYS_OFF,
                        style_type_name_override="TreeView.ScrollingFrame",
                        style={"TreeView.ScrollingFrame": {"background_color": 0xFF333333}},
                    ):
                        self._tree_view = ui.TreeView(
                            self._model,
                            delegate=self._delegate,
                            column_widths=[ui.Fraction(1), 150],
                            header_visible=False,
                            root_visible=False,
                        )

                        self._tree_view.set_expanded(None, True, True)
                ui.Spacer(width=5)

    def _add_style(self):
        if not self._widget:
            return
        style = cast(dict, self._widget.style)
        if not style:
            style = {}
        style["color"] = 0xFF000000

        self._widget.set_style(style)
        self._model.update_cached_style()

    def _copy_style(self):
        if self._widget:
            style: Dict = cast(Dict, self._widget.style)
            if not style:
                style = {}
            has_type_names = False
            # convert numbers to
            for key, value in style.items():
                if type(value) == dict:
                    has_type_names = True
                    for name, internal_value in value.items():
                        if name in StyleColorProperties:
                            value[name] = int32_color_to_hex(internal_value)

                        if name in StyleEnumProperty:
                            value[name] = int_enum_to_constant(internal_value, name)
                else:
                    if key in StyleColorProperties:
                        style[key] = int32_color_to_hex(value)
                    if key in StyleEnumProperty:
                        style[key] = int_enum_to_constant(value, key)

            if has_type_names:
                style_json = json.dumps(style, indent=4)
            else:
                style_json = json.dumps(style)

            # remove HEX Markers
            style_json = style_json.replace('"HEX<', "")
            style_json = style_json.replace('>HEX"', "")

            # remove Constant Markers
            style_json = style_json.replace('"UI.CONSTANT<', "")
            style_json = style_json.replace('>UI.CONSTANT"', "")
            omni.kit.clipboard.copy(style_json)
