#!/usr/bin/env python3

import sys
import os
import json
import argparse
from subprocess import run, PIPE, check_output, CalledProcessError

rootdir = os.path.dirname(os.path.realpath(__file__)) + '/../..'

def crc_from_apigen(revision, filename):
    if not revision and not os.path.isfile(filename):
        print(f'skipping: {filename}', file=sys.stderr)
        return {}
    apigen_bin = f'{rootdir}/src/tools/vppapigen/vppapigen.py'
    if revision:
        apigen = (f'{apigen_bin} --git-revision {revision} --includedir src '
                  f'--input {filename} CRC')
    else:
        apigen = (f'{apigen_bin} --includedir src --input {filename} CRC')
    rv = run(apigen.split(), stdout=PIPE, stderr=PIPE)
    if rv.returncode == 2: # No such file
        print(f'skipping: {revision}:{filename} {rv}', file=sys.stderr)
        return {}
    if rv.returncode != 0:
        print(f'vppapigen failed for {revision}:{filename} with command\n {apigen}\n error: {rv}',
              rv.stderr.decode('ascii'), file=sys.stderr)
        sys.exit(-2)

    return json.loads(rv.stdout)


def dict_compare(d1, d2):
    d1_keys = set(d1.keys())
    d2_keys = set(d2.keys())
    intersect_keys = d1_keys.intersection(d2_keys)
    added = d1_keys - d2_keys
    removed = d2_keys - d1_keys
    modified = {o: (d1[o], d2[o]) for o in intersect_keys if d1[o]['crc'] != d2[o]['crc']}
    same = set(o for o in intersect_keys if d1[o] == d2[o])
    return added, removed, modified, same


def filelist_from_git_ls():
    filelist = []
    git_ls = 'git ls-files *.api'
    rv = run(git_ls.split(), stdout=PIPE, stderr=PIPE)
    if rv.returncode != 0:
        sys.exit(rv.returncode)

    for l in rv.stdout.decode('ascii').split('\n'):
        if len(l):
            filelist.append(l)
    return filelist


def is_uncommitted_changes():
    git_status = 'git status --porcelain -uno'
    rv = run(git_status.split(), stdout=PIPE, stderr=PIPE)
    if rv.returncode != 0:
        sys.exit(rv.returncode)

    if len(rv.stdout):
        return True
    return False


def filelist_from_git_grep(filename):
    filelist = []
    try:
        rv = check_output(f'git grep -e "import .*{filename}" -- *.api', shell=True)
    except CalledProcessError as err:
        return []
        print('RV', err.returncode)
    for l in rv.decode('ascii').split('\n'):
        if l:
            f, p = l.split(':')
            filelist.append(f)
    return filelist


def filelist_from_patchset():
    filelist = []
    git_cmd = '((git diff HEAD~1.. --name-only;git ls-files -m) | sort -u)'
    rv = check_output(git_cmd, shell=True)
    for l in rv.decode('ascii').split('\n'):
        if len(l) and os.path.splitext(l)[1] == '.api':
            filelist.append(l)

    # Check for dependencies (imports)
    imported_files = []
    for f in filelist:
        imported_files.extend(filelist_from_git_grep(os.path.basename(f)))

    filelist.extend(imported_files)
    return set(filelist)

def is_deprecated(d, k):
    if 'options' in d[k]:
        if 'deprecated' in d[k]['options']:
            return True
        # recognize the deprecated format
        if 'status' in d[k]['options'] and d[k]['options']['status'] == 'deprecated':
            print("WARNING: please use 'option deprecated;'")
            return True
    return False

def is_in_progress(d, k):
    if 'options' in d[k]:
        if 'in_progress' in d[k]['options']:
            return True
        # recognize the deprecated format
        if  'status' in d[k]['options'] and d[k]['options']['status'] == 'in_progress':
            print("WARNING: please use 'option in_progress;'")
            return True
    return False

def report(new, old):
    added, removed, modified, same = dict_compare(new, old)
    backwards_incompatible = 0
    # print the full list of in-progress messages
    # they should eventually either disappear of become supported
    for k in new.keys():
        newversion = int(new[k]['version'])
        if newversion == 0 or is_in_progress(new, k):
            print(f'in-progress: {k}')
    for k in added:
        print(f'added: {k}')
    for k in removed:
        oldversion = int(old[k]['version'])
        if oldversion > 0 and not is_deprecated(old, k) and not is_in_progress(old, k):
            backwards_incompatible += 1
            print(f'removed: ** {k}')
        else:
            print(f'removed: {k}')
    for k in modified.keys():
        oldversion = int(old[k]['version'])
        newversion = int(new[k]['version'])
        if oldversion > 0 and not is_in_progress(old, k):
            backwards_incompatible += 1
            print(f'modified: ** {k}')
        else:
            print(f'modified: {k}')

    # check which messages are still there but were marked for deprecation
    for k in new.keys():
        newversion = int(new[k]['version'])
        if newversion > 0 and is_deprecated(new, k):
            if k in old:
                if not is_deprecated(old, k):
                    print(f'deprecated: {k}')
            else:
                print(f'added+deprecated: {k}')

    return backwards_incompatible


def main():
    parser = argparse.ArgumentParser(description='VPP CRC checker.')
    parser.add_argument('--git-revision',
                        help='Git revision to compare against')
    parser.add_argument('--dump-manifest', action='store_true',
                        help='Dump CRC for all messages')
    parser.add_argument('--check-patchset', action='store_true',
                        help='Dump CRC for all messages')
    parser.add_argument('files', nargs='*')
    parser.add_argument('--diff', help='Files to compare (on filesystem)', nargs=2)

    args = parser.parse_args()

    if args.diff and args.files:
        parser.print_help()
        sys.exit(-1)

    # Diff two files
    if args.diff:
        oldcrcs = crc_from_apigen(None, args.diff[0])
        newcrcs = crc_from_apigen(None, args.diff[1])
        backwards_incompatible = report(newcrcs, oldcrcs)
        sys.exit(0)

    # Dump CRC for messages in given files / revision
    if args.dump_manifest:
        files = args.files if args.files else filelist_from_git_ls()
        crcs = {}
        for f in files:
            crcs.update(crc_from_apigen(args.git_revision, f))
        for k, v in crcs.items():
            print(f'{k}: {v}')
        sys.exit(0)

    # Find changes between current patchset and given revision (previous)
    if args.check_patchset:
        if args.git_revision:
            print('Argument git-revision ignored', file=sys.stderr)
        # Check there are no uncomitted changes
        if is_uncommitted_changes():
            print('Please stash or commit changes in workspace', file=sys.stderr)
            sys.exit(-1)
        files = filelist_from_patchset()
    else:
        # Find changes between current workspace and revision
        # Find changes between a given file and a revision
        files = args.files if args.files else filelist_from_git_ls()

    revision = args.git_revision if args.git_revision else 'HEAD~1'

    oldcrcs = {}
    newcrcs = {}
    for f in files:
        newcrcs.update(crc_from_apigen(None, f))
        oldcrcs.update(crc_from_apigen(revision, f))

    backwards_incompatible = report(newcrcs, oldcrcs)

    if args.check_patchset:
        if backwards_incompatible:
            # alert on changing production API
            print("crcchecker: Changing production APIs in an incompatible way", file=sys.stderr)
            sys.exit(-1)
        else:
            print('*' * 67)
            print('* VPP CHECKAPI SUCCESSFULLY COMPLETED')
            print('*' * 67)

if __name__ == '__main__':
    main()
