#!python

from asyncapicodegen import cpp, specwrapper, python_client, markdown_summary
import stringcase
import sys
import os
from pprint import pprint
from copy import copy
import argparse
import urllib.request
import ruamel.yaml as yaml

assert(sys.version_info.major == 3 and sys.version_info.minor >= 7), "Requires Python 3.7 or later"

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Generate AsyncAPI Code")
    input_group = parser.add_mutually_exclusive_group(required=True)
    input_group.add_argument("--spec", type=open, help="AsyncAPI specification document")
    input_group.add_argument("--spec-url", type=str, help="URL to AsyncAPI specification document")

    parser.add_argument("--output_dir", type=str, help="Directory where output files should be written", required=True)
    parser.add_argument("--name", type=str, help="Name of the class that is generated", required=True)
    parser.add_argument("--progtype", type=str, choices=["provider", "utilizer"], default="utilizer")
    parser.add_argument("--verbose", action="store_true", help="Display generated files")

    lang = parser.add_mutually_exclusive_group(required=True)
    lang.add_argument("--cpp", action="store_true", help="Generated C++ code")
#    lang.add_argument("--python", action="store_true", help="Generate Python3 code")
    lang.add_argument("--python-package", action="store_true", help="Generate Python3 package")
    lang.add_argument("--markdown", action="store_true", help="Generate Markdown Documentation")
    args = parser.parse_args()
    args.python = False # This needs to be removed when python as a non-package is supported

    spec = None

    if args.spec_url:
        with urllib.request.urlopen(args.spec_url) as spec_fp:
            spec = yaml.load(spec_fp, Loader=yaml.Loader)
    elif args.spec:
        spec = yaml.load(args.spec, Loader=yaml.Loader)

    if args.progtype == 'provider':
        spec = specwrapper.invert_spec(spec)

    if args.cpp:
        resolver = cpp.SimpleResolver(args.name)
        src_dir = os.path.join(args.output_dir, "src")
        inc_dir = os.path.join(args.output_dir, "include")
        try:
            os.mkdir(src_dir)
            os.mkdir(inc_dir)
        except FileExistsError:
            pass

        generator = cpp.GeneratorFromAsyncApi(src_dir, inc_dir, resolver)
        result = generator.Generate(spec, args.name)
        cppList = result.cpp
        for cpp_file in cppList:
            print(cpp_file)
        hppList = result.hpp
        for hpp_file in hppList:
            print(hpp_file)

        with open(os.path.join(args.output_dir, 'sources.cmake'), 'w') as fp:
            fp.write(f"set({args.name}_sources\n")
            cppList.sort()
            for c in cppList:
                fp.write("{}\n".format(c))
            fp.write(")\n")
        
        with open(os.path.join(args.output_dir, 'headers.cmake'), 'w') as fp:
            fp.write(f"set({args.name}_headers\n")
            hppList.sort()
            for c in hppList:
                fp.write("{}\n".format(c))
            fp.write(")\n")

    elif args.python or args.python_package:
        output_dir = args.output_dir
        if args.python_package:
            output_dir = os.path.join(args.output_dir, args.name)
            the_dirs = ['messages', 'schemas', 'tests']
            for d in the_dirs:
                try:
                    dir_name = os.path.join(output_dir, d)
                    os.makedirs(dir_name)
                except FileExistsError:
                    pass
                with open(os.path.join(dir_name, '__init__.py'), 'w') as fp:
                    fp.write('')
            resolver = python_client.PackageResolver(args.name)
        else:
            resolver = python_client.SimpleResolver(args.name)
        pyClientGenerator = python_client.GeneratorFromAsyncApi(output_dir, resolver)
        pyClientGenerator.Generate(spec, stringcase.pascalcase(args.name), args.progtype)
        if args.python_package:
            pySetupGenerator = python_client.GeneratorFromAsyncApi(args.output_dir, resolver)
            print(pySetupGenerator.GenerateSetup(spec, args.name))

    elif args.markdown:
        resolver = cpp.SimpleResolver(args.name)
        outname = os.path.join(args.output_dir, f"{args.name}.md")
        docGenerator = markdown_summary.GeneratorFromAsyncApi(outname, resolver)
        docGenerator.Generate(spec)

