import carb
import omni.kit.test
import omni.kit.helper.file_utils as file_utils

from omni.kit import ui_test
from .. import get_instance
from omni.kit.window.file_importer.test_helper import FileImporterTestHelper


class TestMenuFileRecents(omni.kit.test.AsyncTestCase):
    # Before running each test
    async def setUp(self):
        await omni.usd.get_context().new_stage_async()
        file_utils.reset_file_event_queue()

    # After running each test
    async def tearDown(self):
        await omni.usd.get_context().new_stage_async()
        file_utils.reset_file_event_queue()

    async def _mock_open_stage_async(self, url: str):
        # Doesn't actually open a stage but pushes an opened event like that action would.  This
        # should cause the file event queue to update.
        message_bus = omni.kit.app.get_app().get_message_bus_event_stream()
        message_bus.push(file_utils.FILE_OPENED_EVENT, payload=file_utils.FileEventModel(url=url).dict())
        await ui_test.human_delay(4)

    async def test_file_recent_menu(self):
        test_files = [
            "omniverse://ov-test/first.usda",
            "c:/users/me/second.usda",
            "omniverse://ov-test/third.usda",
        ]
        under_test = get_instance()
        get_recent_list = lambda: under_test._recent_menu_list[0].sub_menu

        # load first.usda file... rebuild_menu == 1
        await self._mock_open_stage_async(test_files[0])
        recent_list = get_recent_list()
        self.assertEqual(len(recent_list), 1)
        self.assertEqual(recent_list[0].name, test_files[0])

        # load second.usda file... rebuild_menu == 2
        await self._mock_open_stage_async(test_files[1])
        recent_list = get_recent_list()
        self.assertEqual(len(recent_list), 2)
        self.assertEqual(recent_list[0].name, test_files[1])

        # load second.usda file again... rebuild_menu still == 2
        await self._mock_open_stage_async(test_files[1])
        recent_list = get_recent_list()
        self.assertEqual(len(recent_list), 2)
        self.assertEqual(recent_list[0].name, test_files[1])

        # load third.usda ... rebuild_menu == 3
        await self._mock_open_stage_async(test_files[2])
        recent_list = get_recent_list()
        self.assertEqual(len(recent_list), 3)
        self.assertEqual(recent_list[0].name, test_files[2])

        # confirm list order is as expected
        expected = test_files[::-1]
        self.assertEqual([i.name for i in recent_list], expected)

async def test_file_recent_menu_current_stage(tester, _):
    under_test = get_instance()
    get_recent_list = lambda: under_test._recent_menu_list[0].sub_menu

    # verify recent == "None"
    recent_list = get_recent_list()
    tester.assertEqual(len(recent_list), 1)
    tester.assertTrue(recent_list[0].name.startswith("None"))

    await tester.reset_stage_event(omni.usd.StageEventType.OPENED)
    menu_widget = ui_test.get_menubar()
    await menu_widget.find_menu("File").click()
    await menu_widget.find_menu("Open").click()
    await ui_test.human_delay(5)

    async with FileImporterTestHelper() as file_import_helper:
        dir_url = carb.tokens.acquire_tokens_interface().resolve("${kit}/exts/omni.kit.menu.file/data/tests")
        await file_import_helper.click_apply_async(filename_url=f"{dir_url}/4Lights.usda")
        await tester.wait_for_stage_event()
    await ui_test.human_delay(5)

    # verify name of stage
    stage = omni.usd.get_context().get_stage()
    tester.assertTrue(stage.GetRootLayer().identifier.replace("\\", "/").endswith("data/tests/4Lights.usda"))

    # verify recent == "Current stage:" and "4Lights.usda"
    recent_list = get_recent_list()
    tester.assertEqual(len(recent_list), 2)

    tester.assertTrue(recent_list[0].name.startswith("Current stage:"))
    tester.assertTrue(recent_list[0].name.endswith("data/tests/4Lights.usda"))
    tester.assertFalse(recent_list[1].name.startswith("Current stage:"))
    tester.assertTrue(recent_list[1].name.endswith("data/tests/4Lights.usda"))

    await omni.usd.get_context().new_stage_async()
    await ui_test.human_delay(5)

    # verify recent == "4Lights.usda"
    recent_list = get_recent_list()
    tester.assertEqual(len(recent_list), 1)
    tester.assertFalse(recent_list[0].name.startswith("Current stage:"))
    tester.assertTrue(recent_list[0].name.endswith("data/tests/4Lights.usda"))
