#!/usr/bin/env python3

import platform
import subprocess
import sys

VERSION_FILE = 'fasm/version.py'
VERSION_FILE_TEMPLATE = '''\
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright 2017-2022 F4PGA Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0

# ** WARNING **
# This file is auto-generated by the update_version.py script.
# ** WARNING **

version_str = "{version}"
version_tuple = {version_tuple}
try:
    from packaging.version import Version as V
    pversion = V("{version}")
except ImportError:
    pass

git_hash = "{git_hash}"
git_describe = "{git_describe}"
git_msg = """\\
{git_msg}
"""
'''

GIT = 'git'
if platform.system() == 'Windows':
    GIT = 'git.exe'


def get_hash():
    cmd = [GIT, 'rev-parse', 'HEAD']
    try:
        return subprocess.check_output(cmd).decode('utf-8').strip()
    except OSError:
        print(cmd)
        raise


def get_describe():
    cmd = [
        GIT, 'describe', '--tags', 'HEAD', '--match', 'v*', '--exclude', '*-r*'
    ]
    try:
        return subprocess.check_output(cmd).decode('utf-8').strip()
    except OSError:
        print(cmd)
        raise


def get_msg():
    cmd = [GIT, 'log', '-1', 'HEAD']
    try:
        data = subprocess.check_output(cmd).decode('utf-8')
    except OSError:
        print(cmd)
        raise
    return '\n'.join(line.rstrip() for line in data.split('\n'))


def create_version_tuple(git_describe):
    """
    >>> t = '''\\
    ... v0.0
    ... v0.0.0
    ... v1.0.1-265-g5f0c7a7
    ... v0.0-7004-g1cf70ea2
    ... '''
    >>> for d in t.splitlines():
    ...     v = create_version_tuple(d)
    ...     print((create_version_str(v), v))
    ('0.0', (0, 0, None))
    ('0.0.0', (0, 0, 0, None))
    ('1.0.1.post265', (1, 0, 1, 265))
    ('0.0.post7004', (0, 0, 7004))
    """
    vtag = git_describe.strip()
    if vtag.startswith('v'):
        vtag = vtag[1:]

    vbits = vtag.split('.')
    vpost = [None]
    if '-' in vbits[-1]:
        vend = vbits.pop(-1).split('-')
        assert len(vend) == 3, (vtag, vbits, vend)
        assert len(vend[0]) > 0, (vtag, vbits, vend)
        vbits.append(vend.pop(0))
        vpost = [int(vend.pop(0))]
        assert vend[-1].startswith('g'), (vtag, vbits, vend, vpost)
    vbits = [int(i) for i in vbits]
    vbits.extend(vpost)
    return tuple(vbits)


def create_version_str(version_tuple):
    vbits = [str(i) for i in version_tuple]
    if version_tuple[-1] is None:
        vbits.pop(-1)
    else:
        vbits[-1] = 'post' + vbits[-1]
    return '.'.join(vbits)


def update_version_py(args):
    output = VERSION_FILE_TEMPLATE.format(**args)

    old = ''
    try:
        with open(VERSION_FILE) as f:
            old = f.read()
    except IOError as e:
        print(e)

    if old != output:
        with open(VERSION_FILE, 'w') as f:
            f.write(output)
        print('Updated {}'.format(VERSION_FILE))


def main(args):
    git_hash = get_hash()
    git_describe = get_describe()
    git_msg = get_msg()

    version_tuple = create_version_tuple(git_describe)
    version = create_version_str(version_tuple)

    update_version_py(locals())

    return 0


if __name__ == "__main__":
    import doctest
    failure_count, test_count = doctest.testmod()
    if failure_count > 0:
        sys.exit(-1)
    sys.exit(main(sys.argv))
