# test case management tool - manual execution from testopia test cases
#
# Copyright (c) 2018, Intel Corporation.
#
# SPDX-License-Identifier: GPL-2.0-only
#

import argparse
import json
import os
import sys
import datetime
import re
import copy
from oeqa.core.runner import OETestResultJSONHelper


def load_json_file(f):
    with open(f, "r") as filedata:
        return json.load(filedata)

def write_json_file(f, json_data):
    os.makedirs(os.path.dirname(f), exist_ok=True)
    with open(f, 'w') as filedata:
        filedata.write(json.dumps(json_data, sort_keys=True, indent=4))

class ManualTestRunner(object):

    def _get_test_module(self, case_file):
        return os.path.basename(case_file).split('.')[0]

    def _get_input(self, config):
        while True:
            output = input('{} = '.format(config))
            if re.match('^[a-z0-9-.]+$', output):
                break
            print('Only lowercase alphanumeric, hyphen and dot are allowed. Please try again')
        return output

    def _get_available_config_options(self, config_options, test_module, target_config):
        avail_config_options = None
        if test_module in config_options:
            avail_config_options = config_options[test_module].get(target_config)
        return avail_config_options

    def _choose_config_option(self, options):
        while True:
            output = input('{} = '.format('Option index number'))
            if output in options:
                break
            print('Only integer index inputs from above available configuration options are allowed. Please try again.')
        return options[output]

    def _get_config(self, config_options, test_module):
        from oeqa.utils.metadata import get_layers
        from oeqa.utils.commands import get_bb_var
        from resulttool.resultutils import store_map

        layers = get_layers(get_bb_var('BBLAYERS'))
        configurations = {}
        configurations['LAYERS'] = layers
        configurations['STARTTIME'] = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
        configurations['TEST_TYPE'] = 'manual'
        configurations['TEST_MODULE'] = test_module

        extra_config = set(store_map['manual']) - set(configurations)
        for config in sorted(extra_config):
            avail_config_options = self._get_available_config_options(config_options, test_module, config)
            if avail_config_options:
                print('---------------------------------------------')
                print('These are available configuration #%s options:' % config)
                print('---------------------------------------------')
                for option, _ in sorted(avail_config_options.items(), key=lambda x: int(x[0])):
                    print('%s: %s' % (option, avail_config_options[option]))
                print('Please select configuration option, enter the integer index number.')
                value_conf = self._choose_config_option(avail_config_options)
                print('---------------------------------------------\n')
            else:
                print('---------------------------------------------')
                print('This is configuration #%s. Please provide configuration value(use "None" if not applicable).' % config)
                print('---------------------------------------------')
                value_conf = self._get_input('Configuration Value')
                print('---------------------------------------------\n')
            configurations[config] = value_conf
        return configurations

    def _execute_test_steps(self, case):
        test_result = {}
        print('------------------------------------------------------------------------')
        print('Executing test case: %s' % case['test']['@alias'])
        print('------------------------------------------------------------------------')
        print('You have total %s test steps to be executed.' % len(case['test']['execution']))
        print('------------------------------------------------------------------------\n')
        for step, _ in sorted(case['test']['execution'].items(), key=lambda x: int(x[0])):
            print('Step %s: %s' % (step, case['test']['execution'][step]['action']))
            expected_output = case['test']['execution'][step]['expected_results']
            if expected_output:
                print('Expected output: %s' % expected_output)
        while True:
            done = input('\nPlease provide test results: (P)assed/(F)ailed/(B)locked/(S)kipped? \n').lower()
            result_types = {'p':'PASSED',
                            'f':'FAILED',
                            'b':'BLOCKED',
                            's':'SKIPPED'}
            if done in result_types:
                for r in result_types:
                    if done == r:
                        res = result_types[r]
                        if res == 'FAILED':
                            log_input = input('\nPlease enter the error and the description of the log: (Ex:log:211 Error Bitbake)\n')
                            test_result.update({case['test']['@alias']: {'status': '%s' % res, 'log': '%s' % log_input}})
                        else:
                            test_result.update({case['test']['@alias']: {'status': '%s' % res}})
                break
            print('Invalid input!')
        return test_result

    def _get_write_dir(self):
        return os.environ['BUILDDIR'] + '/tmp/log/manual/'

    def run_test(self, case_file, config_options_file, testcase_config_file):
        test_module = self._get_test_module(case_file)
        cases = load_json_file(case_file)
        config_options = {}
        if config_options_file:
            config_options = load_json_file(config_options_file)
        configurations = self._get_config(config_options, test_module)
        result_id = 'manual_%s_%s' % (test_module, configurations['STARTTIME'])
        test_results = {}
        if testcase_config_file:
            test_case_config = load_json_file(testcase_config_file)
            test_case_to_execute = test_case_config['testcases']
            for case in copy.deepcopy(cases) :
                if case['test']['@alias'] not in test_case_to_execute:
                    cases.remove(case)

        print('\nTotal number of test cases in this test suite: %s\n' % len(cases))
        for c in cases:
            test_result = self._execute_test_steps(c)
            test_results.update(test_result)
        return configurations, result_id, self._get_write_dir(), test_results

    def _get_true_false_input(self, input_message):
        yes_list = ['Y', 'YES']
        no_list = ['N', 'NO']
        while True:
            more_config_option = input(input_message).upper()
            if more_config_option in yes_list or more_config_option in no_list:
                break
            print('Invalid input!')
        if more_config_option in no_list:
            return False
        return True

    def make_config_option_file(self, logger, case_file, config_options_file):
        config_options = {}
        if config_options_file:
            config_options = load_json_file(config_options_file)
        new_test_module = self._get_test_module(case_file)
        print('Creating configuration options file for test module: %s' % new_test_module)
        new_config_options = {}

        while True:
            config_name = input('\nPlease provide test configuration to create:\n').upper()
            new_config_options[config_name] = {}
            while True:
                config_value = self._get_input('Configuration possible option value')
                config_option_index = len(new_config_options[config_name]) + 1
                new_config_options[config_name][config_option_index] = config_value
                more_config_option = self._get_true_false_input('\nIs there more configuration option input: (Y)es/(N)o\n')
                if not more_config_option:
                    break
            more_config = self._get_true_false_input('\nIs there more configuration to create: (Y)es/(N)o\n')
            if not more_config:
                break

        if new_config_options:
            config_options[new_test_module] = new_config_options
        if not config_options_file:
            config_options_file = os.path.join(self._get_write_dir(), 'manual_config_options.json')
        write_json_file(config_options_file, config_options)
        logger.info('Configuration option file created at %s' % config_options_file)

def manualexecution(args, logger):
    testrunner = ManualTestRunner()
    if args.make_config_options_file:
        testrunner.make_config_option_file(logger, args.file, args.config_options_file)
        return 0
    configurations, result_id, write_dir, test_results = testrunner.run_test(args.file, args.config_options_file, args.testcase_config_file)
    resultjsonhelper = OETestResultJSONHelper()
    resultjsonhelper.dump_testresult_file(write_dir, configurations, result_id, test_results)
    return 0

def register_commands(subparsers):
    """Register subcommands from this plugin"""
    parser_build = subparsers.add_parser('manualexecution', help='helper script for results populating during manual test execution.',
                                         description='helper script for results populating during manual test execution. You can find manual test case JSON file in meta/lib/oeqa/manual/',
                                         group='manualexecution')
    parser_build.set_defaults(func=manualexecution)
    parser_build.add_argument('file', help='specify path to manual test case JSON file.Note: Please use \"\" to encapsulate the file path.')
    parser_build.add_argument('-c', '--config-options-file', default='',
                              help='the config options file to import and used as available configuration option selection or make config option file')
    parser_build.add_argument('-m', '--make-config-options-file', action='store_true',
                              help='make the configuration options file based on provided inputs')
    parser_build.add_argument('-t', '--testcase-config-file', default='',
                              help='the testcase configuration file to enable user to run a selected set of test case')