#!/usr/bin/env python3
#  Copyright (c) 2019. Vinci Consulting Corp. All Rights Reserved.
#
#  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 pathlib
import subprocess
BASE_DIR = subprocess.check_output('git rev-parse --show-toplevel',
                                   shell=True).strip().decode()
vppapigen_bin = pathlib.Path(
    '%s/src/tools/vppapigen/vppapigen.py' % BASE_DIR).as_posix()

src_dir_depth = 3
output_path = pathlib.Path(
    '%s/build-root/install-vpp-native/vpp/share/vpp/api/' % BASE_DIR)
output_path_debug = pathlib.Path(
    '%s/build-root/install-vpp_debug-native/vpp/share/vpp/api/' % BASE_DIR)

output_dir_map = {
    'plugins': 'plugins',
    'vlibmemory': 'core',
    'vnet': 'core',
    'vpp': 'core',
}


def api_search_globs(src_dir):
    globs = []
    for g in output_dir_map:
        globs.extend(list(src_dir.glob('%s/**/*.api' % g)))
    return globs


def api_files(src_dir):
    print("Searching '%s' for .api files." % src_dir.as_posix())
    return [x for x in api_search_globs(src_dir)]


def vppapigen(vppapigen_bin, output_path, src_dir, src_file):
    try:
        subprocess.check_output(
            [vppapigen_bin, '--includedir', src_dir.as_posix(),
             '--input', src_file.as_posix(), 'JSON',
             '--output', '%s/%s/%s.json' % (
                 output_path,
                 output_dir_map[src_file.as_posix().split('/')[
                     src_dir_depth + BASE_DIR.count('/') - 1]],
                 src_file.name)])
    except KeyError:
        print('src_file: %s' % src_file)
        raise


def main():
    cliparser = argparse.ArgumentParser(
        description='VPP API JSON definition generator')
    cliparser.add_argument('--srcdir', action='store',
                           default='%s/src' % BASE_DIR),
    cliparser.add_argument('--output', action='store',
                           help='directory to store files'),
    cliparser.add_argument('--debug-target', action='store_true',
                           default=False,
                           help="'True' if -debug target"),
    args = cliparser.parse_args()

    src_dir = pathlib.Path(args.srcdir)
    output_target = output_path_debug if args.debug_target else output_path

    if args.output:
        output_dir = pathlib.Path(args.output)
    else:
        output_dir = pathlib.Path(output_target)

    for d in output_dir_map.values():
        output_dir.joinpath(d).mkdir(exist_ok=True, parents=True)

    for f in output_dir.glob('**/*.api.json'):
        f.unlink()

    for f in api_files(src_dir):
        vppapigen(vppapigen_bin, output_dir, src_dir, f)
    print('json files written to: %s/.' % output_dir)


if __name__ == '__main__':
    main()
