# Path: sismic/io/yaml.py
# def import_from_yaml(
#         text: str = None, filepath: str = None, *, ignore_schema: bool = False,
#         ignore_validation: bool = False) -> Statechart:
#     """
#     Import a statechart from a YAML representation (first argument) or a YAML file (filepath
#     argument).
# 
#     Unless specified, the structure contained in the YAML is validated against a predefined
#     schema (see *sismic.io.SCHEMA*), and the resulting statechart is validated using its
#     *validate()* method.
# 
#     :param text: A YAML text. If not provided, filepath argument has to be provided.
#     :param filepath: A path to a YAML file.
#     :param ignore_schema: set to *True* to disable yaml validation.
#     :param ignore_validation: set to *True* to disable statechart validation.
#     :return: a *Statechart* instance
#     """
#     if not text and not filepath:
#         raise TypeError(
#             'A YAML must be provided, either using first argument or filepath argument.')
#     elif text and filepath:
#         raise TypeError('Either provide first argument or filepath argument, not both.')
#     elif filepath:
#         with open(filepath, 'r') as f:
#             text = f.read()
# 
#     if yaml.version_info < (0, 15):
#         data = yaml.safe_load(text)  # type: dict
#     else:
#         yml = yaml.YAML(typ='safe', pure=True)
#         data = yml.load(text)
# 
#     if not ignore_schema:
#         try:
#             data = schema.Schema(SCHEMA.statechart).validate(data)
#         except schema.SchemaError as e:
#             raise StatechartError('YAML validation failed') from e
# 
#     sc = import_from_dict(data)
# 
#     if not ignore_validation:
#         sc.validate()
#     return sc
# 
# Path: sismic/bdd/wrappers.py
# def execute_bdd(statechart: Statechart,
#                 feature_filepaths: List[str],
#                 *,
#                 step_filepaths: List[str] = None,
#                 property_statecharts: List[Statechart] = None,
#                 interpreter_klass: Callable[[Statechart], Interpreter] = Interpreter,
#                 debug_on_error: bool = False,
#                 behave_parameters: List[str] = None) -> int:
#     """
#     Execute BDD tests for a statechart.
# 
#     :param statechart: statechart to test
#     :param feature_filepaths: list of filepaths to feature files.
#     :param step_filepaths: list of filepaths to step definitions.
#     :param property_statecharts: list of property statecharts
#     :param interpreter_klass: a callable that accepts a statechart and an optional clock
#         and returns an Interpreter
#     :param debug_on_error: set to True to drop to (i)pdb in case of error.
#     :param behave_parameters: additional CLI parameters used by Behave
#         (see http://behave.readthedocs.io/en/latest/behave.html#command-line-arguments)
#     :return: exit code of behave CLI.
#     """
#     # Default values
#     step_filepaths = step_filepaths if step_filepaths else []
#     property_statecharts = property_statecharts if property_statecharts else []
#     behave_parameters = behave_parameters if behave_parameters else []
# 
#     # If debug_on_error, disable captured stdout, otherwise it hangs
#     if debug_on_error and '--capture' not in behave_parameters:
#         behave_parameters.append('--no-capture')
# 
#     # Create temporary directory to put everything inside
#     with tempfile.TemporaryDirectory() as tempdir:
#         # Create configuration for Behave
#         config = Configuration(behave_parameters)
# 
#         # Paths to features
#         config.paths = feature_filepaths
# 
#         # Copy environment
#         with open(os.path.join(tempdir, 'environment.py'), 'w') as environment:
#             environment.write('from sismic.bdd.environment import *')
# 
#         # Path to environment
#         config.environment_file = os.path.join(tempdir, 'environment.py')
# 
#         # Add predefined steps
#         os.mkdir(os.path.join(tempdir, 'steps'))
#         with open(os.path.join(tempdir, 'steps', '__steps.py'), 'w') as step:
#             step.write('from sismic.bdd.steps import *')
# 
#         # Copy provided steps, if any
#         for step_filepath in step_filepaths:
#             shutil.copy(step_filepath, os.path.join(
#                 tempdir, 'steps', os.path.split(step_filepath)[-1]))
# 
#         # Path to steps
#         config.steps_dir = os.path.join(tempdir, 'steps')
# 
#         # Put statechart and properties in user data
#         config.update_userdata({
#             'statechart': statechart,
#             'interpreter_klass': interpreter_klass,
#             'property_statecharts': property_statecharts,
#             'debug_on_error': debug_on_error,
#         })
# 
#         # Run behave
#         return run_behave(config)


import argparse
import sys
from ..io import import_from_yaml
from .wrappers import execute_bdd



def cli(args=None) -> int:
    parser = argparse.ArgumentParser(
        prog='sismic-bdd',
        description='Command-line utility to execute Gherkin feature files using Behave.\n'
        'Extra parameters will be passed to Behave.')

    parser.add_argument('statechart', metavar='statechart', type=str,
                        help='A YAML file describing a statechart')
    parser.add_argument('--features', metavar='features', nargs='+', type=str, required=True,
                        help='A list of files containing features')
    parser.add_argument('--steps', metavar='steps', nargs='+', type=str,
                        help='A list of files containing steps implementation')
    parser.add_argument(
        '--properties', metavar='properties', nargs='+', type=str,
        help='A list of filepaths pointing to YAML property statecharts. They will be checked '
             'at runtime following a fail fast approach.')
    parser.add_argument(
        '--show-steps', action='store_true', default=False,
        help='Display a list of available steps (equivalent to Behave\'s --steps parameter')
    parser.add_argument('--debug-on-error', action='store_true', default=False,
                        help='Drop in a debugger in case of step failure (ipdb if available)')

    args, parameters = parser.parse_known_args(args)
    if args.show_steps:
        parameters.append('--steps')


# Path: sismic/io/yaml.py
# def import_from_yaml(
#         text: str = None, filepath: str = None, *, ignore_schema: bool = False,
#         ignore_validation: bool = False) -> Statechart:
#     """
#     Import a statechart from a YAML representation (first argument) or a YAML file (filepath
#     argument).
# 
#     Unless specified, the structure contained in the YAML is validated against a predefined
#     schema (see *sismic.io.SCHEMA*), and the resulting statechart is validated using its
#     *validate()* method.
# 
#     :param text: A YAML text. If not provided, filepath argument has to be provided.
#     :param filepath: A path to a YAML file.
#     :param ignore_schema: set to *True* to disable yaml validation.
#     :param ignore_validation: set to *True* to disable statechart validation.
#     :return: a *Statechart* instance
#     """
#     if not text and not filepath:
#         raise TypeError(
#             'A YAML must be provided, either using first argument or filepath argument.')
#     elif text and filepath:
#         raise TypeError('Either provide first argument or filepath argument, not both.')
#     elif filepath:
#         with open(filepath, 'r') as f:
#             text = f.read()
# 
#     if yaml.version_info < (0, 15):
#         data = yaml.safe_load(text)  # type: dict
#     else:
#         yml = yaml.YAML(typ='safe', pure=True)
#         data = yml.load(text)
# 
#     if not ignore_schema:
#         try:
#             data = schema.Schema(SCHEMA.statechart).validate(data)
#         except schema.SchemaError as e:
#             raise StatechartError('YAML validation failed') from e
# 
#     sc = import_from_dict(data)
# 
#     if not ignore_validation:
#         sc.validate()
#     return sc
# 
# Path: sismic/bdd/wrappers.py
# def execute_bdd(statechart: Statechart,
#                 feature_filepaths: List[str],
#                 *,
#                 step_filepaths: List[str] = None,
#                 property_statecharts: List[Statechart] = None,
#                 interpreter_klass: Callable[[Statechart], Interpreter] = Interpreter,
#                 debug_on_error: bool = False,
#                 behave_parameters: List[str] = None) -> int:
#     """
#     Execute BDD tests for a statechart.
# 
#     :param statechart: statechart to test
#     :param feature_filepaths: list of filepaths to feature files.
#     :param step_filepaths: list of filepaths to step definitions.
#     :param property_statecharts: list of property statecharts
#     :param interpreter_klass: a callable that accepts a statechart and an optional clock
#         and returns an Interpreter
#     :param debug_on_error: set to True to drop to (i)pdb in case of error.
#     :param behave_parameters: additional CLI parameters used by Behave
#         (see http://behave.readthedocs.io/en/latest/behave.html#command-line-arguments)
#     :return: exit code of behave CLI.
#     """
#     # Default values
#     step_filepaths = step_filepaths if step_filepaths else []
#     property_statecharts = property_statecharts if property_statecharts else []
#     behave_parameters = behave_parameters if behave_parameters else []
# 
#     # If debug_on_error, disable captured stdout, otherwise it hangs
#     if debug_on_error and '--capture' not in behave_parameters:
#         behave_parameters.append('--no-capture')
# 
#     # Create temporary directory to put everything inside
#     with tempfile.TemporaryDirectory() as tempdir:
#         # Create configuration for Behave
#         config = Configuration(behave_parameters)
# 
#         # Paths to features
#         config.paths = feature_filepaths
# 
#         # Copy environment
#         with open(os.path.join(tempdir, 'environment.py'), 'w') as environment:
#             environment.write('from sismic.bdd.environment import *')
# 
#         # Path to environment
#         config.environment_file = os.path.join(tempdir, 'environment.py')
# 
#         # Add predefined steps
#         os.mkdir(os.path.join(tempdir, 'steps'))
#         with open(os.path.join(tempdir, 'steps', '__steps.py'), 'w') as step:
#             step.write('from sismic.bdd.steps import *')
# 
#         # Copy provided steps, if any
#         for step_filepath in step_filepaths:
#             shutil.copy(step_filepath, os.path.join(
#                 tempdir, 'steps', os.path.split(step_filepath)[-1]))
# 
#         # Path to steps
#         config.steps_dir = os.path.join(tempdir, 'steps')
# 
#         # Put statechart and properties in user data
#         config.update_userdata({
#             'statechart': statechart,
#             'interpreter_klass': interpreter_klass,
#             'property_statecharts': property_statecharts,
#             'debug_on_error': debug_on_error,
#         })
# 
#         # Run behave
#         return run_behave(config)


# Path: sismic/bdd/__main__.py
import argparse
import sys
from ..io import import_from_yaml
from .wrappers import execute_bdd




def cli(args=None) -> int:
    parser = argparse.ArgumentParser(
        prog='sismic-bdd',
        description='Command-line utility to execute Gherkin feature files using Behave.\n'
        'Extra parameters will be passed to Behave.')

    parser.add_argument('statechart', metavar='statechart', type=str,
                        help='A YAML file describing a statechart')
    parser.add_argument('--features', metavar='features', nargs='+', type=str, required=True,
                        help='A list of files containing features')
    parser.add_argument('--steps', metavar='steps', nargs='+', type=str,
                        help='A list of files containing steps implementation')
    parser.add_argument(
        '--properties', metavar='properties', nargs='+', type=str,
        help='A list of filepaths pointing to YAML property statecharts. They will be checked '
             'at runtime following a fail fast approach.')
    parser.add_argument(
        '--show-steps', action='store_true', default=False,
        help='Display a list of available steps (equivalent to Behave\'s --steps parameter')
    parser.add_argument('--debug-on-error', action='store_true', default=False,
                        help='Drop in a debugger in case of step failure (ipdb if available)')

    args, parameters = parser.parse_known_args(args)
    if args.show_steps:
        parameters.append('--steps')


    statechart = import_from_yaml(filepath=args.statechart)