# Copyright (c) 2022, 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.graph.core as og

from . import UINodeCommon


class OgnReadWidgetProperty:
    @staticmethod
    def compute(db) -> bool:
        widget_path = db.inputs.widgetPath
        if not widget_path:
            widget_identifier = db.inputs.widgetIdentifier
            if not widget_identifier:
                db.log_warning("No widgetIdentifier or widgetPath provided.")
                return False

            widget = UINodeCommon.get_registered_widget(db.abi_context, widget_identifier)
            if not widget:
                db.log_warning(f"No widget with identifier '{widget_identifier}' found in this graph.")
                return False
        else:
            widget = UINodeCommon.find_widget_among_all_windows(widget_path)
            if not widget:
                db.log_warning(f"No widget found at path '{widget_path}'.")
                return False
            # For error messages only.
            widget_identifier = widget_path

        property_name = db.inputs.propertyName
        if not property_name:
            db.log_warning("No property provided.")
            return False

        if not hasattr(widget, property_name):
            db.log_error(f"Widget '{widget_identifier}' has no property '{property_name}'.")
            return False

        widget_summary = f"widget '{widget_identifier}' ({type(widget)})"
        callbacks = UINodeCommon.get_widget_callbacks(widget)
        if not callbacks:
            db.log_error(f"{widget_summary} is not supported by the ReadWidgetProperty node.")
            return False

        if not hasattr(callbacks, "get_property_names") or not callable(callbacks.get_property_names):
            db.log_error(f"No 'get_property_names' callback found for {widget_summary}")
            return False
        readable_props = callbacks.get_property_names(widget, False)
        if not readable_props or property_name not in readable_props:
            db.log_error(f"'{property_name}' is not a readable property of {widget_summary}")
            return False

        if not hasattr(callbacks, "resolve_output_property") or not callable(callbacks.resolve_output_property):
            db.log_error(f"No 'resolve_output_property' callback found for {widget_summary}")
            return False
        try:
            callbacks.resolve_output_property(widget, property_name, db.node.get_attribute("outputs:value"))
        except og.OmniGraphError as og_error:
            db.log_error(
                f"Could resolve outputs from '{property_name}' for {widget_summary}\n{og_error}", add_context=False
            )
            return False

        if not hasattr(callbacks, "get_property_value") or not callable(callbacks.get_property_value):
            db.log_error(f"No 'get_property_value' callback found for {widget_summary}")
            return False
        try:
            callbacks.get_property_value(widget, property_name, db.outputs.value)
        except og.OmniGraphError as og_error:
            db.log_error(f"Could not get value of '{property_name}' on {widget_summary}\n{og_error}", add_context=False)
            return False

        return True
