import carb.settings
import omni.kit.app
from functools import partial
from ..preferences_window import PreferenceBuilder, PERSISTENT_SETTINGS_PREFIX, SettingType


class StagePreferences(PreferenceBuilder):
    def __init__(self):
        super().__init__("Stage")

        self._update_setting = {}

        settings = carb.settings.get_settings()

        if settings.get(PERSISTENT_SETTINGS_PREFIX + "/app/stage/timeCodeRange") is None:
            settings.set_float_array(PERSISTENT_SETTINGS_PREFIX + "/app/stage/timeCodeRange", [0, 100])

        if settings.get(PERSISTENT_SETTINGS_PREFIX + "/app/stage/timeCodesPerSecond") is None:
            settings.set_default_float(PERSISTENT_SETTINGS_PREFIX + "/app/stage/timeCodesPerSecond", 60.0)

        if settings.get(PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/PrimCreationWithDefaultXformOps") is None:
            settings.set_default_bool(
                PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/PrimCreationWithDefaultXformOps", True
            )

        if settings.get(PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/DefaultXformOpType") is None:
            settings.set_default_string(
                PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/DefaultXformOpType", "Scale, Rotate, Translate"
            )

        if settings.get(PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/DefaultRotationOrder") is None:
            settings.set_default_string(PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/DefaultRotationOrder", "XYZ")
        
        # OM-47905: Default camera rotation order should be YXZ.
        if settings.get(PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/DefaultCameraRotationOrder") is None:
            settings.set_default_string(PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/DefaultCameraRotationOrder", "YXZ")

        if settings.get(PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/DefaultXformOpOrder") is None:
            settings.set_default_string(
                PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/DefaultXformOpOrder",
                "xformOp:translate, xformOp:rotate, xformOp:scale",
            )

        if settings.get(PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/DefaultXformOpPrecision") is None:
            settings.set_default_string(
                PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/DefaultXformOpPrecision", "Double"
            )

        if settings.get(PERSISTENT_SETTINGS_PREFIX + "/app/stage/dragDropImport") is None:
            settings.set_default_string(
                PERSISTENT_SETTINGS_PREFIX + "/app/stage/dragDropImport", "payload"
            )
        
        if settings.get(PERSISTENT_SETTINGS_PREFIX + "/app/stage/nestedGprimsAuthoring") is None:
            settings.set_default_bool(
                PERSISTENT_SETTINGS_PREFIX + "/app/stage/nestedGprimsAuthoring", False
            )

        if settings.get(PERSISTENT_SETTINGS_PREFIX + "/app/stage/movePrimInPlace") is None:
            settings.set_default_bool(
                PERSISTENT_SETTINGS_PREFIX + "/app/stage/movePrimInPlace", True
            )
            
    def build(self):
        import omni.ui as ui

        """ New Stage """
        with ui.VStack(height=0):
            with self.add_frame("New Stage"):
                with ui.VStack():

                    self.create_setting_widget_combo(
                        "Default Up Axis", PERSISTENT_SETTINGS_PREFIX + "/app/stage/upAxis", ["Y", "Z"]
                    )

                    self.create_setting_widget(
                        "Default Animation Rate (TimeCodesPerSecond)",
                        PERSISTENT_SETTINGS_PREFIX + "/app/stage/timeCodesPerSecond",
                        SettingType.FLOAT
                    )

                    self.create_setting_widget(
                        "Default Meters Per Unit",
                        PERSISTENT_SETTINGS_PREFIX + "/simulation/defaultMetersPerUnit",
                        SettingType.FLOAT,
                        range_from=0.001,
                        range_to=1.0,
                        speed=0.001,
                        identifier="default_meters_per_unit"
                    )

                    self.create_setting_widget(
                        "Default Time Code Range",
                        PERSISTENT_SETTINGS_PREFIX + "/app/stage/timeCodeRange",
                        SettingType.DOUBLE2,
                    )
                    self.create_setting_widget(
                        "Default DefaultPrim Name",
                        PERSISTENT_SETTINGS_PREFIX + "/app/stage/defaultPrimName",
                        SettingType.STRING,
                    )
                    self.create_setting_widget_combo(
                        "Interpolation Type",
                        PERSISTENT_SETTINGS_PREFIX + "/app/stage/interpolationType",
                        ["Linear", "Held"],
                    )

                    self.create_setting_widget(
                        "Enable Static Material Network Topology",
                        "/omnihydra/staticMaterialNetworkTopology",
                        SettingType.BOOL,
                    )

                    self._create_prim_creation_settings_widgets()

            self.spacer()

            """ Authoring """
            with self.add_frame("Authoring"):
                with ui.VStack():
                    self.create_setting_widget(
                        "Keep Prim World Transfrom When Reparenting",
                        PERSISTENT_SETTINGS_PREFIX + "/app/stage/movePrimInPlace",
                        SettingType.BOOL,
                    )
                    self.create_setting_widget(
                        'Set "Instanceable" When Creating Reference',
                        PERSISTENT_SETTINGS_PREFIX + "/app/stage/instanceableOnCreatingReference",
                        SettingType.BOOL,
                    )
                    self.create_setting_widget(
                        "Transform Gizmo Manipulates Scale/Rotate/Translate Separately (New)",
                        PERSISTENT_SETTINGS_PREFIX + "/app/transform/gizmoUseSRT",
                        SettingType.BOOL,
                    )
                    self.create_setting_widget(
                        "Camera Controller Manipulates Scale/Rotate/Translate Separately (New)",
                        PERSISTENT_SETTINGS_PREFIX + "/app/camera/controllerUseSRT",
                        SettingType.BOOL,
                    )
                    self.create_setting_widget(
                        "Allow nested gprims authoring",
                        PERSISTENT_SETTINGS_PREFIX + "/app/stage/nestedGprimsAuthoring",
                        SettingType.BOOL,
                    )
                    
            self.spacer()

            """ Import """
            with self.add_frame("Import"):
                with ui.VStack():
                    self.create_setting_widget_combo(
                        "Drag & Drop USD Method",
                        PERSISTENT_SETTINGS_PREFIX + "/app/stage/dragDropImport",
                        ["payload", "reference"],
                    )

            self.spacer()

            """ Logging """
            with self.add_frame("Logging"):
                with ui.VStack():
                    self.create_setting_widget(
                        "Mute USD Coding Error from USD Diagnostic Manager",
                        PERSISTENT_SETTINGS_PREFIX + "/app/usd/muteUsdCodingError",
                        SettingType.BOOL,
                    )

            self.spacer()

            """ Compatibility """
            with self.add_frame("Compatibility"):
                with ui.VStack():
                    self.create_setting_widget(
                        "Support unprefixed UsdLux attributes (USD <= 20.11)",
                        PERSISTENT_SETTINGS_PREFIX + "/app/usd/usdLuxUnprefixedCompat",
                        SettingType.BOOL,
                    )

    def __del__(self):
        super().__del__()
        self._update_setting = {}

    def _create_prim_creation_settings_widgets(self):

        self.create_setting_widget(
            "Start with Transform Op on Prim Creation",
            PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/PrimCreationWithDefaultXformOps",
            SettingType.BOOL,
        )

        def _on_prim_creation_with_default_xform_ops_change(item, event_type, owner):
            if event_type == carb.settings.ChangeEventType.CHANGED:
                owner._update_prim_creation_with_default_xform_ops()

        self._update_setting["PrimCreationWithDefaultXformOps"] = omni.kit.app.SettingChangeSubscription(
            PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/PrimCreationWithDefaultXformOps",
            partial(_on_prim_creation_with_default_xform_ops_change, owner=self),
        )

        widget = self.create_setting_widget_combo(
            " Default Transform Op Type",
            PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/DefaultXformOpType",
            ["Scale, Rotate, Translate", "Scale, Orient, Translate", "Transform"],
        )

        def _on_default_xform_op_type_change(item, event_type, owner):
            if event_type == carb.settings.ChangeEventType.CHANGED:
                owner._update_prim_creation_with_default_xform_ops()

        self._update_setting["DefaultXformOpType"] = omni.kit.app.SettingChangeSubscription(
            PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/DefaultXformOpType",
            partial(_on_default_xform_op_type_change, owner=self),
        )
        self._widget_default_xform_op_type = widget

        widget = self.create_setting_widget_combo(
            " Default Camera Rotation Order",
            PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/DefaultCameraRotationOrder",
            ["XYZ", "XZY", "YZX", "YXZ", "ZXY", "ZYX"],
        )
        self._widget_default_camera_rotation_order = widget

        widget = self.create_setting_widget_combo(
            " Default Rotation Order",
            PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/DefaultRotationOrder",
            ["XYZ", "XZY", "YZX", "YXZ", "ZXY", "ZYX"],
        )
        self._widget_default_rotation_order = widget

        widget = self.create_setting_widget_combo(
            " Default Xform Op Order",
            PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/DefaultXformOpOrder",
            [
                "xformOp:translate, xformOp:rotate, xformOp:scale",
                "xformOp:translate, xformOp:orient, xformOp:scale",
                "xformOp:transform",
            ],
        )
        self._widget_default_xform_op_order = widget

        widget = self.create_setting_widget_combo(
            " Default Xform Precision",
            PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/DefaultXformOpPrecision",
            ["Float", "Double"],
        )
        self._widget_default_xform_op_precision = widget

        self._update_prim_creation_with_default_xform_ops()

    def _update_prim_creation_with_default_xform_ops(self):
        settings = carb.settings.get_settings()
        if settings.get_as_bool(PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/PrimCreationWithDefaultXformOps"):
            self._widget_default_xform_op_type.enabled = True
            default_xform_ops = settings.get_as_string(
                PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/DefaultXformOpType"
            )
            if default_xform_ops == "Scale, Orient, Translate":
                self._widget_default_rotation_order.enabled = False
                self._widget_default_camera_rotation_order.enabled = False
                settings.set_string(
                    PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/DefaultXformOpOrder",
                    "xformOp:translate, xformOp:orient, xformOp:scale",
                )
            elif default_xform_ops == "Transform":
                self._widget_default_rotation_order.enabled = False
                self._widget_default_camera_rotation_order.enabled = False
                settings.set_string(
                    PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/DefaultXformOpOrder", "xformOp:transform"
                )
            else:
                self._widget_default_rotation_order.enabled = True
                self._widget_default_camera_rotation_order.enabled = True
                settings.set_string(
                    PERSISTENT_SETTINGS_PREFIX + "/app/primCreation/DefaultXformOpOrder",
                    "xformOp:translate, xformOp:rotate, xformOp:scale",
                )

            self._widget_default_xform_op_order.enabled = False
            self._widget_default_xform_op_precision.enabled = True
        else:
            self._widget_default_xform_op_type.enabled = False
            self._widget_default_rotation_order.enabled = False
            self._widget_default_camera_rotation_order.enabled = False
            self._widget_default_xform_op_order.enabled = False
            self._widget_default_xform_op_precision.enabled = False
