#!/usr/bin/env fuchsia-vendored-python
# Copyright 2019 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import argparse
import json
import os
import platform
import sys


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--reference', help='Path to the golden API file', required=False)
    parser.add_argument(
        '--manifest', help='Path to the SDK manifest', required=True)
    parser.add_argument(
        '--updated', help='Path to the API file to compute', required=True)
    parser.add_argument(
        '--warn',
        help='Whether API changes should only cause warnings',
        action='store_true')
    parser.add_argument(
        '--base_reference',
        help=
        'If the reference has been filtered to remove items, this is the original file'
    )
    parser.add_argument(
        '--ensure-no-host-tools',
        action='store_true',
        help='Error if there are host tools in the SDK manifest.')

    args = parser.parse_args()

    if not args.reference:
        # Nothing to do.
        with open(args.updated, 'w') as updated_file:
            updated_file.write('No API verification for this SDK :/')
        return 0

    with open(args.manifest, 'r') as manifest_file:
        manifest = json.load(manifest_file)

    ids = [a['id'] for a in manifest['atoms']]

    with open(args.updated, 'w') as updated_file:
        updated_file.write('\n'.join(ids))

    with open(args.reference, 'r') as reference_file:
        old_ids = [l.strip() for l in reference_file.readlines()]

    def is_host_tool_id(id: str) -> bool:
        """Return True if id should not appear when --no-host-tools is used."""
        return id.startswith('sdk://tools/') or id == 'sdk://docs/ref_docs'

    if args.ensure_no_host_tools:
        # Remove any host tools from the golden manifest, as well as the
        # //sdk:docs/ref_docs target which depends on
        # //sdk:host_tools.all($host_toolchain)
        old_ids = [i for i in old_ids if not is_host_tool_id(i)]

    # tools/arm64 should not exist on mac hosts
    # TODO(fxbug.dev/42999): remove when SDK transition is complete.
    if platform.mac_ver()[0]:
        old_ids = [i for i in old_ids if not i.startswith('sdk://tools/arm64')]

    ids = filter(lambda i: not i.startswith('sdk://fidl/zx'), ids)
    old_ids = filter(lambda i: not i.startswith('sdk://fidl/zx'), old_ids)

    new_id_set = set(ids)
    required_id_set = set()
    optional_id_set = set()
    for i in old_ids:
        if i.startswith('?'):
            optional_id_set.add(i[1:])
        else:
            required_id_set.add(i)

    added_ids = new_id_set - (required_id_set | optional_id_set)
    removed_ids = required_id_set - new_id_set

    if args.ensure_no_host_tools:
        added_host_ids = {i for i in added_ids if is_host_tool_id(i)}
        if added_host_ids:
            print('Error: Host tools incorrectly added to SDK:')
            for id in sorted(added_host_ids):
                print(' - %s' % id)
            print(
                'The SDK atoms above should not be dependencies of GN sdk() targets used'
            )
            print('to build this SDK when sdk_no_host_tools is set!')
            return 1

    if added_ids:
        print('Elements added to SDK:')
        for id in sorted(added_ids):
            print(' - %s' % id)
    if removed_ids:
        print('Elements removed from SDK:')
        for id in sorted(removed_ids):
            print(' - %s' % id)
    if removed_ids or added_ids:
        type = 'Warning' if args.warn else 'Error'
        print('%s: SDK contents have changed!' % type)
        if args.base_reference:
            print(
                'The manifest cannot be automatically updated when not cross compiling host tools'
            )
            print(
                'Please update the manifest manually - {}'.format(
                    args.base_reference))
            print(
                'or run fx set with "--args sdk_cross_compile_host_tools=true"')
        else:
            print('Please acknowledge this change by running:')
            print(
                '  cp ' + os.path.abspath(args.updated) + ' ' +
                os.path.abspath(args.reference))
            print(
                'Elements can be marked optional with a leading question mark.')
            print(
                'Please remember to complete transitions by marking elements required!'
            )
        if not args.warn:
            return 1

    return 0


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