import carb.settings
import omni.kit.app
import omni.ui as ui
from ..preferences_window import PreferenceBuilder, PERSISTENT_SETTINGS_PREFIX, SettingType
from ..material_config_utils import SETTING_USERALLOWLIST, SETTING_USERBLOCKLIST
from ..material_config_widget import EditableListWidget
from ..material_path_widget import MdlDefaultPathListWidget
from ..material_path_widget import MdlLocalPathListWidget

class MaterialPreferences(PreferenceBuilder):
    def __init__(self):
        super().__init__("Material")

        settings = carb.settings.get_settings()
        self._sub_render_context = omni.kit.app.SettingChangeSubscription(
            PERSISTENT_SETTINGS_PREFIX + "/app/hydra/material/renderContext", self._on_render_context_changed
        )

        if settings.get(PERSISTENT_SETTINGS_PREFIX + "/app/material/dragDropMaterialPath") is None:
            settings.set_default_string(PERSISTENT_SETTINGS_PREFIX + "/app/material/dragDropMaterialPath", "Relative")

        if settings.get("/app/mdl/nostdpath") is None:
            settings.set_default_bool("/app/mdl/nostdpath", False)

        PreferenceBuilder.__init__(self, "Material")

    def build(self):
        """ Material """
        with ui.VStack(height=0):
            """ Material """
            with self.add_frame("Material"):
                with ui.VStack():
                    self.create_setting_widget_combo(
                        "Binding Strength",
                        PERSISTENT_SETTINGS_PREFIX + "/app/stage/materialStrength",
                        ["weakerThanDescendants", "strongerThanDescendants"],
                    )
                    self.create_setting_widget_combo(
                        "Drag/Drop Path",
                        PERSISTENT_SETTINGS_PREFIX + "/app/material/dragDropMaterialPath",
                        ["Absolute", "Relative"],
                    )
                    self.create_setting_widget_combo(
                        "Render Context / Material Network (Requires Stage Reload)",
                        PERSISTENT_SETTINGS_PREFIX + "/app/hydra/material/renderContext",
                        {"default": "", "mdl": "mdl"},
                    )

            self.spacer()

            """ Material Search Path """
            with self.add_frame("Material Search Path"):
                with ui.VStack(height=0):
                    """ Default Paths """
                    default_path_frame = self.add_frame("Default Paths")
                    # default_path_frame.collapsed = True
                    default_path_frame.collapsed = False
                    with default_path_frame:
                        with ui.VStack():
                            self.create_setting_widget(
                                "Ignore Standard Paths",
                                "/app/mdl/nostdpath",
                                SettingType.BOOL
                            )

                            self.spacer()

                            with ui.HStack():
                                ui.Spacer(width=5)
                                self._mdl_default_paths = MdlDefaultPathListWidget()

                    self.spacer()

                    """ Local  Paths """
                    with self.add_frame("Local Paths"):
                        self._mdl_local_paths = MdlLocalPathListWidget()
            
            self.spacer()

            """ Material Graph """
            if self._isExtensionEnabled("omni.kit.window.material_graph"):
                with self.add_frame("Material Graph"):
                    with ui.VStack(height=0):
                        """ User Allow List """
                        user_allow_list_frame = self.add_frame("User Allow List")
                        with user_allow_list_frame:
                            self._user_allow_list_widget = EditableListWidget(setting_path=SETTING_USERALLOWLIST)
                        
                        self.spacer()

                        """ User Block List """
                        user_block_list_frame = self.add_frame("User Block List")
                        with user_block_list_frame:
                            self._user_block_list_widget = EditableListWidget(setting_path=SETTING_USERBLOCKLIST)

    def _isExtensionEnabled(self, name):
        manager = omni.kit.app.get_app().get_extension_manager()
        for ext in manager.get_extensions():
            if ext["name"] == name and ext["enabled"] == True:
                return True
        
        return False

    def _on_render_context_changed(self, value: str, event_type: carb.settings.ChangeEventType):
        import omni.usd

        if event_type == carb.settings.ChangeEventType.CHANGED:
            stage = omni.usd.get_context().get_stage()
            if not stage or stage.GetRootLayer().anonymous:
                return

            msg = "Material render context has been changed. You will need to reload your stage for this to take effect."
            try:
                import asyncio
                import omni.kit.notification_manager
                import omni.kit.app

                async def show_msg():
                    await omni.kit.app.get_app().next_update_async()
                    omni.kit.notification_manager.post_notification(msg, hide_after_timeout=False)

                asyncio.ensure_future(show_msg())
            except:
                carb.log_warn(msg)
