#!/usr/bin/env python

# Copyright (C) 2016 The ANGLE Project Authors.
#
# 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
#
#     https://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.

"""Generate copies of the Vulkan layers JSON files, with no paths, forcing
Vulkan to use the default search path to look for layers."""

from __future__ import print_function

import argparse
import glob
import json
import os
import platform
import sys


def glob_slash(dirname):
    """Like regular glob but replaces \ with / in returned paths."""
    return [s.replace('\\', '/') for s in glob.glob(dirname)]


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('--icd', action='store_true')
    parser.add_argument('--platform', type=str, default=platform.system(),
        help='Target platform to build validation layers for: '
             'Linux|Darwin|Windows|...')
    parser.add_argument('source_dir')
    parser.add_argument('target_dir')
    parser.add_argument('version_header', help='path to vulkan_core.h')
    parser.add_argument('json_files', nargs='*')
    args = parser.parse_args()

    source_dir = args.source_dir
    target_dir = args.target_dir

    json_files = [j for j in args.json_files if j.endswith('.json')]
    json_in_files = [j for j in args.json_files if j.endswith('.json.in')]

    data_key = 'ICD' if args.icd else 'layer'

    if not os.path.isdir(source_dir):
        print(source_dir + ' is not a directory.', file=sys.stderr)
        return 1

    if not os.path.exists(target_dir):
        os.makedirs(target_dir)

    # Copy the *.json files from source dir to target dir
    if (set(glob_slash(os.path.join(source_dir, '*.json'))) != set(json_files)):
        print(glob.glob(os.path.join(source_dir, '*.json')))
        print('.json list in gn file is out-of-date', file=sys.stderr)
        return 1

    for json_fname in json_files:
        if not json_fname.endswith('.json'):
            continue
        with open(json_fname) as infile:
            data = json.load(infile)

        # Update the path.
        if not data_key in data:
            raise Exception(
                "Could not find '%s' key in %s" % (data_key, json_fname))

        # The standard validation layer has no library path.
        if 'library_path' in data[data_key]:
            prev_name = os.path.basename(data[data_key]['library_path'])
            data[data_key]['library_path'] = prev_name

        target_fname = os.path.join(target_dir, os.path.basename(json_fname))
        with open(target_fname, 'w') as outfile:
            json.dump(data, outfile)

    # Get the Vulkan version from the vulkan_core.h file
    vk_header_filename = args.version_header
    vk_version = None
    with open(vk_header_filename) as vk_header_file:
        for line in vk_header_file:
            if line.startswith('#define VK_HEADER_VERSION'):
                vk_version = line.split()[-1]
                break
    if not vk_version:
        print('failed to extract vk_version', file=sys.stderr)
        return 1

    # Set json file prefix and suffix for generating files, default to Linux.
    relative_path_prefix = '../lib'
    file_type_suffix = '.so'
    if args.platform == 'Windows':
        relative_path_prefix = r'..\\'  # json-escaped, hence two backslashes.
        file_type_suffix = '.dll'
    elif args.platform == 'Darwin':
        file_type_suffix = '.dylib'

    # For each *.json.in template files in source dir generate actual json file
    # in target dir
    if (set(glob_slash(os.path.join(source_dir, '*.json.in'))) !=
            set(json_in_files)):
        print('.json.in list in gn file is out-of-date', file=sys.stderr)
        return 1
    for json_in_name in json_in_files:
        if not json_in_name.endswith('.json.in'):
            continue
        json_in_fname = os.path.basename(json_in_name)
        layer_name = json_in_fname[:-len('.json.in')]
        layer_lib_name = layer_name + file_type_suffix
        json_out_fname = os.path.join(target_dir, json_in_fname[:-len('.in')])
        with open(json_out_fname,'w') as json_out_file, \
             open(json_in_name) as infile:
            for line in infile:
                line = line.replace('@RELATIVE_LAYER_BINARY@',
                                    relative_path_prefix + layer_lib_name)
                line = line.replace('@VK_VERSION@', '1.1.' + vk_version)
                json_out_file.write(line)

if __name__ == '__main__':
    sys.exit(main())
