import argparse

try:
    import pytest
except ImportError:
    pytest = None

from empyric.experiment import Manager


# List of testable features.
# Tests are invoked at the command line with `empyric --test <feature>`
testable_features = [
    'experiment',  # tests Variable, Experiment and Manager classes (default)
    'variable',  # tests Knob, Meter, Parameter and Expression

    # Adapters
    'serial',
    'gpib',
    'usb',
    'modbus',
    'phidget'
]


def execute():

    parser = argparse.ArgumentParser(
        description='Empyric Command Line Interface'
    )

    parser.add_argument(
        '-r', '--runcard', type=str, required=False, default=None,
        help="path of experiment runcard to execute"
    )

    parser.add_argument(
        '-d', '--directory', type=str, default=None,
        help='directory to write data and plots to'
    )

    parser.add_argument(
        '-t', '--test', nargs='*',
        help='test empyric installation and components'
    )

    args = parser.parse_args()

    if args.test is not None:

        if pytest is None:
            raise ImportError('pytest is not installed')

        if len(args.test) == 0:  # test main classes in experiment.py
            pytest.main(
                [
                    '-r', 'A', '--pyargs', 'empyric.tests',
                    '-k', 'test_experiment',
                    '-q'
                ]
            )

        elif all([feature in testable_features for feature in args.test]):
            # test specified features
            test_names = ['test_' + name for name in args.test]

            pytest.main(
                [
                    '-r', 'A', '--pyargs', 'empyric.tests',
                    '-k', ' or '.join(test_names),
                    '-q'
                ]
            )

        else:

            raise NotImplementedError(
                '\n' + '\n'.join(
                    [
                        f'Requested test of {feature} is not implemented'
                        for feature in args.test
                        if feature not in testable_features
                    ]
                )
            )
    else:
        manager = Manager(runcard=args.runcard)
        manager.run(directory=args.directory)
