#!/usr/bin/env python
import os
import sys
from os.path import join, isfile, abspath, dirname, relpath, isdir
import shutil


def err(msg=''):
    sys.stderr.write(msg + '\n')
    

def init(name, package_name, setup_py_fpath, kwargs=None):
    if abspath(dirname(setup_py_fpath)) != abspath(os.getcwd()):
        sys.exit('Please, change to ' + dirname(setup_py_fpath) + ' before running setup.py\n')

    cmds = [a for a in sys.argv[1:] if not a.startswith('-')]
    if cmds:
        cmd = sys.argv[1]
        if cmd == 'tag':
            version = write_version_py(package_name, kwargs=kwargs)
            run_cmdl('git tag -a %s -m "Version %s"' % (version, version))
            run_cmdl('git push --tags')
            sys.exit()
    
        if cmd == 'publish':
            run_cmdl('python setup.py sdist && twine upload dist/*')
            sys.exit()
    
        if cmd == 'up':
            run_cmdl('git pull --recurse-submodules --rebase')
            # if first time: $ git submodule update --init --recursive
            run_cmdl('git submodule foreach "(git checkout master; git pull --rebase)"')
            sys.exit()
    
        if is_cleaning():
            clean_package(package_name, '.')
            sys.exit()

    version = write_version_py(package_name, kwargs=kwargs)
    return version


def clean_package(package_name, dirpath='.'):
    print('Cleaning up binary, build and dist for ' + package_name + ' in ' + dirpath + '...')
    if isdir(join(dirpath, 'build')):
        shutil.rmtree(join(dirpath, 'build'))
    if isdir(join(dirpath, 'dist')):
        shutil.rmtree(join(dirpath, 'dist'))
    if isdir(join(dirpath, package_name + '.egg-info')):
        shutil.rmtree(join(dirpath, package_name + '.egg-info'))
    print('Done.')


def get_reqs():
    with open("requirements.txt") as requirements_txt:
        requirements_lines = [line.strip() for line in requirements_txt.readlines()]
    reqs = [line for line in requirements_lines if line and not line.startswith("#")]
    return reqs


def find_package_files(dirpath, package, skip_exts=None):
    paths = []
    for (path, dirs, fnames) in os.walk(join(package, dirpath)):
        for fname in fnames:
            if skip_exts and any(fname.endswith(ext) for ext in skip_exts):
                continue
            fpath = join(path, fname)
            paths.append(relpath(fpath, package))
    return paths


''' Versioning:
1. Write each version to VERSION.txt
2. If the changes are significant, tag the release and push the new tag:
   $ python setup.py tag '''
def write_version_py(package_name, kwargs=None):
    version_txt = 'VERSION.txt'
    if not isfile(version_txt):
        return None

    with open(version_txt) as f:
        v = f.read().strip().split('\n')[0]

    try:
        import subprocess
        git_revision = subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD']).rstrip()
    except:
        git_revision = ''
        pass
    if isinstance(git_revision, bytes):
        git_revision = git_revision.decode()

    version_py = os.path.join(package_name, 'version.py')
    with open(version_py, 'w') as f:
        f.write((
            '# Do not edit this file, pipeline versioning is governed by git tags\n' +
            '__version__ = \'' + v + '\'\n' +
            '__git_revision__ = \'' + str(git_revision) + '\'') + '\n')
        if kwargs:
            for k, v in kwargs.items():
                f.write(k + ' = \'' + v + '\'\n')
    return v


def run_cmdl(_cmd):
    print('$ ' + _cmd)
    os.system(_cmd)


def compile_tool(tool_name, dirpath, requirements):
    if not all(isfile(join(dirpath, req)) for req in requirements):
        print('Compiling ' + tool_name)
        run_cmdl('make -C ' + dirpath)
        if not all(isfile(join(dirpath, req)) for req in requirements):
            err('Failed to compile ' + tool_name + ' (' + dirpath + ')\n')
            return False
    return True


def is_cleaning():
    return len(sys.argv) == 2 and sys.argv[1] == 'clean'
