# -*- Python -*- vim: set syntax=python tabstop=4 expandtab cc=80:
#===----------------------------------------------------------------------===##
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
#===----------------------------------------------------------------------===##
"""
diff - A set of functions for diff-ing two symbol lists.
"""

from libcxx.sym_check import util


def _symbol_difference(lhs, rhs):
    lhs_names = set(((n['name'], n['type']) for n in lhs))
    rhs_names = set(((n['name'], n['type']) for n in rhs))
    diff_names = lhs_names - rhs_names
    return [n for n in lhs if (n['name'], n['type']) in diff_names]


def _find_by_key(sym_list, k):
    for sym in sym_list:
        if sym['name'] == k:
            return sym
    return None


def added_symbols(old, new):
    return _symbol_difference(new, old)


def removed_symbols(old, new):
    return _symbol_difference(old, new)


def changed_symbols(old, new):
    changed = []
    for old_sym in old:
        if old_sym in new:
            continue
        new_sym = _find_by_key(new, old_sym['name'])
        if (new_sym is not None and not new_sym in old
                and old_sym != new_sym):
            changed += [(old_sym, new_sym)]
    return changed


def diff(old, new):
    added = added_symbols(old, new)
    removed = removed_symbols(old, new)
    changed = changed_symbols(old, new)
    return added, removed, changed


def report_diff(added_syms, removed_syms, changed_syms, names_only=False,
                demangle=True):
    def maybe_demangle(name):
        return util.demangle_symbol(name) if demangle else name

    report = ''
    for sym in added_syms:
        report += 'Symbol added: %s\n' % maybe_demangle(sym['name'])
        if not names_only:
            report += '    %s\n\n' % sym
    if added_syms and names_only:
        report += '\n'
    for sym in removed_syms:
        report += 'SYMBOL REMOVED: %s\n' % maybe_demangle(sym['name'])
        if not names_only:
            report += '    %s\n\n' % sym
    if removed_syms and names_only:
        report += '\n'
    if not names_only:
        for sym_pair in changed_syms:
            old_sym, new_sym = sym_pair
            old_str = '\n    OLD SYMBOL: %s' % old_sym
            new_str = '\n    NEW SYMBOL: %s' % new_sym
            report += ('SYMBOL CHANGED: %s%s%s\n\n' %
                       (maybe_demangle(old_sym['name']),
                        old_str, new_str))

    added = bool(len(added_syms) != 0)
    abi_break = bool(len(removed_syms))
    if not names_only:
        abi_break = abi_break or len(changed_syms)
    if added or abi_break:
        report += 'Summary\n'
        report += '    Added:   %d\n' % len(added_syms)
        report += '    Removed: %d\n' % len(removed_syms)
        if not names_only:
            report += '    Changed: %d\n' % len(changed_syms)
        if not abi_break:
            report += 'Symbols added.'
        else:
            report += 'ABI BREAKAGE: SYMBOLS ADDED OR REMOVED!'
    else:
        report += 'Symbols match.'
    is_different = abi_break or bool(len(added_syms)) \
                   or bool(len(changed_syms))
    return report, abi_break, is_different
