# -*- Python -*- vim: set syntax=python tabstop=4 expandtab cc=80:
#===----------------------------------------------------------------------===##
#
#                     The LLVM Compiler Infrastructure
#
# This file is dual licensed under the MIT and the University of Illinois Open
# Source Licenses. See LICENSE.TXT for details.
#
#===----------------------------------------------------------------------===##
"""
diff - A set of functions for diff-ing two symbol lists.
"""

from sym_check import util


def _symbol_difference(lhs, rhs):
    lhs_names = set((n['name'] for n in lhs))
    rhs_names = set((n['name'] for n in rhs))
    diff_names = lhs_names - rhs_names
    return [n for n in lhs if n['name'] 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 cmp(old_sym, new_sym) != 0):
            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.'
    return report, int(abi_break)
