#!/usr/bin/env python3
# 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 os
import re
import sys
from typing import List, Tuple, Set, DefaultDict, Dict, Callable, Optional
from collections import defaultdict

from difl.changes import Change
from difl.ir import Libraries, Library, Declaration
from difl.library import library_changes
from difl.comparator import Comparator

# All the changes for a given line
LineChanges = Tuple[int, Set[str]]
# All the changes for a given source file
FileChanges = List[LineChanges]
# All the changes in to all the source files in a library
LibraryChanges = Dict[str, FileChanges]

# Regex to match expected changes in test source files
EXPECT_RE = re.compile(r'\s*//!(.+)')


def expected_file_changes(filename: str) -> FileChanges:
    lines = [l.rstrip() for l in open(filename).readlines()]
    expected_changes: FileChanges = []
    changes: Set[str] = set()
    for num, line in enumerate(lines):
        match = EXPECT_RE.match(line)
        if match:
            changes.add(match.group(1))
        elif len(changes):
            expected_changes.append((num + 1, changes))
            changes = set()
    assert not len(changes)
    return expected_changes


def expected_library_changes(library: Library,
                             source_base_dir: str) -> LibraryChanges:
    '''Extract the list of expected changes from the source files for the library based on //! lines'''
    return {
        filename: expected_file_changes(
            os.path.join(source_base_dir, filename))
        for filename in library.filenames
    }


# A function that returns either the before or after Declaration from a Change
DeclSelector = Callable[[Change], Optional[Declaration]]


def before_selector(change: Change) -> Optional[Declaration]:
    return change.before


def after_selector(change: Change) -> Optional[Declaration]:
    return change.after


def actual_file_changes(changes: List[Change], filename: str,
                        decl_selector: DeclSelector) -> FileChanges:
    line_changes_dict: DefaultDict[int, Set[str]] = defaultdict(set)
    for change in changes:
        decl = decl_selector(change)
        if decl is None: continue
        if decl.filename != filename: continue
        line_changes_dict[decl.line].add(change.name)
    line_changes: List[Tuple[int, Set[str]]] = list(line_changes_dict.items())
    line_changes.sort(key=lambda t: t[0])
    return line_changes


def actual_library_changes(library: Library, changes: List[Change],
                           decl_selector: DeclSelector) -> LibraryChanges:
    return {
        filename: actual_file_changes(changes, filename, decl_selector)
        for filename in library.filenames
    }


def describe_file_differences(filename: str, expected: FileChanges,
                              actual: FileChanges):
    # dictionaries mapping line numbers to change descriptions
    expected_lines = {line: changes for line, changes in expected}
    actual_lines = {line: changes for line, changes in actual}
    # union of the line numbers from expected and actual
    line_numbers: Set[int] = set(
        [line for line, _ in expected] + [line for line, _ in actual])
    for num in sorted(line_numbers):
        expected_changes = expected_lines.get(num, set())
        actual_changes = actual_lines.get(num, set())
        if expected_changes == actual_changes: continue
        print('%s:%d' % (filename, num))
        for c in actual_changes - expected_changes:
            print('  unexpected %s' % c)
        for c in expected_changes - actual_changes:
            print('  expected %s' % c)
        print()


def describe_library_differences(expected: LibraryChanges,
                                 actual: LibraryChanges):
    # the union of the filenames in expected and actual
    filenames = set(list(expected.keys()) + list(actual.keys()))
    for filename in sorted(filenames):
        describe_file_differences(filename, expected.get(filename, []),
                                  actual.get(filename, []))


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--build-dir', help='Fuchsia build directory', required=True)
    parser.add_argument(
        '--before',
        help="Path to JSON IR for before version of the library",
        required=True)
    parser.add_argument(
        '--after',
        help="Path to JSON IR for after version of the library",
        required=True)
    parser.add_argument(
        '--stamp', help="Path to stamp file to write after completion")
    args = parser.parse_args()
    fidl_json_dir = os.path.join(
        args.build_dir, 'gen/garnet/public/lib/fidl/tools/difl_test_fidl')

    before = Libraries().load(args.before)
    after = Libraries().load(args.after)

    before_expected_changes = expected_library_changes(before, args.build_dir)
    after_expected_changes = expected_library_changes(after, args.build_dir)

    comparator = Comparator()

    changes: List[Change] = library_changes(before, after, comparator)

    before_actual_changes = actual_library_changes(before, changes,
                                                   before_selector)
    after_actual_changes = actual_library_changes(after, changes,
                                                  after_selector)

    describe_library_differences(before_expected_changes,
                                 before_actual_changes)
    describe_library_differences(after_expected_changes, after_actual_changes)

    if before_expected_changes == before_actual_changes and after_expected_changes == after_actual_changes:
        if args.stamp:
            with open(args.stamp, 'w') as stamp:
                stamp.truncate()
    else:
        sys.exit(1)
