#!/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',
    'vlib': '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()
