#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: ai ts=4 sts=4 et sw=4
# Written by Alan Viars  - This software is public domain

import json, sys

from pdt.pjson.validate_basic import validate_basic_dict
from pdt.pjson.validate_addresses import validate_address_list
from pdt.pjson.validate_licenses import validate_license_list
from pdt.pjson.validate_taxonomies import validate_taxonomy_list
from pdt.pjson.validate_identifiers import validate_identifier_list
from pdt.pjson.validate_other_names import validate_other_name_list
from pdt.pjson.validate_affiliations import validate_affiliation_list

# from validate_basic import validate_basic_dict
# from validate_addresses import validate_address_list
# from validate_licenses import validate_license_list
# from validate_taxonomies import validate_taxonomy_list
# from validate_identifiers import validate_identifier_list
# from validate_other_names import validate_other_name_list
# from validate_affiliations import validate_affiliation_list

def validate_pjson(j, action):
    """
    Input a JSON object and an action. return a list of errors. If error list
    is empty then the file is valid.
    """
    action = action.lower()

    errors =[]
    warnings =[]
    response = { "errors": [], "warnings": [] }


    #Check the action
    if action not in ("create", "update"):
        error ="action must be either create or update."
        errors.append(error)


    # Does the string contain JSON
    try:
        d = json.loads(j)
    except:
        error ="The string did not contain valid JSON."
        errors.append(error)
        response["errors"] = errors
        return response

    # Is it a dict {} (JSON object equiv)?
    if type(d)!=type({}):
        error ="The JSON string did not contain a JSON object i.e. {}."
        errors.append(error)
        response["errors"] = errors
        return response

    # Does it contain the top-level enumeration_type
    if not d.has_key("enumeration_type"):
        error ="The JSON object does not contain an enumeration_type."
        errors.append(error)
        response["errors"] = errors
        return response


    # Is the enumeration_type a valid?
    if d["enumeration_type"] not in ("NPI-1", "NPI-2", "OEID", "HPID"):
        error ="enumeration_type must be one of these: ('NPI-1', 'NPI-2', 'OEID', 'HPID')"
        errors.append(error)
        response["errors"] = errors
        return response

    #If a number is present we assume this is an update.
    if not d.has_key("number"):
        number = None
    else:
        number = d['number']

    if action=="create" and number:
        warning ="enumeration number is generated by CMS. The provided value will be ignored."
        warnings.append(warning)

    if action=="update" and not number:
        error ="enumeration number is required when performaing an update."
        errors.append(error)

    ## Sanity check epoch dates
    #if d.has_key("last_updated_epoch"):
    #    if type(d["last_updated_epoch"]) != type(1):
    #        warning ="last_updated_epoch is not an integer."
    #        warnings.append(warning)
    #else:
    #    warning ="last_updated_epoch is missing."
    #    warnings.append(warning)
    #
    #if d.has_key("created_epoch"):
    #    if type(d["created_epoch"]) != type(1):
    #        warning ="created_epoch is not an integer."
    #        warnings.append(warning)
    #else:
    #    warning ="created_date_epoch is missing."
    #    warnings.append(warning)


    #Check for errors in the basic section
    basic_errors, basic_warnings = validate_basic_dict(d.get('basic', {}),
                                                       d.get('enumeration_type'),
                                                       action, number)


    #Check for errors in the addresses
    address_errors = validate_address_list(d.get('addresses', ()), d.get('enumeration_type'))


    #Check for errors in the license section

    if d.has_key('licenses'):
        license_errors = validate_license_list(d.get('licenses', []),
                                            d.get('enumeration_type'))
    else:
        license_errors = []

    taxonomy_errors = validate_taxonomy_list(d.get('taxonomies',()),
                                             d.get('enumeration_type',()),
                        d.get('licenses', []), d.get('taxonomy_licenses', []),
                        d.get('basic', {}).get('sole_proprietor', "NO"))

    if d.has_key('identifiers'):
        identifier_errors = validate_identifier_list(d.get('identifiers',[]), d.get('enumeration_type'))
    else:
        identifier_errors = []


    if d.has_key('other_names'):
        other_names_errors = validate_other_name_list(d.get('other_names',[]),
                                                      d.get('enumeration_type'),
                                                      d.get('basic', {}))
    else:
        other_names_errors = []


    affiliation_errors, affiliation_warnings = validate_affiliation_list(d.get('affiliations',[]),
                                                      d.get('enumeration_type'))

    errors = errors + basic_errors + other_names_errors + address_errors + license_errors + \
                        taxonomy_errors + identifier_errors + affiliation_errors
    warnings = warnings + basic_warnings
    response["errors"] = errors
    response["warnings"] = warnings
    return response


if __name__ == "__main__":


    #Get the file from the command line
    if len(sys.argv)<3:
        print "You must supply a a ProviderJSON file to validate and an action"
        print "Usage: validate-pjson [ProivderJSON] [update|create]"
        sys.exit(1)
    else:
        pjson_file = sys.argv[1]
        action       = sys.argv[2]

    if action.lower() not in ("create", "update"):
        print "You must supply an action of either create or update."
        print "Usage: validate-pjson [ProivderJSON] [update|create]"
        sys.exit(1)

    #Try to open the file
    try:
        fh = open(pjson_file, 'r')

        j = fh.read()

        #Validate the provider JSON content
        errors = validate_pjson(j, action)
        #Print the erros and warings as JSON to stout.
        errors_json =  json.dumps(errors, indent =4)
        print errors_json
    except IOError:
        print "Could not open file %s." % (pjson_file)
        sys.exit(1)




