#!/usr/bin/env python
import os
import yaml
import sys
from smolder import Charcoal
import logging
import argh
from yaml.parser import ParserError
from argh import arg, dispatch_command
import validictory
FORMAT = '%(asctime)-15s %(name)s [%(levelname)s]: %(message)s'
logging.basicConfig(format=FORMAT, level=logging.ERROR, datefmt="%Y-%m-%d %H:%M:%S")
LOG = logging.getLogger('smolder')
LOG.setLevel(logging.INFO)
PARSER = argh.ArghParser()
SCHEMA = {
    "type": "object",
    "properties": {
        "name": {
            "type": "string"
        },
        "uri": {
            "type": "string",
            "required": False
        },
        "port": {
            "type": "integer",
            "required": False
        },
        "inputs": {
            "type": "object",
            "required": False,
            "properties": {
                "headers": {"type": "any", "required": False},
                "username": {"type": "any", "required": False},
                "password": {"type": "any", "required": False},
                "cookie": {"type": "any", "required": False},
                "data": {"type": "any", "required": False},
                "file": {"type": "any", "required": False},
                "verify": {"type": "any", "required": False},
                "allow_redirects": {"type": "any", "required": False},
                "timeout": {"type": "any", "required": False},
                "proxies": {"type": "any", "required": False}
            }
        },
        "outcomes": {
            "type": "object",
            "required": False
        },
        "protocol": {
            "type": "string",
            "required": False,
            "enum": ["tcp", "http", "https"]
        },
        "method": {
            "type": "string",
            "required": False,
            "enum": ["GET", "get", "post", "POST", "put", "PUT", "delete", "DELETE", "option", "OPTION"]
        },
        "request_headers": {
            "type": "None",
            "required": False
        },
        "url": {
            "type": "None",
            "required": False
        }
    }
}


@dispatch_command
@arg('host', help='IP address or DNS name to run tests against', default=os.environ.get('TEST_HOST'))
@arg('testfile', default=os.environ.get('TEST_FILE'), metavar='TEST_FILE', nargs='?', help='The json file that details the tests to execute')
@arg('--force', help='Use http methods that can potentially change data (PUT, POST, DELETE, etc. ie !GET)', default=False)
def smolder_cli(**kwargs):
    """ Parse CLI args and if valid dispatch to lower methods """
    all_tests = []
    total_passed_tests = 0
    total_failed_tests = 0

    # Load the test specification file, parse the json and create a 'tests' object
    try:
        f = open(kwargs['testfile']) if kwargs['testfile'] else sys.stdin
        myfile = "".join(f.read())
        test_input = yaml.load(myfile)
        tests = test_input['tests']
        try:
            for test in tests:
                validictory.validate(test, SCHEMA)
            LOG.debug("Valid schema")
        except ValueError as error:
            LOG.error(
                "Error, invalid test: {0}.  Tests now use v0.2 format. v0.1 branch is still available.".format(error))
            sys.exit(7)
    except IOError:
        LOG.exception("Couldn't open test file %s", kwargs['testfile'])
        sys.exit(6)
    except yaml.parser.ParserError:
        LOG.exception("Invalid yaml in file %s", kwargs['testfile'])
        sys.exit(5)
    except ValueError:
        LOG.exception("Invalid data in file %s", kwargs['testfile'])
        sys.exit(4)
    except KeyError:
        LOG.exception("No tests defined in %s", kwargs['testfile'])
        sys.exit(3)
    except ParserError:
        LOG.exception("Invalid yaml in file %s", kwargs['testfile'])
        sys.exit(8)
    if len(tests) == 0:
        LOG.error("There are no tests configured in %s: You need at least one test", kwargs['testfile'])
        sys.exit(2)

    print("Preparing to execute {0} tests".format(len(tests)))
    # Iterate through all the tests

    for test in test_input['tests']:
        test_obj = Charcoal(test=test, host=kwargs['host'])

        print(str(test_obj))
        total_failed_tests += test_obj.failed
        total_passed_tests += test_obj.passed
        all_tests.append(test_obj)

    LOG.debug("Number of test objects: {0}".format(len(all_tests)))
    LOG.debug("failed: {0}, passed: {1}".format(total_failed_tests, total_passed_tests))
    if total_failed_tests > 0:
        print("FOUND {0} FAILURES IN {1} TESTS".format(str(total_failed_tests), str(total_passed_tests + total_failed_tests)))
        sys.exit(1)
    elif total_failed_tests == 0 and total_passed_tests == 0:
        print("No tests run: check plugins")
        sys.exit(3)
    else:
        print("ALL TESTS PASSED!")
