import re
from argparse import ArgumentParser
from os.path import dirname, abspath, join
from subprocess import check_output, call


def git(command, repo):
    return check_output('git '+command, cwd=repo, shell=True).decode()


def repo_state_bad(mock_repo):
    status = git('status', mock_repo)
    if 'You are in the middle of an am session' in status:
        print(f'Mock repo at {mock_repo} needs cleanup:\n')
        call('git status', shell=True)
        return True


def cleanup_old_patches(mock_repo):
    print('cleaning up old patches:')
    call('rm -vf /tmp/*.mock.patch', shell=True)
    call('find . -name "*.rej" -print -delete', shell=True, cwd=mock_repo)


def find_initial_cpython_rev():
    with open('lastsync.txt') as source:
        return source.read().strip()


def cpython_revs_affecting_mock(cpython_repo, start):
    revs = git(f'log --no-merges --format=%H {start}..  '
               f'-- '
               f'Lib/unittest/mock.py '
               f'Lib/unittest/test/testmock/ '
               f'Lib/test/test_unittest/testmock/',
               repo=cpython_repo).split()
    revs.reverse()
    print(f'{len(revs)} patches that may need backporting')
    return revs


def has_been_backported(mock_repo, cpython_rev):
    backport_rev = git(f'log --format=%H --grep "Backports: {cpython_rev}"',
                       repo=mock_repo).strip()
    if backport_rev:
        print(f'{cpython_rev} backported in {backport_rev}')
        return True
    print(f'{cpython_rev} has not been backported')


def extract_patch_for(cpython_repo, rev):
    return git(f'format-patch -1 --no-stat --keep-subject --signoff --stdout {rev}',
               repo=cpython_repo)


def munge(rev, patch):

    sign_off = 'Signed-off-by:'
    patch = patch.replace(sign_off, f'Backports: {rev}\n{sign_off}', 1)

    for pattern, sub in (
        ('(a|b)/Lib/unittest/mock.py', r'\1/mock/mock.py'),
        (r'(a|b)/Lib/unittest/test/testmock/(\S+)', r'\1/mock/tests/\2'),
        (r'(a|b)/Lib/test/test_unittest/testmock/(\S+)', r'\1/mock/tests/\2'),
        ('(a|b)/Misc/NEWS', r'\1/NEWS'),
        ('(a|b)/NEWS.d/next/[^/]+/(.+\.rst)', r'\1/NEWS.d/\2'),
    ):
        patch = re.sub(pattern, sub, patch)
    return patch


def apply_patch(mock_repo, rev, patch):
    patch_path = f'/tmp/{rev}.mock.patch'

    with open(patch_path, 'w') as target:
        target.write(patch)
    print(f'wrote {patch_path}')

    call(f'git am -k '
         f'--include "mock/*" --include NEWS --include "NEWS.d/*" '
         f'--reject {patch_path} ',
         cwd=mock_repo, shell=True)


def update_last_sync(mock_repo, rev):
    with open(join(mock_repo, 'lastsync.txt'), 'w') as target:
        target.write(rev+'\n')
    print(f'update lastsync.txt to {rev}')


def rev_from_mock_patch(text):
    match = re.search('Backports: ([a-z0-9]+)', text)
    return match.group(1)


def skip_current(mock_repo, reason):
    text = git('am --show-current-patch', repo=mock_repo)
    rev = rev_from_mock_patch(text)
    git('am --abort', repo=mock_repo)
    print(f'skipping {rev}')
    update_last_sync(mock_repo, rev)
    call(f'git commit -m "Backports: {rev}, skipped: {reason}" lastsync.txt', shell=True, cwd=mock_repo)
    cleanup_old_patches(mock_repo)


def commit_last_sync(revs, mock_repo):
    print('Yay! All caught up!')
    if len(revs):
        git('commit -m "latest sync point" lastsync.txt', repo=mock_repo)


def main():
    args = parse_args()

    if args.skip_current:
        return skip_current(args.mock, args.skip_reason)

    initial_cpython_rev = find_initial_cpython_rev()

    if args.list:
        for rev in cpython_revs_affecting_mock(args.cpython, initial_cpython_rev):
            print(git(f'show --name-only --oneline {rev}', args.cpython), end='')
            has_been_backported(args.mock, rev)
            print()
        return

    if repo_state_bad(args.mock):
        return

    cleanup_old_patches(args.mock)

    if args.rev:
        revs = [args.rev]
    else:
        revs = cpython_revs_affecting_mock(args.cpython, initial_cpython_rev)

    for rev in revs:

        if has_been_backported(args.mock, rev):
            update_last_sync(args.mock, rev)
            continue

        patch = extract_patch_for(args.cpython, rev)
        patch = munge(rev, patch)
        apply_patch(args.mock, rev, patch)
        break

    else:
        if not args.rev:
            commit_last_sync(revs, args.mock)


def parse_args():
    parser = ArgumentParser()
    parser.add_argument('--cpython', default='../cpython')
    parser.add_argument('--mock', default=abspath(dirname(__file__)))
    parser.add_argument('--list', action='store_true', help='list revs remaining to backport')
    parser.add_argument('--rev', help='backport a specific git hash')
    parser.add_argument('--skip-current', action='store_true')
    parser.add_argument('--skip-reason', default='it has no changes needed here.')
    return parser.parse_args()


if __name__ == '__main__':
    main()
