# 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.
#

import carb.events
import carb.settings
import carb.windowing

import omni.appwindow
import omni.ext
import omni.kit.app
import omni.usd

import time
import urllib.parse

main_window_title = None


def get_main_window_title():
    return main_window_title


class WindowTitle(omni.ext.IExt):
    def on_startup(self, ext_id):
        self._app_name = ""
        self._app_version = ""
        self._title = ""
        self._title_decor = ""
        self._full_title = ""
        self._listener = None

        self._app = omni.kit.app.get_app()

        # We don't have a way to acquire interface without throwing on missing implementation in Carbonite,
        # so for now we have to work this around with try/except block.
        try:
            self._windowing = carb.windowing.acquire_windowing_interface()
        except:
            self._windowing = None
        self._settings = carb.settings.get_settings()
        self._window = omni.appwindow.get_default_app_window().get_window()
        self._usd_context = omni.usd.get_context()

        self._stage_event_sub = self._usd_context.get_stage_event_stream().create_subscription_to_pop(
            self._on_stage_event, name="Window title bar"
        )
        if self._usd_context.get_stage_state() == omni.usd.StageState.OPENED:
            self._update_title()

        # default value
        self._app_name = self._settings.get("/app/window/title")
        self._app_version = self._app.get_build_version()
        self._apply()

        # Default polling interval is 500ms (or 0.5s)
        self._settings.set_default("/exts/omni.kit.window.title/pollIntervalMS", 500.0)
        self._poll_interval_s = self._settings.get("/exts/omni.kit.window.title/pollIntervalMS") / 1000.0

        global main_window_title
        main_window_title = self

    def on_shutdown(self):
        global main_window_title
        main_window_title = None
        self._stage_event_sub = None

    def set_app_name(self, name: str):
        """
        Sets app name on title bar. This is the first element on the title bar string.

        Args:
            name: app name to be set to.
        """
        if self._app_name != name:
            self._app_name = name
            self._apply()

    def set_app_version(self, version: str):
        """
        Sets app version on title bar. This is the second element on the title bar string, after app name.

        Args:
            version: app version to be set to.
        """
        if self._app_version != version:
            self._app_version = version
            self._apply()

    def set_title(self, title: str):
        """
        Sets title text on title bar. This is the third element on the title bar string, after app name and version.

        Args:
            title: app title to be set to.
        """
        # OM-64018: need to unquote the chars in the title string
        title = urllib.parse.unquote(title)
        if self._title != title:
            self._title = title
            self._apply()

    def set_title_decor(self, title_decor: str):
        """
        Sets title decor on title bar. This is at the end of the title string.

        Args:
            title_decor: title decor to be set to.
        """
        if self._title_decor != title_decor:
            self._title_decor = title_decor
            self._apply()

    def get_full_title(self):
        """
        Gets the full title.
        """
        return self._full_title

    def _apply(self):
        self._full_title = f"{self._app_name} {self._app_version}"
        if len(self._title) > 0:
            self._full_title += f" - {self._title}{self._title_decor}"
        if self._window is not None:
            self._windowing.set_window_title(self._window, self._full_title)

    def _on_stage_event(self, event: carb.events.IEvent):
        if event.type == int(omni.usd.StageEventType.OPENED):
            self._update_title()
        elif event.type == int(omni.usd.StageEventType.CLOSING):
            self._on_stage_closing()
        elif event.type == int(omni.usd.StageEventType.DIRTY_STATE_CHANGED):
            self._update_title()

    def set_title_url(self):
        title = "New Stage" if self._usd_context.is_new_stage() else self._usd_context.get_stage_url()
        if not self._usd_context.is_writable():
            title += " (read-only)"
        self.set_title(title)

    def _on_stage_closing(self):
        self.set_title("")
        self.set_title_decor("")

    def _update_title(self):
        self.set_title_url()
        dirty = self._usd_context.has_pending_edit()
        if dirty and self._title_decor != "*":
            self.set_title_decor("*")
        elif not dirty and self._title_decor == "*":
            self.set_title_decor("")
