#! /usr/bin/python3

import os, sys, logging, click

# Allow direct execution from the source tree by exposing both the repository
# root for `tests.*` imports and `src/` for `ffx.*` imports.
script_dir = os.path.dirname(os.path.abspath(__file__))
repo_root = os.path.dirname(script_dir)
src_root = os.path.join(repo_root, 'src')

sys.path = [p for p in sys.path if os.path.abspath(p) != script_dir]
for path in [repo_root, src_root]:
    if path not in sys.path:
        sys.path.insert(0, path)

existing_pythonpath = [p for p in os.environ.get('PYTHONPATH', '').split(os.pathsep) if p]
pythonpath_entries = []
for path in [src_root, repo_root] + existing_pythonpath:
    if path not in pythonpath_entries:
        pythonpath_entries.append(path)
os.environ['PYTHONPATH'] = os.pathsep.join(pythonpath_entries)

from ffx.configuration_controller import ConfigurationController

from ffx.file_properties import FileProperties
from ffx.ffx_controller import FfxController

from tests.legacy.helper import createMediaTestFile

from tests.legacy.scenario import Scenario
from ffx.tmdb_controller import TMDB_API_KEY_NOT_PRESENT_EXCEPTION


@click.group()
@click.pass_context
@click.option('-v', '--verbose', type=int, default=0, help='Set verbosity of output')
@click.option("--dry-run", is_flag=True, default=False)
def ffx(ctx, verbose, dry_run):
    """FFX"""

    ctx.obj = {}

    ctx.obj['config'] = ConfigurationController()

    ctx.obj['database'] = None
    ctx.obj['dry_run'] = dry_run

    ctx.obj['verbosity'] = verbose

    # Critical 50
    # Error 40
    # Warning 30
    # Info 20
    # Debug 10
    fileLogVerbosity = max(40 - verbose * 10, 10)
    consoleLogVerbosity = max(20 - verbose * 10, 10)

    ctx.obj['logger'] = logging.getLogger('FFX Tests')
    ctx.obj['logger'].setLevel(logging.DEBUG)

    ctx.obj['report_logger'] = logging.getLogger('FFX Test Result')
    ctx.obj['report_logger'].setLevel(logging.INFO)

    ffxFileHandler = logging.FileHandler(ctx.obj['config'].getLogFilePath())
    ffxFileHandler.setLevel(fileLogVerbosity)
    ffxConsoleHandler = logging.StreamHandler()
    ffxConsoleHandler.setLevel(consoleLogVerbosity)

    if os.path.isfile('ffx_test_report.log'):
        os.unlink('ffx_test_report.log')
    ffxTestReportFileHandler = logging.FileHandler('ffx_test_report.log')

    fileFormatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    ffxFileHandler.setFormatter(fileFormatter)
    consoleFormatter = logging.Formatter(
        '%(message)s')
    ffxConsoleHandler.setFormatter(consoleFormatter)
    reportFormatter = logging.Formatter(
        '%(message)s')
    ffxTestReportFileHandler.setFormatter(reportFormatter)

    ctx.obj['logger'].addHandler(ffxConsoleHandler)
    ctx.obj['logger'].addHandler(ffxFileHandler)

    ctx.obj['report_logger'].addHandler(ffxConsoleHandler)
    ctx.obj['report_logger'].addHandler(ffxTestReportFileHandler)
    

# Another subcommand
@ffx.command()
@click.pass_context
@click.option('--scenario', type=str, default='', help='Only run tests from this scenario')
@click.option('--variant', type=str, default='', help='Only run variants beginning like this')
@click.option('--limit', type=int, default=0, help='Only run this number of tests')
def run(ctx, scenario, variant, limit):
    """Run ffx test sequences"""

    ctx.obj['logger'].info('Starting FFX test runs')
    ctx.obj['test_passed_counter'] = 0
    ctx.obj['test_failed_counter'] = 0

    ctx.obj['test_variant'] = variant
    ctx.obj['test_limit'] = limit

    for si in Scenario.list():

        try:
            SCEN = Scenario.getClassReference(si)
            scen = SCEN(ctx.obj)

            if scenario and scenario != scen.getScenario():
                continue

            ctx.obj['logger'].debug(f"Running scenario {si}")

            scen.run()

        except TMDB_API_KEY_NOT_PRESENT_EXCEPTION:
            ctx.obj['logger'].info(f"TMDB_API_KEY not set: Skipping {SCEN.__class__.__name__}")    

    ctx.obj['logger'].info(f"\n{ctx.obj['test_passed_counter']} tests passed")
    ctx.obj['logger'].info(f"{ctx.obj['test_failed_counter']} test failed")
    ctx.obj['logger'].info('\nDone.')


@ffx.command()
@click.pass_context
@click.argument('paths', nargs=-1)
def dupe(ctx, paths):

    existingSourcePaths = [p for p in paths if os.path.isfile(p) and p.split('.')[-1] in FfxController.INPUT_FILE_EXTENSIONS]

    for sourcePath in existingSourcePaths:

        sourceFileProperties = FileProperties(ctx.obj, sourcePath)
        sourceMediaDescriptor = sourceFileProperties.getMediaDescriptor()

        createMediaTestFile(sourceMediaDescriptor, baseName='dupe')

if __name__ == '__main__':
    ffx()
