#!/usr/bin/env python3

import argparse
import signal
import sys
import tempfile
from logging import _nameToLevel as levelNames

from apifuzzer.fuzz_utils import get_api_definition_from_file, get_api_definition_from_url
from apifuzzer.fuzzer import Fuzzer
from apifuzzer.utils import json_data, str2bool
from apifuzzer.version import get_version

if __name__ == '__main__':

    def signal_handler(sig, frame):
        sys.exit(0)

    parser = argparse.ArgumentParser(description='APIFuzzer configuration')
    parser.add_argument('-s', '--src_file',
                        type=str,
                        required=False,
                        help='API definition file path. Currently only JSON format is supported',
                        dest='src_file')
    parser.add_argument('--src_url',
                        type=str,
                        required=False,
                        help='API definition url. Currently only JSON format is supported',
                        dest='src_url')
    parser.add_argument('-r', '--report_dir',
                        type=str,
                        required=False,
                        help='Directory where error reports will be saved. Default is temporally generated directory',
                        dest='report_dir',
                        default=tempfile.mkdtemp())
    parser.add_argument('--level',
                        type=int,
                        required=False,
                        help='Test deepness: [1,2], higher is the deeper !!!Not implemented!!!',
                        dest='level',
                        default=1)
    parser.add_argument('-u', '--url',
                        type=str,
                        required=False,
                        help='Use CLI defined url instead compile the url from the API definition. Useful for testing',
                        dest='alternate_url',
                        default=None)
    parser.add_argument('-t', '--test_report',
                        type=str,
                        required=False,
                        help='JUnit test result xml save path ',
                        dest='test_result_dst',
                        default=None)
    parser.add_argument('--log',
                        type=str,
                        required=False,
                        help='Use different log level than the default WARNING',
                        dest='log_level',
                        default='warning',
                        choices=[level.lower() for level in levelNames if isinstance(level, str)])
    parser.add_argument('--basic_output',
                        type=str2bool,
                        required=False,
                        help='Use basic output for logging (useful if running in jenkins). Example --basic_output=True',
                        dest='basic_output',
                        default=False)
    parser.add_argument('--headers',
                        type=json_data,
                        required=False,
                        help='Http request headers added to all request. Example: \'[{"Authorization": "SuperSecret"}, '
                             '{"Auth2": "asd"}]\'',
                        dest='headers',
                        default=None)
    parser.add_argument('-v ,--version',
                        action='version',
                        version=get_version())
    args = parser.parse_args()
    api_definition_json = dict()
    if args.src_file:
        api_definition_json = get_api_definition_from_file(args.src_file)
    elif args.src_url:
        api_definition_json = get_api_definition_from_url(args.src_url)
    else:
        argparse.ArgumentTypeError('No API definition source provided -s, --src_file or --src_url should be defined')
        exit()
    prog = Fuzzer(api_resources=api_definition_json,
                  report_dir=args.report_dir,
                  test_level=args.level,
                  alternate_url=args.alternate_url,
                  test_result_dst=args.test_result_dst,
                  log_level=args.log_level,
                  basic_output=args.basic_output,
                  auth_headers=args.headers,
                  api_definition_url=args.src_url,
                  junit_report_path=args.test_result_dst
                  )
    prog.prepare()
    signal.signal(signal.SIGINT, signal_handler)
    prog.run()
