#!/usr/bin/python


import os
import sys
import time

if not os.environ.get("PYXIE_DEV","dev")=="global": #"unless"
    sys.path[:0] = ["."]

import pyxie

verbose = False
dryrun = False
ver_updating = None


changelog_entry_tmpl = """\
## [%s] - UNRELEASED

### New

*

### Other

*
"""

def vPrint(*args):
    if verbose:
        print " ".join([str(x) for x in args])

def get_shortlog_version():
    global ver_updating
    
    f = open("site/src/panels/shortlog.md")
    shortlog = [x.strip() for x in f.readlines()]
    f.close()
    if shortlog[0] != "---":
        print "CANNOT GET VERSION"
        print "\n".join(shortlog)
        return "-1", "UNRELEASED"
    log = shortlog[1:]
    while log[0] != "---":
        log = log[1:]

    current_version_info = log[1].split()

    ver, release_date = current_version_info[1], current_version_info[3]

    if ver_updating is None:
        ver_updating = ver

    return ver, release_date

def unreleased(release):
    return release == "UNRELEASED"

def get_next_version(ver_type):
    vPrint("get_next_version", ver_type)
    ver, release = get_shortlog_version()
    if unreleased(release):
        vPrint("WARNING: Current version is not yet released")
        return ver, release

    major,minor,patch = [ int(x) for x in ver.split(".") ]
    if ver_type == "major":
        major = major + 1
    elif ver_type == "minor":
        minor = minor + 1
    else:
        patch = patch +1

    new_version = "%d.%d.%d" % (major, minor, patch)
    return new_version, release

def do_usage():
    print "pyxie-dev [toggles] [options]"
    print 
    print "toggles:"
    print "    -v        verbose mode"
    print "    -d        dryrun - don't change files"
    print
    print "options:"
    print "    get       get current version, and if verbose other information"
    print "    propose   get proposed version"
    print "    released  get status of released, Returns 0 if released, 1 if not. If verbose outputs state as well"
    print "    bump      bump version"
    print
    print "    rebase-release Rebase the current code, ready for release"
    print "    make-release   Make the release based on current code"
    print "    do-upload      upload to launchpad and pypi"
    print
    print     
    print "pyxie-dev is intended to be run relative to a development checkout"
    print "If this is not what you want, set PYXIE_DEV=global prior to running pyxie-dev"
    print "eg:"
    print "PYXIE_DEV=global pyxie-dev options"
    print
    print "CURRENT VERSION:", get_shortlog_version()

def do_get():
    ver, release = get_shortlog_version()
    if verbose:
        print "Dryrun: ", dryrun
        print "Release date:", release
        print "Version:",
    print ver
    return 0

def do_released():
    vPrint("do_released")
    ver, release = get_shortlog_version()
    if unreleased(release):
        vPrint("Unreleased")
        return 1
    vPrint("Released:", release)
    vPrint("Version:", ver)
    
    return 0

def do_propose(ver_type):
    vPrint("propose", ver_type)
    ver, release = get_next_version(ver_type)
    if unreleased(release):
        print "Releasing current version -", ver, "- before bumping to next release"
        return 1

    print "PROPOSED NEW VERSION:", ver
    return 0

def bump_shortlog(new_ver):
    f = open("site/src/panels/shortlog.md")
    shortlog =  f.readlines()
    f.close()
    if dryrun:
        vPrint("Writing to stdout")
        print "----SHORTLOG START"
        outfile = sys.stdout
    else:
	outfile = open("site/src/panels/shortlog.md","w")

    newline = "* %s - UNRELEASED - TBD\n" % (new_ver,)
    shortlog.insert(7, newline)
    
    for line in shortlog:
        outfile.write(line)
    
    outfile.flush()
    if not dryrun:
        outfile.close()
    else:
        print "------ END SHORTLOG"

def update_current_shortlog(shortlog_entry):

    ver, release = get_shortlog_version()
    if not unreleased(release):
        print "We appear to already have released this release."
        print "release date:", release

    release_date = time.strftime("%Y-%m-%d")
    new_log_line = "* %s - %s - %s\n" % (ver, release_date, shortlog_entry)

    f = open("site/src/panels/shortlog.md")
    shortlog =  f.readlines()
    f.close()
    if dryrun:
        vPrint("Writing to stdout")
        print "----SHORTLOG START"
        outfile = sys.stdout
    else:
	outfile = open("site/src/panels/shortlog.md","w")

    for line in shortlog:
        if (ver in line) and ("UNRELEASED") in line:
            outfile.write(new_log_line)
        else:
            outfile.write(line)

    outfile.flush()
    if not dryrun:
        outfile.close()
    else:
        print "------ END SHORTLOG"

def bump_CHANGELOG(new_ver):
    vPrint("TBD -- bump_CHANGELOG")
    f = open("CHANGELOG")
    lines = f.readlines()
    f.close()

    old_ver = ver_updating

    for line in range(len(lines)):
        if old_ver in lines[line]:
            # print "FOUND START OF LAST VERSION"
            break

    new_changelog = changelog_entry_tmpl % new_ver
    lines[line:line] = [x+"\n" for x in new_changelog.split("\n") ]

    if dryrun:
        vPrint("Writing to stdout")
        print "----CHANGELOG START"                 
        outfile = sys.stdout
    else:
	outfile = open("CHANGELOG","w")

    for line in lines:
        outfile.write(line)

    if not dryrun:
        outfile.close()
    else:
        print "------ END CHANGE"


def bump_Makefile(ver):
    vPrint("TBD -- bump_Makefile") 
    f = open("Makefile")
    lines = f.readlines()
    f.close()

    if dryrun:
        vPrint("Writing to stdout")
        print "----Makefile START"
        outfile = sys.stdout
    else:
	outfile = open("Makefile","w")


    for line in lines:
        if line.startswith("VERSION="):
            outfile.write("VERSION=%s\n" % (ver,)  )
        else:
            outfile.write(line)

    if not dryrun:
        outfile.close()
    else:
        print "------ END Makefile"

def bump_rebuildDocs():
    vPrint("TBD -- bump_rebuildDocs")
    if dryrun:
        print "Would rebuild docs now. (dryrun - means don't)"
	return

    here = os.getcwd()
    os.chdir("site")
    os.system("./build_site.py")
    os.chdir(here)


def do_bump(ver_type):
    global dryrun
    global verbose

    vPrint("bump", ver_type)
    ver, release = get_next_version(ver_type)
    if unreleased(release):
        print "Refusing to bump release version until this version is released"
        print "You can still do this manually, if you must"
        print
        print "So that you can see what would be updated though, switching dryrun to True, and verbose to True"
        dryrun = True
        verbose = True

    bump_shortlog(ver)
    bump_CHANGELOG(ver)
    bump_Makefile(ver)
    bump_rebuildDocs()

    if dryrun:
        vPrint("Dryrun")
        return 1


def update_changelog_release_date():

    release_date = time.strftime("%Y-%m-%d")

    f = open("CHANGELOG")
    lines = f.readlines()
    f.close()

    if dryrun:
        vPrint("Writing to stdout")
        print "----CHANGELOG START"
        outfile = sys.stdout
    else:
        outfile = open("CHANGELOG","w")

    found = False
    for line in lines:
        if ("UNRELEASED" in line) and not found:
            line = line.replace("UNRELEASED",release_date)
            found = True
        print "HERE"
        outfile.write(line)

    if not dryrun:
        outfile.close()
    else:
        print "------ END CHANGE"

def rebase_release(dryrun):
    release_branch = time.strftime("%Y%m%d")

    if dryrun:
        print "Do This"
        print "git checkout -b "+release_branch
        print "git checkout WIP"
        print "git rebase -i master"
    else:
        os.system("git checkout -b "+release_branch)
        os.system("git checkout WIP")
        os.system("git rebase -i master")
    return 0

def make_release():
    # Extract Shortlog
    x = os.popen("git log|head -20").read()
    lines = x.split("\n")
    shortlog = lines[4].strip()

    # Update shortlog
    update_current_shortlog(shortlog)

    # Update changelog date (assume rest is up to date)
    print "UPDATE CHANGELOG"
    update_changelog_release_date()

    print "update all docs"
    here = os.getcwd()
    os.chdir("site")
    os.system("./build_site.py")   
    os.chdir(here)

    os.system("rm -rf dist")
    os.system("rm MANIFEST")
    ver,release = get_shortlog_version()

    os.system("git tag v"+ver)

    # Update python version of the clib.
    os.chdir("clib")
    os.system("./mk_py_clib.py")
    os.chdir(here)
    return 0

def do_upload():
    # Build debian package - for actual release change "make deb" to "make ppadeb"
    os.system("rm -rf dist")
    os.system("rm MANIFEST")
    os.system("make ppadeb")
    os.system("make distclean")

    # Build PyPI release
    os.system("rm -rf dist")
    os.system("rm MANIFEST")
    os.system("python setup.py sdist upload")
    os.system("make distclean")

    print ""


def main(argv):
    global verbose
    global dryrun
    if "-v" in argv:
        verbose = True
        argv = [x for x in argv if x != "-v" ]

    if "-d" in argv:
        dryrun = True
        argv = [x for x in argv if x != "-d" ]

    if len(argv) == 2:
        if argv[1] == "get":
            return do_get()

        if argv[1] == "released":
            return do_released()

    if len(argv) >= 2:
        if argv[1] == "bump":
            if len(argv) == 3:
                ver_type = argv[2]
            else:
                ver_type = "patch"
            return do_bump(ver_type)

        if argv[1] == "propose":
            if len(argv) == 3:
                ver_type = argv[2] 
            else:
                ver_type = "patch"
            return do_propose(ver_type)

        if argv[1] == "rebase-release":
            rebase_release(dryrun)
            return 0

        if argv[1] == "make-release":
            make_release()
            return 0

        if argv[1] == "do-upload":
            do_upload()
            return 0

    do_usage()
    return 1

if __name__ == "__main__":
    result = main(sys.argv[:])
    if result != None:
        sys.exit(result)
