# Copyright (c) 2020, NVIDIA CORPORATION.  All rights reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto.  Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#

from collections import OrderedDict
from .usd_property_widget import UsdPropertyUiEntry

stack = []


class Container:
    def __init__(self, hide_if_true=None, show_if_true=None):
        self._children = []
        self._container_name = ""
        self._collapsed = False
        self._is_visible = True
        if isinstance(hide_if_true, bool):
            self._is_visible = not hide_if_true
        if isinstance(show_if_true, bool):
            self._is_visible = show_if_true

    def __enter__(self):
        stack.append(self)

    def __exit__(self, exc_type, exc_value, tb):
        stack.pop()

    def add_child(self, item):
        self._children.append(item)

    def get_name(self):
        return self._container_name

    def get_collapsed(self):
        return self._collapsed
    
    def is_visible(self):
        return self._is_visible


class CustomLayoutProperty:
    def __init__(self, prop_name, display_name=None, build_fn=None, hide_if_true=None, show_if_true=None):
        self._prop_name = prop_name
        self._display_name = display_name
        self._build_fn = build_fn  # TODO
        self._is_visible = True
        if isinstance(hide_if_true, bool):
            self._is_visible = not hide_if_true
        if isinstance(show_if_true, bool):
            self._is_visible = show_if_true

        global stack
        stack[-1].add_child(self)

    def get_property_name(self):
        return self._prop_name

    def get_display_name(self):
        return self._display_name

    def get_build_fn(self):
        return self._build_fn

    def is_visible(self):
        return self._is_visible


class CustomLayoutGroup(Container):
    def __init__(self, container_name, collapsed=False, hide_if_true=None, show_if_true=None):
        super().__init__(hide_if_true=hide_if_true, show_if_true=show_if_true)
        self._container_name = container_name
        self._collapsed = collapsed

        global stack
        stack[-1].add_child(self)


class CustomLayoutFrame(Container):
    def __init__(self, hide_extra=False):
        super().__init__()
        self._hide_extra = hide_extra

    def apply(self, props):
        customized_props = []
        # preprocess to speed up lookup
        props_dict = OrderedDict()
        for prop in props:
            props_dict[prop[0]] = prop
        self._process_container(self, props_dict, customized_props, "")

        # add the remaining
        if not self._hide_extra:
            for prop in props_dict.values():
                customized_props.append(prop)

        return customized_props

    def _process_container(self, container, props_dict, customized_props, group_name):
        for child in container._children:
            if isinstance(child, Container):
                if child.is_visible():
                    prefix = group_name + f":{child.get_name()}" if group_name else child.get_name()
                    self._process_container(child, props_dict, customized_props, prefix)
            elif isinstance(child, CustomLayoutProperty):
                if child.is_visible():
                    prop_name = child.get_property_name()
                    collapsed = container.get_collapsed()
                    prop = props_dict.pop(prop_name, None)  # get and remove
                    if prop:
                        if group_name != "":
                            prop.override_display_group(group_name, collapsed)
                        display_name = child.get_display_name()
                        if display_name:
                            prop.override_display_name(display_name)
                        prop.build_fn = child.get_build_fn()
                        customized_props.append(prop)
                    elif child.get_build_fn():
                        prop = UsdPropertyUiEntry("", group_name, "", None, child.get_build_fn(), collapsed)
                        customized_props.append(prop)
