from pathlib import Path

import omni.kit.ui_test as ui_test
from omni.ui.tests.test_base import OmniUiTest

from ..options_menu import OptionsMenu
from ..options_model import OptionsModel
from ..option_item import OptionItem, OptionSeparator

CURRENT_PATH = Path(__file__).parent.absolute()
TEST_DATA_PATH = CURRENT_PATH.parent.parent.parent.parent.parent.joinpath("data/tests")


class TestOptions(OmniUiTest):
    # Before running each test
    async def setUp(self):
        self._model = OptionsModel(
            "Filter",
            [
                OptionItem("audio", text="Audio"),
                OptionItem("materials", text="Materials"),
                OptionItem("scripts", text="Scripts"),
                OptionItem("textures", text="Textures"),
                OptionItem("usd", text="USD"),
            ]
        )

        self._golden_img_dir = TEST_DATA_PATH.absolute().joinpath("golden")

        await super().setUp()

    # After running each test
    async def tearDown(self):
        await super().tearDown()

    async def finalize_test(self, golden_img_name: str):
        await self.wait_n_updates()
        await super().finalize_test(golden_img_dir=self._golden_img_dir, golden_img_name=golden_img_name)
        await self.wait_n_updates()

    async def test_ui_layout(self):
        """Test ui, reset and API to get/set value"""
        items = self._model.get_item_children()
        self._changed_names = []

        def _on_item_changed(_, item: OptionItem):
            self._changed_names.append(item.name)

        self._sub = self._model.subscribe_item_changed_fn(_on_item_changed)

        menu = OptionsMenu(self._model)
        menu.show_at(0, 0)
        try:
            # Initial UI
            await ui_test.emulate_mouse_move(ui_test.Vec2(0, 0))
            await ui_test.human_delay()
            await self.finalize_test("options_menu.png")

            # Change first and last item via mouse click
            await ui_test.human_delay()
            await ui_test.emulate_mouse_move_and_click(ui_test.Vec2(50, 45))
            await ui_test.human_delay()
            await ui_test.emulate_mouse_move_and_click(ui_test.Vec2(50, 145))
            await ui_test.human_delay()
            self.assertEqual(len(self._changed_names), 2)
            self.assertEqual(self._changed_names[0], items[0].name)
            self.assertEqual(self._changed_names[1], items[-1].name)
            await self.finalize_test("options_menu_click.png")

            # Change value via item property
            items[2].value = not items[2].value
            items[3].value = not items[3].value
            await self.finalize_test("options_menu_value_changed.png")

            # Reset all
            await ui_test.emulate_mouse_move_and_click(ui_test.Vec2(120, 20))
            await self.finalize_test("options_menu.png")

        finally:
            menu.destroy()

    async def test_ui_rebuild_items(self):
        """Test ui, reset and API to get/set value"""
        items = self._model.get_item_children()
        
        menu = OptionsMenu(self._model)
        menu.show_at(0, 0)
        try:
            # Initial UI
            await ui_test.emulate_mouse_move(ui_test.Vec2(0, 0))
            await ui_test.human_delay()
            await self.finalize_test("options_menu.png")

            self._model.rebuild_items(
                [
                    OptionItem("Test"),
                    OptionSeparator(),
                    OptionItem("More"),
                ]
            )
            await ui_test.human_delay()
            await self.finalize_test("options_menu_rebuild.png")

            self._model.rebuild_items(items)
            await ui_test.human_delay()
            await self.finalize_test("options_menu.png")
        finally:
            menu.destroy()


