#!/usr/bin/python3 -s

import argparse
import json

import yaml
from colorama import Fore

from apidoc_to_openapi.lib.parse_config import *
from apidoc_to_openapi.lib.input_files import *
from apidoc_to_openapi.lib.helper_methods import merge
from apidoc_to_openapi.lib.log import create_custom_logger

logger = create_custom_logger("root")


def parse_command_line_args():
    parser = argparse.ArgumentParser()
    req_grp = parser.add_argument_group(title="Required")
    req_grp.add_argument(
        "-i", metavar="path", required=True, help="File or directory containing apidoc annotations"
    )
    parser.add_argument("-o", metavar="path", help="File output (default: stdout)")
    parser.add_argument("--yaml", action="store_true", help="Convert output to yaml format")
    parser.set_defaults(yaml=False)
    args = parser.parse_args()
    return args


def file_output_to_file(output, filename):
    try:
        f = open(filename, "w+")
        f.write(output)
        f.close()
        return True
    except:
        return False


def main():
    args = parse_command_line_args()
    logger.info(f"{Fore.GREEN}Converting ApiDoc notation to OpenApi 3.0{Fore.RESET}")
    swagger = {"openapi": "3.0.0"}

    apidoc_conf = parse_apidoc_json(args.i)
    swagger["info"] = build_info_section(apidoc_conf)

    # Parse through all found annotations create an instance of class for each
    annotations_objs = []
    for filepath in get_files_to_parse(args.i):
        file_contents = open(filepath, "r").read()
        annotations = find_apidoc_annotations(file_contents)

        for anno in annotations:
            annotations_objs.append(parse_generic_annotation(anno))

    # For every index that contains an Api, take all annotations after that
    #   until the next api declaration or the end of the object array and
    #   construct an api using it's children elements

    api_indices = [i for i, v in enumerate(annotations_objs) if isinstance(v, Api)]
    for i, v in enumerate(api_indices):
        annotations_objs[v].construct(
            annotations_objs[v : (api_indices[i + 1] if len(api_indices) > i + 1 else None)]
        )

    # Add all the apis to the swagger doc
    for i in api_indices:
        merge(swagger, annotations_objs[i].to_swagger())

    # If -o is specified output to file, otherwise, output to stdout
    if args.o:
        successful = False
        if args.yaml:
            successful = file_output_to_file(yaml.dump(swagger, indent=2, sort_keys=False), args.o)
        else:
            successful = file_output_to_file(json.dumps(swagger, indent=2), args.o)
        if successful:
            logger.info("Successfully outputted documentation to %s", args.o)
        else:
            logger.info("Failed to output documentation to %s", args.o)
    else:
        if args.yaml:
            print("\n================YAML=================")
            print(yaml.dump(swagger, indent=2, sort_keys=False))
            print("=====================================\n")
        else:
            print("\n================JSON=================")
            print(json.dumps(swagger, indent=2))
            print("=====================================\n")


if __name__ == "__main__":
    main()
