# Copyright 2022 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 errno
import filecmp
import os
import sys
import plasa_differ
from enum import Enum

# TODO(kjharland): Write unit tests.


class Policy(Enum):
    # update_golden tells this script to overwrite the existing golden with
    # the current golden. This is useful for batch updates.
    update_golden = 'update_golden'

    # ack_changes tells this script to fail if any changes are detected.
    # It will tell the user how to update the golden to acknowledge the
    # changes.
    ack_changes = 'ack_changes'

    # no_breaking_changes tells this script to fail if breaking changes
    # are detected. If non-breaking changes are detected it will tell
    # the user how to update the golden to acknowledge the changes.
    no_breaking_changes = 'no_breaking_changes'

    # no_changes tells this script to fail if any changes are detected.
    # It will not ask the user to update the golden.
    no_changes = 'no_changes'

    def __str__(self):
        return self.value


FIDL_VERSIONING_DOCS_URL = "https://fuchsia.dev/fuchsia-src/reference/fidl/language/versioning"

FIDL_AVAILABILITY_HINT = (
    f"Are you missing an @available annotation?\n"
    f"For more information see {FIDL_VERSIONING_DOCS_URL}\n")


class CompatibilityError(Exception):
    """Exception raised when breaking API changes are detected"""

    def __init__(self, api_level, breaking_changes, current, golden):
        self.api_level = api_level
        self.breaking_changes = breaking_changes
        self.current = current
        self.golden = golden

    def __str__(self):
        formatted_breaking_changes = '\n - '.join(self.breaking_changes)
        return (
            f"These changes are incompatible with API level {self.api_level}\n"
            f"{formatted_breaking_changes}\n\n"
            f"{FIDL_AVAILABILITY_HINT}")


class GoldenMismatchError(Exception):
    """Exception raised when a stale golden file is detected."""

    def __init__(self, api_level, current, golden, show_update_hint=False):
        self.api_level = api_level
        self.current = current
        self.golden = golden
        self.show_update_hint = show_update_hint

    def __str__(self):
        hints = [FIDL_AVAILABILITY_HINT]
        if self.show_update_hint:
            cmd = update_cmd(self.current, self.golden)
            hints.append(
                f"Please acknowledge this change by updating the golden.\n"
                f"To do this, please run:\n"
                f"  {cmd}\n")

        hint_lines = '\n'.join(hints)
        return f"Detected changes to API level {self.api_level}\n" + hint_lines


def golden_not_found_error(filename):
    message = (
        f"The golden file {filename} does not exist.\n"
        f"If this is a new FIDL API you must first create this file.\n"
        f"To do so, run:\n"
        f"  touch {os.path.abspath(filename)}\n")
    return FileNotFoundError(errno.ENOENT, message, filename)


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--policy',
        help="How to handle failures",
        type=Policy,
        default=Policy.no_breaking_changes,
        choices=list(Policy))
    parser.add_argument(
        '--depfile', help='Where to write the depfile', required=True)
    parser.add_argument(
        '--api-level', help='The API level being tested', required=True)
    parser.add_argument(
        '--golden', help='Path to the golden file', required=True)
    parser.add_argument(
        '--current', help='Path to the local file', required=True)
    parser.add_argument(
        '--stamp', help='Path to the victory file', required=True)
    parser.add_argument(
        '--fidl_api_diff_path',
        help='Path to the fidl_api_diff binary',
        required=True)
    args = parser.parse_args()

    dependencies = [args.current, args.golden]

    if not os.path.exists(args.golden):
        if os.path.getsize(args.current) > 0:
            err = golden_not_found_error(args.golden)
        else:
            # Don't depend on files that don't exist.
            dependencies.remove(args.golden)

            # Skip testing if current is empty and golden is missing.
            # This prevents us from asking users to create empty golden files.
            err = None
    elif args.policy == Policy.update_golden:
        err = update_golden(args)
    elif args.policy == Policy.no_breaking_changes:
        err = fail_on_breaking_changes(args)
    elif args.policy == Policy.no_changes:
        err = fail_on_changes(args)
    elif args.policy == Policy.ack_changes:
        err = fail_on_unacknowledged_changes(args)
    else:
        raise ValueError("unknown policy: {}".format(args.policy))

    with open(args.depfile, 'w') as f:
        f.write("{}: {}\n".format(args.stamp, ' '.join(dependencies)))

    with open(args.stamp, 'w') as stamp_file:
        stamp_file.write('Golden!\n')

    if not err:
        return 0

    print("\nERROR: ", err)
    return 1


def update_golden(args):
    import subprocess
    c = update_cmd(args.current, args.golden)
    subprocess.run(c.split())
    return None


def fail_on_breaking_changes(args):
    """Fails if current is not backward compatible with golden or if
    current and golden aren't identical.
    """
    differ = plasa_differ.PlasaDiffer(args.fidl_api_diff_path)
    breaking_changes = differ.find_breaking_changes_in_fragment_file(
        args.golden, args.current)

    if breaking_changes:
        return CompatibilityError(
            api_level=args.api_level,
            breaking_changes=breaking_changes,
            current=args.current,
            golden=args.golden,
        )

    return fail_on_unacknowledged_changes(args)


def fail_on_unacknowledged_changes(args):
    """Asks the user to fix the golden if current and golden aren't identical."""
    if not filecmp.cmp(args.golden, args.current):
        return GoldenMismatchError(
            api_level=args.api_level,
            current=args.current,
            golden=args.golden,
            show_update_hint=True,
        )
    return None


def fail_on_changes(args):
    """Fails if current and golden aren't identical."""
    if not filecmp.cmp(args.golden, args.current):
        return GoldenMismatchError(
            api_level=args.api_level,
            current=args.current,
            golden=args.golden,
        )
    return None


def update_cmd(current, golden):
    return "cp {} {}".format(os.path.abspath(current), os.path.abspath(golden))


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