#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
Validate a JSON file against its JSON schema.

SEE ALSO:
  * https://python-jsonschema.readthedocs.org/
  * https://python-jsonschema.readthedocs.org/en/latest/errors.html

REQUIRES:
  Python >= 2.6
  jsonschema >= 1.3.0
  argparse
"""

__author__  = "Jens Engel"
__version__ = "0.1.0"

from jsonschema import validate
import argparse
import os.path
import sys
import textwrap
try:
    import json
except ImportError:
    try:
        import simplejson as json
    except ImportError:
        sys.exit("REQUIRE: simplejson (which is not installed)")


# -----------------------------------------------------------------------------
# CONSTANTS:
# -----------------------------------------------------------------------------
HERE = os.path.dirname(__file__)
TOP  = os.path.normpath(os.path.join(HERE, ".."))
SCHEMA = os.path.join(TOP, "etc", "json", "behave.json-schema")


# -----------------------------------------------------------------------------
# FUNCTIONS:
# -----------------------------------------------------------------------------
def jsonschema_validate(filename, schema, encoding=None):
    f = open(filename, "r")
    contents = f.read()
    f.close()
    data = json.loads(contents, encoding=encoding)
    return validate(data, schema)


def main(args=None):
    """
    Validate JSON files against their JSON schema.
    NOTE: Behave's JSON-schema is used per default.

    SEE ALSO:
      * http://json-schema.org/
      * http://tools.ietf.org/html/draft-zyp-json-schema-04
    """
    if args is None:
        args = sys.argv[1:]
    default_schema = None
    if os.path.exists(SCHEMA):
        default_schema = SCHEMA

    parser = argparse.ArgumentParser(
                description=textwrap.dedent(main.__doc__),
                formatter_class=argparse.RawDescriptionHelpFormatter
    )
    parser.add_argument("-v", "--version",
                        action="version", version=__version__)
    parser.add_argument("-s", "--schema",
                        help="JSON schema to use.")
    parser.add_argument("-e", "--encoding",
                        help="Encoding for JSON/JSON schema.")
    parser.add_argument("files", nargs="+", metavar="JSON_FILE",
                        help="JSON file to check.")
    parser.set_defaults(
            schema=default_schema,
            encoding="UTF-8"
    )
    options = parser.parse_args(args)
    if not options.schema:
        parser.error("REQUIRE: JSON schema")
    elif not os.path.isfile(options.schema):
        parser.error("SCHEMA not found: %s" % options.schema)

    try:
        f = open(options.schema, "r")
        contents = f.read()
        f.close()
        schema = json.loads(contents, encoding=options.encoding)
    except Exception, e:
        msg = "ERROR: %s: %s (while loading schema)" % (e.__class__.__name__, e)
        sys.exit(msg)

    error_count = 0
    for filename in options.files:
        validated = True
        more_info = None
        try:
            print "validate:", filename, "...",
            jsonschema_validate(filename, schema, encoding=options.encoding)
        except Exception, e:
            more_info = "%s: %s" % (e.__class__.__name__, e)
            validated = False
            error_count += 1
        if validated:
            print "OK"
        else:
            print "FAILED\n\n%s" % more_info
    return error_count


# -----------------------------------------------------------------------------
# AUTO-MAIN
# -----------------------------------------------------------------------------
if __name__ == "__main__":
    sys.exit(main())
