__copyright__ = "Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved."
__license__ = """
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 os
import pathlib
import platform
import sys
import time
import unittest

from . import tc_logger


def setUpModule():
    # pre-load USD before anything else to prevent crash
    # from weird carb conflict
    # FIXME ^^^
    try:
        from . import update_path_and_load_usd

        update_path_and_load_usd()
    except ImportError:
        # not needed in Kit
        pass


try:
    import omni.kit.test

    TestClass = omni.kit.test.AsyncTestCase
    TEST_DIR = str(pathlib.Path(__file__).parent.parent.parent.parent)
except ImportError:
    from . import TestRtScenegraph

    TestClass = TestRtScenegraph
    TEST_DIR = "."


class TestRtBoundable(TestClass):
    @tc_logger
    def test_ctor(self):
        from usdrt import Gf, Rt, Sdf, Usd

        stage = Usd.Stage.Open(TEST_DIR + "/data/usd/tests/cornell.usda")
        self.assertTrue(stage)

        prim = stage.GetPrimAtPath(Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/White_Wall_Back"))
        self.assertTrue(prim)

        boundable = Rt.Boundable(prim)
        self.assertTrue(boundable)

        empty = Rt.Boundable()
        self.assertFalse(empty)

    @tc_logger
    def test_get_prim(self):
        from usdrt import Gf, Rt, Sdf, Usd

        stage = Usd.Stage.Open(TEST_DIR + "/data/usd/tests/cornell.usda")
        self.assertTrue(stage)

        prim = stage.GetPrimAtPath(Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/White_Wall_Back"))
        self.assertTrue(prim)

        boundable = Rt.Boundable(prim)
        self.assertTrue(boundable)

        check_prim = boundable.GetPrim()

        self.assertEqual(prim.GetPath(), check_prim.GetPath())

    @tc_logger
    def test_get_path(self):
        from usdrt import Gf, Rt, Sdf, Usd

        stage = Usd.Stage.Open(TEST_DIR + "/data/usd/tests/cornell.usda")
        self.assertTrue(stage)

        prim = stage.GetPrimAtPath(Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/White_Wall_Back"))
        self.assertTrue(prim)

        boundable = Rt.Boundable(prim)
        self.assertTrue(boundable)

        self.assertEqual(prim.GetPath(), boundable.GetPath())

    @tc_logger
    def test_world_extent(self):
        from usdrt import Gf, Rt, Sdf, Usd

        stage = Usd.Stage.Open(TEST_DIR + "/data/usd/tests/cornell.usda")
        self.assertTrue(stage)

        prim = stage.GetPrimAtPath(Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/White_Wall_Back"))
        self.assertTrue(prim)

        boundable = Rt.Boundable(prim)
        self.assertTrue(boundable)

        extent = Gf.Range3d(Gf.Vec3d(-10, -10, -10), Gf.Vec3d(10, 10, 10))
        attr = boundable.CreateWorldExtentAttr(extent)
        self.assertTrue(attr)

        attr = boundable.GetWorldExtentAttr()
        self.assertTrue(attr)

        world_ext = attr.Get()
        self.assertEqual(extent, world_ext)

    @tc_logger
    def test_has_world_extent(self):
        from usdrt import Gf, Rt, Sdf, Usd

        stage = Usd.Stage.Open(TEST_DIR + "/data/usd/tests/cornell.usda")
        self.assertTrue(stage)

        prim = stage.GetPrimAtPath(Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/White_Wall_Back"))
        self.assertTrue(prim)

        boundable = Rt.Boundable(prim)
        self.assertTrue(boundable)

        self.assertFalse(boundable.HasWorldExtent())

        extent = Gf.Range3d(Gf.Vec3d(-10, -10, -10), Gf.Vec3d(10, 10, 10))
        attr = boundable.CreateWorldExtentAttr(extent)
        self.assertTrue(attr)

        self.assertTrue(boundable.HasWorldExtent())

    @tc_logger
    def test_clear_world_extent(self):
        from usdrt import Gf, Rt, Sdf, Usd

        stage = Usd.Stage.Open(TEST_DIR + "/data/usd/tests/cornell.usda")
        self.assertTrue(stage)

        prim = stage.GetPrimAtPath(Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/White_Wall_Back"))
        self.assertTrue(prim)

        boundable = Rt.Boundable(prim)
        self.assertTrue(boundable)

        self.assertFalse(boundable.HasWorldXform())

        extent = Gf.Range3d(Gf.Vec3d(-10, -10, -10), Gf.Vec3d(10, 10, 10))
        attr = boundable.CreateWorldExtentAttr(extent)
        self.assertTrue(attr)

        self.assertTrue(boundable.HasWorldExtent())

        boundable.ClearWorldExtent()

        self.assertFalse(boundable.HasWorldExtent())

    @tc_logger
    def test_set_world_extent_from_usd(self):
        from usdrt import Gf, Rt, Sdf, Usd

        stage = Usd.Stage.Open(TEST_DIR + "/data/usd/tests/cornell.usda")
        self.assertTrue(stage)

        prim = stage.GetPrimAtPath(Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/White_Wall_Back"))
        self.assertTrue(prim)

        boundable = Rt.Boundable(prim)
        self.assertTrue(boundable)

        self.assertFalse(boundable.HasWorldExtent())

        self.assertTrue(boundable.SetWorldExtentFromUsd())

        self.assertTrue(boundable.HasWorldExtent())

        attr = boundable.GetWorldExtentAttr()
        self.assertTrue(attr)

        extent = attr.Get()
        expected = Gf.Range3d(Gf.Vec3d(247.11319, -249.90994, 0.0), Gf.Vec3d(247.11328, 249.91781, 500.0))

        self.assertTrue(Gf.IsClose(extent.GetMin(), expected.GetMin(), 0.001))
        self.assertTrue(Gf.IsClose(extent.GetMax(), expected.GetMax(), 0.001))

    @tc_logger
    def test_boundable_tokens(self):
        from usdrt import Rt

        self.assertEqual(Rt.Tokens.worldExtent, "_worldExtent")

    @tc_logger
    def test_repr_representation(self):
        from usdrt import Gf, Rt, Sdf, Usd

        stage = Usd.Stage.Open(TEST_DIR + "/data/usd/tests/cornell.usda")
        self.assertTrue(stage)

        prim = stage.GetPrimAtPath(Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/White_Wall_Back"))
        self.assertTrue(prim)

        boundable = Rt.Boundable(prim)
        expected = "Boundable(</Cornell_Box/Root/Cornell_Box1_LP/White_Wall_Back>)"

        self.assertEqual(repr(boundable), expected)
