# create a new numerical tag number for the most recent git checkin
# and advance the "mini" GSAS-II version number (from 5.X.Y to 5.X.Y+1)
# or the minor GSAS-II version number (from 5.X.Y to 5.X+1.0)
# Record the hash and version numbers in the git_version.py file.

# This routine can only be used where HEAD and HEAD^1 have not been a tag

import os
import sys
import datetime as dt
import git

mode = 'mini'
if len(sys.argv) > 1:
    if sys.argv[1].lower() == 'minor': 
        mode = 'minor'
    elif sys.argv[1].lower() == 'mini': 
        mode = 'mini'
    else:
        mode = 'help'

if mode == 'help':
    print('Use this command either as ')
    print(f'\t{sys.argv[0]} minor')
    print('or')
    print(f'\t{sys.argv[0]} mini')
    print('If no argument is supplied "mini" is assumed')
    sys.exit()

# get location of the GSAS-II files
# assumed to be the parent of location of this file
path2GSAS2 = os.path.dirname(os.path.dirname(
    os.path.abspath(os.path.expanduser(__file__))))
# and the repo is in the parent of that
path2repo = os.path.dirname(path2GSAS2)

if __name__ == '__main__':

    try:
        g2repo = git.Repo(path2repo)
    except:
        print('Launch of gitpython for version file failed'+
                  f' with path {path2repo}')
        sys.exit()
    if g2repo.active_branch.name != 'main':
        print('Not on main branch')
        sys.exit()
    if g2repo.head.is_detached:
        print(f'Detached head {commit0[:7]!r}')
        sys.exit()
    # make a list of tags without a v; get the largest numeric tag
    # someday use the packaging module (but no more dependencies for now)
    numtag = [i for i in g2repo.tags if 'v' not in i.name]
    max_numeric = max([int(i.name) for i in numtag if i.name.isdecimal()])
    commit = g2repo.head.commit
    now = dt.datetime.now().replace(
        tzinfo=commit.committed_datetime.tzinfo)
    commit0 = commit.hexsha
    # is the newest commit tagged?
    tags0 = g2repo.git.tag('--points-at',commit)
    if tags0: tags0 = tags0.split('\n')
    if tags0:
        print(f'Latest commit ({commit.hexsha[:7]}) is already tagged ({", ".join(tags0)}).')
        sys.exit()
    prev = g2repo.head.commit.parents
    if len(prev) == 1:
        tagsm1 = g2repo.git.tag('--points-at',prev[0])
        if tagsm1: tagsm1 = tagsm1.split('\n')
        if tagsm1:
            print(f'Previous commit ({prev[0].hexsha[:7]}) is already tagged ({", ".join(tagsm1)}).')
            sys.exit()

    # get the latest version number
    releases = [i for i in g2repo.tags if '.' in i.name and i.name.startswith('v')]
    majors = [i.name.split('.')[0][1:] for i in releases]
    major = max([int(i) for i in majors if i.isdecimal()])
    minors = [i.name.split('.')[1] for i in releases if i.name.startswith(f'v{major}.')]
    minor = max([int(i) for i in minors if i.isdecimal()])
    minis = [i.name.split('.',2)[2] for i in releases if i.name.startswith(f'v{major}.{minor}')]
    # mini can be integer, float or even have letters (5.2.1.1rc1)
    # for now, ignore anything with letters or decimals
    mini = max([int(i) for i in minis if i.isdecimal()])
    latest = f'{major}.{minor}.{mini}'
    if mode == 'mini':
        versiontag = f'v{major}.{minor}.{mini+1}'
    elif mode == 'minor':
        versiontag = f'v{major}.{minor+1}.0'    
    else:
        print('unexpected mode',mode)
        sys.exit()
    if versiontag in releases:
        print(f'Versioning problem, generated next version {versiontag} already defined!')
        versiontag = '?'
        sys.exit()
    if versiontag != '?':
        g2repo.create_tag(str(versiontag),ref=commit)
        print(f'created version # {versiontag} for {commit.hexsha[:7]}')

    # add a numeric tag to the newest commit as well
    tagnum = max_numeric + 1
    while str(tagnum) in g2repo.tags:
        print(f'Error: {tagnum} would be repeated')
        tagnum += 1
    g2repo.create_tag(str(tagnum),ref=commit)
    print(f'created tag {tagnum} for {commit.hexsha[:7]}')

    tags0 = [i for i in g2repo.git.tag('--points-at',commit).split('\n') if i.isdecimal()]
    history = list(g2repo.iter_commits('HEAD'))
    for i in history[1:]:
        tags = g2repo.git.tag('--points-at',i)
        if not tags: continue
        commitm1 = i.hexsha
        tagsm1 = [i for i in tags.split('\n') if i.isdecimal()]
        if not tagsm1: continue
        break
    # create a file with GSAS-II version information
    pyfile = os.path.join(path2GSAS2,'git_verinfo.py')
    try:
        fp = open(pyfile,'w')
    except:
        print(f'Creation of git version file {pyfile} failed')
        sys.exit()
    fp.write('# -*- coding: utf-8 -*-\n')
    fp.write(f'# {os.path.split(pyfile)[1]} - GSAS-II version info from git\n')
    fp.write(f'# Do not edit, generated by {" ".join(sys.argv)!r} script\n')
    fp.write(f'# Created {now}\n\n')
    fp.write(f'git_version = {commit0!r}\n')
    if tags:
        fp.write(f'git_tags = {tags0}\n')
    else:
        fp.write('git_tags = []\n')
    fp.write(f'git_prevtaggedversion = {commitm1!r}\n')
    fp.write(f'git_prevtags = {tagsm1}\n')
    fp.write(f'git_versiontag = {versiontag!r}\n')
    fp.close()
    print(f'Created git version file {pyfile} at {now} for {commit0[:7]!r}')

    g2repo.index.add([pyfile])
    g2repo.index.commit(f'increment {mode} version: {versiontag}/{tagnum}')
    print('committed',pyfile,'mode=',mode)
    g2repo.remote(name='origin').push()
    g2repo.remotes.origin.push(versiontag)
    g2repo.remotes.origin.push(str(tagnum))
    print('pushed update and tags',versiontag,tagnum)

#    print('Now do:\n\t git add \n\t git commit \n\t git push \n\t git push --tags\n (try "git push origin HEAD --tags")')
