import os, sys, click

from .scenario import Scenario

from .helper import createMediaTestFile
from ffx.process import executeProcess

from ffx.file_properties import FileProperties

from ffx.media_descriptor import MediaDescriptor
from ffx.track_descriptor import TrackDescriptor

from ffx.track_type import TrackType
from ffx.track_disposition import TrackDisposition

from .media_combinator import MediaCombinator


class Scenario2(Scenario):
    """Creating file VAa, h264/aac/aac
    Converting to VaA, vp9/opus/opus
    No tmdb, default parameters"""

    TEST_FILE_EXTENSION = 'mkv'
    EXPECTED_FILE_EXTENSION = 'webm'


    def __init__(self, context):

        context['use_tmdb'] = False
        context['use_pattern'] = False

        super().__init__(context)
        
    def getScenario(self):
        return self.__class__.__name__[8:]


    def job(self, yieldObj: dict):

        testContext = self._context.copy()

        targetYieldObj = yieldObj['target']
        # presetYieldObj = yieldObj['preset'] # not used here

        identifier = targetYieldObj['identifier']
        variantList = targetYieldObj['variants']

        variantIdentifier = '-'.join(variantList)
        variantLabel = f"{self.__class__.__name__} Variant {variantIdentifier}"

        sourceMediaDescriptor: MediaDescriptor = targetYieldObj['payload']

        assertSelectorList: list = targetYieldObj['assertSelectors']
        assertFuncList = targetYieldObj['assertFuncs']
        shouldFail = targetYieldObj['shouldFail']


        if self._context['test_variant'] and not variantIdentifier.startswith(self._context['test_variant']):
            return

        if (self._context['test_limit'] and (self._context['test_passed_counter'] + self._context['test_failed_counter'])
                    >= self._context['test_limit']):
            return

        self._logger.debug(f"Running Job: {variantLabel}")


        # Phase 1: Setup source files

        self.clearTestDirectory()
        mediaFilePath = createMediaTestFile(mediaDescriptor=sourceMediaDescriptor,
                                            directory=self._testDirectory,
                                            logger=self._logger,
                                            length = 2)


        # Phase 2: Run ffx

        commandSequence = [sys.executable, '-m', self._ffxModuleName]
        
        if self._context['verbosity']:
            commandSequence += ['--verbose',
                                str(self._context['verbosity'])]

        commandSequence += ['convert',
                            mediaFilePath,
                            '--no-prompt',
                            '--no-signature']

        out, err, rc = executeProcess(commandSequence, directory = self._testDirectory, context = self._context)

        if out and self._context['verbosity'] >= 9:
            self._logger.debug(f"{variantLabel}: Process output: {out}")
        if rc:
            self._logger.debug(f"{variantLabel}: Process returned ERROR {rc} ({err})")


        # Phase 3: Evaluate results

        resultFilenames = [rf for rf in self.getFilenamesInTestDirectory() if rf.endswith(f".{Scenario2.EXPECTED_FILE_EXTENSION}")]

        self._logger.debug(f"{variantLabel}: Result filenames: {resultFilenames}")

        try:

            jobFailed = bool(rc)
            self._logger.debug(f"{variantLabel}: Should fail: {shouldFail} / actually failed: {jobFailed}")

            assert (jobFailed == shouldFail
            ), f"Process {'failed' if jobFailed else 'did not fail'}"


            if not jobFailed:

                resultFile = os.path.join(self._testDirectory, 'media.webm')

                assert (os.path.isfile(resultFile)
                ), f"Result file 'media.webm' in path '{self._testDirectory}' wasn't created"

                resultFileProperties = FileProperties(testContext, resultFile)
                resultMediaDescriptor = resultFileProperties.getMediaDescriptor()

                # resultMediaTracks = resultMediaDescriptor.getAllTrackDescriptors()
                resultMediaTracks = resultMediaDescriptor.getTrackDescriptors()

                for assertIndex in range(len(assertSelectorList)):

                    assertSelector = assertSelectorList[assertIndex]
                    assertFunc = assertFuncList[assertIndex]
                    assertVariant = variantList[assertIndex]

                    if assertSelector == 'M':
                        assertFunc()
                        for variantIndex in range(len(assertVariant)):
                            assert (assertVariant[variantIndex].lower() == resultMediaTracks[variantIndex].getType().indicator()
                            ), f"Stream #{variantIndex} is not of type {resultMediaTracks[variantIndex].getType().label()}"

                    elif assertSelector == 'AD' or assertSelector == 'AT':
                        assertFunc({'tracks': resultMediaDescriptor.getAudioTracks()})

                    elif assertSelector == 'SD' or assertSelector == 'ST':
                        assertFunc({'tracks': resultMediaDescriptor.getSubtitleTracks()})

                    elif type(assertSelector) is str:
                        if assertSelector == 'J':
                            assertFunc()


            self._context['test_passed_counter'] += 1
            self._reportLogger.info(f"{variantLabel}: Test passed")

        except AssertionError as ae:

            self._context['test_failed_counter'] += 1
            self._reportLogger.error(f"{variantLabel}: Test FAILED ({ae})")


    def run(self):
        MC_list = MediaCombinator.getAllClassReferences()
        for MC in MC_list:
            self._logger.debug(f"MC={MC.__name__}")
            mc = MC(context = self._context)
            for y in mc.getYield():
                self.job(y)
