#!/usr/bin/env python

"""
usage: collect_schema_locations.py [-h] [-f] [-v] infilename [outfilename]

synopsis:
  collect schema locations from xs:include/xs:import elements in schema.

positional arguments:
  infilename     name/location of the XML schema file to be searched
  outfilename    output file name; if ommited stdout

optional arguments:
  -h, --help     show this help message and exit
  -f, --force    force overwrite existing output file
  -v, --verbose  print messages during actions.

examples:
  python collect_schema_locations.py myschema.xsd
  python collect_schema_locations.py myschema.xsd outfile.txt
"""


#
# imports
from __future__ import print_function
import sys
import os
import argparse
import json
from lxml import etree


#
# Global variables


#
# Private functions

def dbg_msg(options, msg):
    """Print a message if verbose is on."""
    if options['verbose']:
        print(msg)


def extract_locations(infile, options):
    doc = etree.parse(infile)
    root = doc.getroot()
    elements = root.xpath(
        './/xs:include | .//xs:import',
        namespaces=root.nsmap,
    )
    locations = []
    for element in elements:
        schema_name = element.get('schemaLocation')
        locations.append(schema_name)
    return locations


def generate(locations, outfile, options):
    directives = []
    for location in locations:
        schema_name = location
        outfilename = os.path.split(schema_name)[1]
        outfilename = os.path.splitext(outfilename)[0]
        outfilename = '{}.py'.format(outfilename)
        directive = {
            'schema': schema_name,
            'outfile': outfilename,
            'outsubfile': '',
            'flags': '',
        }
        directives.append(directive)
    return directives


def make_output_file(outfilename, options):
    if os.path.exists(outfilename) and not options['force']:
        sys.exit("\noutput file exists.  Use -f/--force to over-write.\n")
    outfile = open(outfilename, 'w')
    return outfile


#
# Exported functions

def extract_and_generate(infile, outfile, extract_locations_fn, options):
    locations = extract_locations(infile, options)
    if extract_locations_fn is None:
        extract_locations_fn = extract_locations
    directives = generate(locations, outfile, options)
    specification = {
        'directives': directives,
    }
    json.dump(specification, outfile, indent='    ')


def main():
    description = """\
synopsis:
  collect schema locations from xs:include/xs:import elements in schema.
"""
    epilog = """\
examples:
  python collect_schema_locations.py myschema.xsd
  python collect_schema_locations.py myschema.xsd outfile.txt

notes:
  The output directives file is a JSON file suitable for input to
    utils/batch_generate.py.  This directives file contains one directive
    for each module to be generated by generateDS.py.
  You can edit this resulting JSON file, for example to add a sub-class
    module file or flags/options for generateDS.py that are specific
    to each directive.
"""
    parser = argparse.ArgumentParser(
        description=description,
        epilog=epilog,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    parser.add_argument(
        "infilename",
        help="name/location of the XML schema file to be searched"
    )
    parser.add_argument(
        "outfilename",
        nargs="?",
        default=None,
        help="output file name; if ommited stdout"
    )
    parser.add_argument(
        "-f", "--force",
        action="store_true",
        help="force overwrite existing output file",
    )
    parser.add_argument(
        "-v", "--verbose",
        action="store_true",
        help="print messages during actions.",
    )
    options = parser.parse_args()
    # Convert options to a dictionary so external programs a call us.
    options = vars(options)
    infile = open(options['infilename'], 'r')
    if options['outfilename']:
        outfile = make_output_file(options['outfilename'], options)
    else:
        outfile = sys.stdout
    extract_locations_fn = extract_locations
    extract_and_generate(infile, outfile, extract_locations_fn, options)
    infile.close()
    if options['outfilename']:
        outfile.close()


if __name__ == '__main__':
    #import pdb; pdb.set_trace()
    #import ipdb; ipdb.set_trace()
    main()
