#!/usr/bin/env python3

# dump-swagger reads all of the swagger API docs used in spec generation and
# outputs a JSON file which merges them all, for use as input to a swagger UI
# viewer.
# See https://github.com/swagger-api/swagger-ui for details of swagger-ui.

# Copyright 2016 OpenMarket Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import argparse
import errno
import json
import logging
import os.path
import re
import sys
import yaml


scripts_dir = os.path.dirname(os.path.abspath(__file__))
templating_dir = os.path.join(scripts_dir, "templating")
api_dir = os.path.join(os.path.dirname(scripts_dir), "api")

sys.path.insert(0, templating_dir)

from matrix_templates import units

parser = argparse.ArgumentParser(
    "dump-swagger.py - assemble the Swagger specs into a single JSON file"
)
parser.add_argument(
    "--client_release", "-c", metavar="LABEL",
    default="unstable",
    help="""The client-server release version to gneerate for. Default:
    %(default)s""",
)
parser.add_argument(
    "-o", "--output",
    default=os.path.join(scripts_dir, "swagger", "api-docs.json"),
    help="File to write the output to. Default: %(default)s"
)
args = parser.parse_args()

output_file = os.path.abspath(args.output)
release_label = args.client_release

major_version = release_label
match = re.match("^(r\d+)(\.\d+)*$", major_version)
if match:
    major_version = match.group(1)

logging.basicConfig()

output = {
    "basePath": "/",
    "consumes": ["application/json"],
    "produces": ["application/json"],
    "host": "matrix.org",
    "schemes": ["https"],
    "info": {
        "title": "Matrix Client-Server API",
        "version": release_label,
    },
    "securityDefinitions": {},
    "paths": {},
    "swagger": "2.0",
}

cs_api_dir = os.path.join(api_dir, 'client-server')
with open(os.path.join(cs_api_dir, 'definitions',
                       'security.yaml')) as f:
    output['securityDefinitions'] = yaml.load(f)

for filename in os.listdir(cs_api_dir):
    if not filename.endswith(".yaml"):
        continue
    filepath = os.path.join(cs_api_dir, filename)

    print("Reading swagger API: %s" % filepath)
    with open(filepath, "r") as f:
        api = yaml.load(f.read())
        api = units.resolve_references(filepath, api)

        basePath = api['basePath']
        for path, methods in api["paths"].items():
            path = (basePath + path).replace('%CLIENT_MAJOR_VERSION%',
                                             major_version)
            for method, spec in methods.items():
                if "tags" in spec.keys():
                    if path not in output["paths"]:
                        output["paths"][path] = {}
                    output["paths"][path][method] = spec

print("Generating %s" % output_file)

try:
    os.makedirs(os.path.dirname(output_file))
except OSError as e:
    if e.errno != errno.EEXIST:
        raise

with open(output_file, "w") as f:
    text = json.dumps(output, sort_keys=True, indent=4)
    text = text.replace("%CLIENT_RELEASE_LABEL%", release_label)
    text = text.replace("%CLIENT_MAJOR_VERSION%", major_version)
    f.write(text)
