# Copyright (c) 2018-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 omni.ui as ui
import carb.settings

from omni.kit.widget.browser_bar import BrowserBar
from omni.kit.window.popup_dialog import InputDialog, MessageDialog, OptionsMenu, FormDialog
from omni.kit.widget.filebrowser import FileBrowserItem
from omni.kit.widget.search_delegate import SearchDelegate

from carb import log_warn
from .style import get_style, ICON_PATH


class ToolBar:
    SAVED_SETTINGS_OPTIONS_MENU = "/persistent/app/omniverse/filepicker/options_menu"

    def __init__(self, **kwargs):
        self._browser_bar: BrowserBar = None
        self._bookmark_button: ui.Button = None
        self._bookmarked: bool = False
        self._config_button: ui.Button = None
        self._config_menu: OptionsMenu = None

        self._current_directory_provider = kwargs.get("current_directory_provider", None)
        self._branching_options_handler = kwargs.get("branching_options_handler", None)
        self._apply_path_handler = kwargs.get("apply_path_handler", None)
        self._toggle_bookmark_handler = kwargs.get("toggle_bookmark_handler", None)
        self._config_values_changed_handler = kwargs.get("config_values_changed_handler", None)
        self._begin_edit_handler = kwargs.get("begin_edit_handler", None)
        self._prefix_separator = kwargs.get("prefix_separator", None)
        self._enable_soft_delete = kwargs.get("enable_soft_delete", False)
        self._search_delegate: SearchDelegate = kwargs.get("search_delegate", None)
        self._modal = kwargs.get("modal", False)
        self._build_ui()

    def _build_ui(self):
        with ui.HStack(height=0, style=get_style(), style_type_name_override="ToolBar"):
            with ui.ZStack():
                with ui.HStack():
                    ui.Spacer(width=48)
                    ui.Rectangle(style_type_name_override="ToolBar.Field")
                with ui.HStack():
                    with ui.VStack():
                        ui.Spacer()
                        self._browser_bar = BrowserBar(
                            visited_history_size=20,
                            branching_options_handler=self._branching_options_handler,
                            apply_path_handler=self._apply_path_handler,
                            prefix_separator=self._prefix_separator,
                            modal=self._modal,
                            begin_edit_handler=self._begin_edit_handler,
                        )
                        ui.Spacer()
                    with ui.VStack(width=20):
                        ui.Spacer()
                        self._bookmark_button = ui.Button(
                            image_url=f"{ICON_PATH}/bookmark_grey.svg",
                            image_width=18,
                            image_height=18,
                            height=18,
                            style_type_name_override="ToolBar.Button",
                            clicked_fn=lambda: self._on_toggle_bookmark(self._current_directory_provider()),
                        )
                        ui.Spacer()

            if self._search_delegate:
                ui.Spacer(width=2)
                with ui.HStack(width=300):
                    self._search_frame = ui.Frame()
                    with self._search_frame:
                        self._search_delegate.build_ui()

            self._build_widgets()

            with ui.VStack(width=24):
                ui.Spacer()
                self._config_button = ui.Button(
                    image_url=f"{ICON_PATH}/settings.svg",
                    image_width=14,
                    height=24,
                    style_type_name_override="ToolBar.Button",
                    identifier="settings_icon"
                )

                self._config_button.set_clicked_fn(
                    lambda: self._config_menu.show(parent=self._config_button, offset_x=-1, offset_y=24, recreate_window=True))
                ui.Spacer()

        self._build_config_menu()

    def _build_widgets(self):
        # For Content window to build filter button 
        pass

    def _build_config_menu(self):
        def on_value_changed(menu: OptionsMenu, _):
            carb.settings.get_settings().set(self.SAVED_SETTINGS_OPTIONS_MENU, menu.get_values())
            if self._config_values_changed_handler:
                self._config_values_changed_handler(menu.get_values())

        def get_default_value(name, default):
            menu_settings = carb.settings.get_settings().get_settings_dictionary(self.SAVED_SETTINGS_OPTIONS_MENU)
            if menu_settings and name in menu_settings:
                return menu_settings[name]
            return default

        field_defs = [
            OptionsMenu.FieldDef("hide_unknown", "Hide Unknown File Types", None, get_default_value("hide_unknown", False)),
            OptionsMenu.FieldDef("hide_thumbnails", "Hide Thumbnails Folders", None, get_default_value("hide_thumbnails", True)),
            OptionsMenu.FieldDef("show_details", "Show Details", None, get_default_value("show_details", False)),
            OptionsMenu.FieldDef("show_udim_sequence", "Display UDIM Sequence", None, get_default_value("show_udim_sequence", False)),
        ]
        if self._enable_soft_delete:
            field_defs.append(OptionsMenu.FieldDef("show_deleted", "Show Deleted", None, get_default_value("show_deleted", False)))
        self._config_menu = OptionsMenu(
            title="Options", field_defs=[i for i in field_defs if i is not None], width=220, value_changed_fn=on_value_changed
        )
        self._config_menu.hide()

    def _on_toggle_bookmark(self, item: FileBrowserItem):
        if not item:
            return

        def on_okay_clicked(dialog: InputDialog, item: FileBrowserItem, is_bookmark: bool):
            if self._toggle_bookmark_handler:
                if is_bookmark:
                    name = dialog.get_value("name")
                    url = dialog.get_value("address")
                else:
                    name = item.name
                    url = item.path
                self._toggle_bookmark_handler(name, url, is_bookmark, is_folder=item.is_folder)
            dialog.hide()

        if self._bookmarked:
            dialog = MessageDialog(
                title="Delete bookmark",
                width=400,
                message=f"Are you sure about deleting the bookmark '{item.path}'?",
                ok_handler=lambda dialog, item=item: on_okay_clicked(dialog, item, False),
                ok_label="Yes",
                cancel_label="No",
            )
        else:
            default_name = (item.path or "").rstrip("/").rsplit("/")[-1]
            field_defs = [
                FormDialog.FieldDef("name", "Name:  ", ui.StringField, default_name, True),
                FormDialog.FieldDef("address", "Address:  ", ui.StringField, item.path),
            ]
            dialog = FormDialog(
                title="Add bookmark",
                width=400,
                ok_handler=lambda dialog, item=item: on_okay_clicked(dialog, item, True),
                field_defs=field_defs,
            )
        dialog.show(offset_x=-1, offset_y=24, parent=self._bookmark_button)

    @property
    def config_values(self):
        if self._config_menu:
            return self._config_menu.get_values()
        else:
            return {}

    def set_config_value(self, name: str, value: bool):
        if self._config_menu:
            self._config_menu.set_value(name, value)

    @property
    def path(self) -> str:
        if self._browser_bar:
            return self._browser_bar.path
        return None

    def set_path(self, path: str):
        if self._browser_bar:
            self._browser_bar.set_path(path)
            path = self._browser_bar.path  # In case browser bar modifies the path str in any way
        if self._search_delegate:
            self._search_delegate.search_dir = path

    @property
    def bookmarked(self) -> bool:
        return self._bookmarked

    def set_bookmarked(self, true_false: bool):
        self._bookmarked = true_false
        if self._bookmarked:
            self._bookmark_button.image_url = f"{ICON_PATH}/bookmark.svg"
        else:
            self._bookmark_button.image_url = f"{ICON_PATH}/bookmark_grey.svg"

    def set_search_delegate(self, delegate: SearchDelegate):
        """
        Sets a custom search delegate for the tool bar.

        Args:
            delegate (:obj:`SearchDelegate`): Object that creates the search widget.

        """
        if delegate is None:
            self._search_frame.visible = False
        else:
            with self._search_frame:
                try:
                    delegate.build_ui()
                    delegate.search_dir = self._browser_bar.path if self._browser_bar else None
                    self._search_delegate = delegate
                    self._search_frame.visible = True
                except Exception:
                    log_warn("Failed to build search widget")

    def destroy(self):
        if self._browser_bar:
            self._browser_bar.destroy()
            self._browser_bar = None
        # NOTE: Dereference but do not call destroy on the search delegate because we don't own the object.
        self._search_delegate = None
        self._search_frame = None
        if self._config_menu:
            self._config_menu.destroy()
            self._config_menu = None
        self._config_button = None
        self._bookmark_button = None

        self._current_directory_provider = None
        self._branching_options_handler = None
        self._apply_path_handler = None
        self._toggle_bookmark_handler = None
        self._config_values_changed_handler = None
        self._begin_edit_handler = None
