#!/usr/bin/env python
import argparse
from xym import xym
from xym import __version__
import re


def run():
    parser = argparse.ArgumentParser(description='Extracts one or more YANG'
                                                 'models from an IETF RFC or draft text file')
    parser.add_argument(
        "source",
        help="The URL or file name of the RFC/draft text from which to get the model")
    parser.add_argument(
        "--rfcxml", action='store_true', default=False,
        help="Parse a file in RFCXMLv3 format")
    parser.add_argument(
        "--srcdir", default='.',
        help="Optional: directory where to find the source text; default is './'")
    parser.add_argument(
        "--dstdir", default='.',
        help="Optional: directory where to put the extracted YANG module(s); default is './'")
    parser.add_argument(
        "--strict", type=bool, default=False,
        help='Optional flag that determines syntax enforcement; '
             "'If set to 'True', the <CODE BEGINS> / <CODE ENDS> "
             "tags are required; default is 'False'")
    parser.add_argument(
        "--strict-name", action='store_true', default=False,
        help="Optional flag that determines name enforcement; "
             "If set to 'True', name will be resolved from module "
             "itself and not from name given in the document;"
             " default is 'False'")
    parser.add_argument(
        "--strict-examples", action='store_true', default=False,
        help="Only output valid examples when in strict mode")
    parser.add_argument(
        "--write-dict", action='store_true',
        default=False, help="Optional: write email and module mapping")
    parser.add_argument(
        "--debug", type=int, default=0,
        help="Optional: debug level - determines the amount of debug "
             "info printed to console; default is 0 (no debug info printed)")
    parser.add_argument(
        "--force-revision-pyang", action='store_true', default=False,
        help="Optional: if True it will check if file contains correct revision in file name."
             "If it doesnt it will automatically add the correct revision to the filename using pyang")
    parser.add_argument(
        "--force-revision-regexp", action='store_true', default=False,
        help="Optional: if True it will check if file contains correct revision in file name."
             "If it doesnt it will automatically add the correct revision to the filename using regular"
             " expression")
    parser.add_argument("--extract-code-snippets", action="store_true", default=False,
                        help="Optional: if True all the code snippets from the RFC/draft will be extracted. "
                             "If the source argument is a URL and this argument is set to True, "
                             "please be sure that the code-snippets-dir argument is provided, "
                             "otherwise this value would be overwritten to False.")
    parser.add_argument("--code-snippets-dir", type=str, default='',
                        help="Optional: Directory where to store code snippets extracted from the RFC/draft."
                             "If this argument isn't provided and the source argument isn't a URL, "
                             "then it will be set to the dstdir + 'code-snippets' + source(without file extension). "
                             "If this argument isn't provided and the source argument is a URL, "
                             "then code snippets wouldn't be extracted")
    parser.add_argument(
        "--version", action='version',
        version='%(prog)s {version}'.format(version=__version__))
    group = parser.add_mutually_exclusive_group()
    group.add_argument(
        "--parse-only-modules", nargs='+',
        help="Optional: it will parse only modules added in the list in arguments."
    )
    group.add_argument(
        "--skip-modules", nargs='+',
        help="Optional: it will skip modules added in the list in arguments."
    )

    args = parser.parse_args()

    extracted_models = xym.xym(args.source,
                               args.srcdir,
                               args.dstdir,
                               args.strict,
                               args.strict_name,
                               args.strict_examples,
                               args.debug,
                               force_revision_pyang=args.force_revision_pyang,
                               force_revision_regexp=args.force_revision_regexp,
                               skip_modules=args.skip_modules,
                               parse_only_modules=args.parse_only_modules,
                               rfcxml=args.rfcxml,
                               extract_code_snippets=args.extract_code_snippets,
                               code_snippets_dir=args.code_snippets_dir)
    if len(extracted_models) > 0:
        if args.strict:
            print("Created the following models that conform to the strict guidelines:")
        else:
            print("Created the following models:")
        for em in extracted_models:
            print('%s' % em)
        if args.write_dict:
            url = re.compile(
                r'^(?:http|ftp)s?://'  # http:// or https://
                r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|'  # domain
                r'localhost|'  # localhost...
                r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'  # ...or ip
                r'(?::\d+)?'  # optional port
                r'(?:/?|[/?]\S+)$', re.IGNORECASE)
            fqfn = args.dstdir + '/yang.dict'
            is_url = url.match(args.source)
            if is_url:
                draft_file = args.source.rsplit('/', 1)[1]
            else:
                draft_file = args.source
            draft_name = draft_file.split('.', 1)[0]
            if draft_name.startswith("draft"):
                draft_email = draft_name.rsplit('-', 1)[0] + "@ietf.org"
            else:
                draft_email = draft_name + "@ietf.org"
            with open(fqfn, "a") as of:
                for em in extracted_models:
                    of.write('%s : %s\n' % (em.split('@', 1)[0], draft_email))
                of.close()
    else:
        print('No models created.')


if __name__ == '__main__':
    run()
