## 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.kit.app
import omni.kit.test
import omni.ui as ui
import omni.usd
import omni.timeline
import carb.tokens
import carb.audio
from omni.ui.tests.test_base import OmniUiTest
from omni.kit import ui_test
#from omni.ui_query import OmniUIQuery

import pathlib
import asyncio
import tempfile
import os
import platform


class TestAudioRecorderWindow(OmniUiTest):  # pragma: no cover

    async def _dock_window(self, win):
        await self.docked_test_window(
            window=win._window,
            width=600,
            height=240)

    #def _dump_ui_tree(self, root):
    #    print("DUMP UI TREE START")
    #    #windows = omni.ui.Workspace.get_windows()
    #    #children = [windows[0].frame]
    #    children = [root.frame]

    #    print(str(dir(root.frame)))
    #    def recurse(children, path=""):
    #        for c in children:
    #            name = path + "/" + type(c).__name__
    #            print(name)
    #            if isinstance(c, omni.ui.ComboBox):
    #                print(str(dir(c)))

    #            recurse(omni.ui.Inspector.get_children(c), name)

    #    recurse(children)
    #    print("DUMP UI TREE END")

    # Before running each test
    async def setUp(self):
        await super().setUp()

        extension_path = carb.tokens.get_tokens_interface().resolve("${omni.kit.window.audiorecorder}")
        self._test_path = pathlib.Path(extension_path).joinpath("data").joinpath("tests").absolute()
        self._golden_img_dir = self._test_path.joinpath("golden")

        # open the dropdown
        window_menu = omni.kit.ui_test.get_menubar().find_menu("Window")
        self.assertIsNotNone(window_menu)
        await window_menu.click()

        # click the Audio Recorder entry to open it
        rec_menu = omni.kit.ui_test.get_menubar().find_menu("Audio Recorder")
        self.assertIsNotNone(rec_menu)
        await rec_menu.click()

        #self._dump_ui_tree(omni.kit.ui_test.find("Audio Recorder").window)

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

    async def _test_just_opened(self):
        win = omni.kit.ui_test.find("Audio Recorder")
        self.assertIsNotNone(win)

        await self._dock_window(win)
        await self.finalize_test(golden_img_dir=self._golden_img_dir, golden_img_name="test_just_opened.png")

    async def _test_recording(self):
        # wait for docking to finish. To prevent ui_test getting widgets as while window is being rebuilt
        await ui_test.human_delay(50)

        iface = carb.audio.acquire_data_interface()
        self.assertIsNotNone(iface)

        win = omni.kit.ui_test.find("Audio Recorder")
        self.assertIsNotNone(win)

        file_name_textbox = win.find("**/StringField[*]")
        self.assertIsNotNone(file_name_textbox)

        record_button = win.find("**/HStack[2]/Button[0]")
        self.assertIsNotNone(record_button)

        with tempfile.TemporaryDirectory() as temp_dir:
            path = os.path.join(temp_dir, "test.wav")

            # type our file path into the textbox
            await file_name_textbox.click()
            await file_name_textbox.input(str(path))

            # the user hit the record button
            await record_button.click()

            await asyncio.sleep(1.0)

            # change the text in the textbox so we'll have something constant
            # for the image comparison
            await file_name_textbox.input("soundstorm_song.wav")

            await self._dock_window(win)
            await self.finalize_test(golden_img_dir=self._golden_img_dir, golden_img_name="test_recording.png")

            # wait for docking to finish. To prevent ui_test getting widgets as while window is being rebuilt
            await ui_test.human_delay(50)

            # grab these again just in case window docking broke it
            win = omni.kit.ui_test.find("Audio Recorder")
            self.assertIsNotNone(win)

            record_button = win.find("**/HStack[2]/Button[0]")
            self.assertIsNotNone(record_button)

            # the user hit the stop button
            await record_button.click()

            await self._dock_window(win)
            await self.finalize_test(golden_img_dir=self._golden_img_dir, golden_img_name="test_stopped.png")

            # wait for docking to finish. To prevent ui_test getting widgets as while window is being rebuilt
            await ui_test.human_delay(50)

            # grab these again just in case window docking broke it
            win = omni.kit.ui_test.find("Audio Recorder")
            self.assertIsNotNone(win)

            file_name_textbox = win.find("**/StringField[*]")
            self.assertIsNotNone(file_name_textbox)

            record_button = win.find("**/HStack[2]/Button[0]")
            self.assertIsNotNone(record_button)

            format_combobox = win.find("**/ComboBox[*]")
            self.assertIsNotNone(format_combobox)

            # analyze the data
            sound = iface.create_sound_from_file(path, streaming=True)
            self.assertIsNotNone(sound)

            fmt = sound.get_format()
            self.assertEqual(fmt.format, carb.audio.SampleFormat.PCM16)

            pcm = sound.get_buffer_as_int16()
            for i in range(len(pcm)):
                self.assertEqual(pcm[i], 0);

            sound = None # close it

            # try again with a different format

            # FIXME: We should not be manipulating the model directly, but ui_test
            #        doesn't have a way to find any of the box item to click on,
            #        and ComboBoxes don't respond to keyboard input either.
            format_combobox.model.set_value(carb.audio.SampleFormat.VORBIS)

            path2 = os.path.join(temp_dir, "test.oga")
            await file_name_textbox.input(str(path2))

            # the user hit the record button
            await record_button.click()

            await asyncio.sleep(1.0)

            # the user hit the stop button
            await record_button.click()

            # analyze the data
            sound = iface.create_sound_from_file(str(path2), streaming=True)
            self.assertIsNotNone(sound)

            fmt = sound.get_format()
            self.assertEqual(fmt.format, carb.audio.SampleFormat.VORBIS)

            pcm = sound.get_buffer_as_int16()
            for i in range(len(pcm)):
                self.assertEqual(pcm[i], 0);

            sound = None # close it


    async def test_all(self):
        await self._test_just_opened()
        await self._test_recording()
