# 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.
#
from omni.kit.tagging import OmniKitTaggingDelegate, get_tagging_instance
from omni.kit.widget.filebrowser import ColumnItem
from omni.kit.widget.filebrowser import AbstractColumnDelegate
import asyncio
import carb
import functools
import omni.client
import omni.ui as ui
import traceback


def handle_exception(func):
    """
    Decorator to print exception in async functions
    """

    @functools.wraps(func)
    async def wrapper(*args, **kwargs):
        try:
            return await func(*args, **kwargs)
        except asyncio.CancelledError:
            pass
        except Exception as e:
            carb.log_error(f"Exception when async '{func}'")
            carb.log_error(f"{e}")
            carb.log_error(f"{traceback.format_exc()}")

    return wrapper


class TagsDelegate(AbstractColumnDelegate):
    """
    The object that adds the new column "Access" to fileblowser. The columns
    displays access flags.
    """

    @property
    def initial_width(self):
        """The width of the column"""
        return ui.Pixel(40)

    def build_header(self):
        """Build the header"""
        ui.Label("Tags", style_type_name_override="TreeView.Header")

    @handle_exception
    async def build_widget(self, item: ColumnItem):
        """
        Build the widget for the given item. Works inside Frame in async
        mode. Once the widget is created, it will replace the content of the
        frame. It allow to await something for a while and create the widget
        when the result is available.
        """

        tagging = get_tagging_instance()
        if tagging is None:
            carb.log_warn("Tagging client not found")
            return

        # sanitize relative item paths
        path = item.path.replace("/./", "/")
        results = await tagging.get_tags_async([path])
        if results is None:
            results = []

        ordered_tags = tagging.ordered_tag_list(results)
        tag_string = ", ".join(ordered_tags)
        tooltip_string = "\n".join(ordered_tags)

        ui.Label(tag_string, style_type_name_override="TreeView.Item", tooltip=tooltip_string)
