#!/usr/bin/env python3

import subprocess


def exec_cmd(cmd, input=None):
    p = subprocess.Popen(
        cmd,
        stdout=subprocess.PIPE,
        stdin=(subprocess.PIPE if input else None))
    stdout, _ = p.communicate(input and input.encode())
    return str(stdout, 'utf-8')


def get_diff(tag):
    return exec_cmd([
        "git", "log", "--pretty=%h %s", "--no-merges", "{}..HEAD".format(tag)
    ]).splitlines()


def get_last_tag():
    return max(
        list(map(int, tag.split('.')))
        for tag in exec_cmd(["git", "tag"]).splitlines())


def inc_tag(tag):
    tag = tag[:]
    tag[-1] += 1
    return tag


def str_tag(tag):
    return '.'.join(map(str, tag))


def get_info(version):
    last_tag = get_last_tag()
    new_tag = version or str_tag(inc_tag(last_tag))

    subject = "Version {}".format(new_tag)
    changes = '\n'.join(
        '* {}'.format(line) for line in get_diff(str_tag(last_tag)))

    annotation = """{subject}
{sep}

{changes}
""".format(
        subject=subject, sep='-' * len(subject), changes=changes)
    return new_tag, annotation


def bump(tag, annotation):
    exec_cmd(["git", "tag", "-s", "-F-", tag], input=annotation)


def push():
    exec_cmd(["git", "push", "origin", "--tags"])


def show(tag):
    return exec_cmd(["git", "show", tag])


def main(args):
    tag, annotation = get_info(args.version)
    if args.dry_run:
        print(annotation)
    else:
        bump(tag, annotation)
        print(show(tag))

        a = input('Push new tag? [y/N]: ')
        if a.lower() in ('y', 'yes'):
            push()


if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument(
        'version',
        nargs='?',
        help="specify version, otherwise the current version "
        "will be incremented by 1")
    parser.add_argument(
        '--dry-run',
        action='store_true',
        help="print tag's number and annotation")

    args = parser.parse_args()

    main(args)
