#!/usr/bin/env python
import json
import argparse
import shutil
import subprocess
import os
import tempfile

try:
    from urllib.request import urlopen
except ImportError as e:
    # Python 2
    from urllib2 import urlopen


TOOL_PLACEHOLDER = '__tool__'
PKG_PLACEHOLDER = '__pkg__'
AUTHOR_PLACEHOLDER = '__author__'

PYPI_REPO = 'https://pypi.yandex-team.ru/simple/'
PYPI_LOGIN = os.environ.get('PYPI_LOGIN', '')
PYPI_PASSWORD = os.environ.get('PYPI_PASSWORD', '')
PYPIRC_TEMPLACE = '''
[distutils]
index-servers =
    yandex

[yandex]
repository: {repo}
username: {username}
password: {password}
'''


def safe_copystat(src, dst):
    try:
        shutil.copystat(src, dst)
    except WindowsError:
        # can't copy file access times on Windows
        pass


class Builder(object):
    def __init__(self, tool_name, version, author, workdir):
        self.tool_name = tool_name
        self.pkg_name = tool_name.lower().replace('-', '_')
        self.version = version
        self.author = author
        self.cwd = workdir

    def copy_template_file(self, src, dst):
        with open(src, 'rt') as src_f:
            with open(dst, 'wt') as dst_f:
                data = src_f.read(). \
                    replace(TOOL_PLACEHOLDER, self.tool_name). \
                    replace(PKG_PLACEHOLDER, self.pkg_name). \
                    replace(AUTHOR_PLACEHOLDER, self.author)
                dst_f.write(data)
        safe_copystat(src, dst)

    def copy_template_tree(self, src, dst):
        if not os.path.exists(dst):
            os.makedirs(dst)

        for name in os.listdir(src):
            if name.endswith('.pyc'):
                continue

            src_name = os.path.join(src, name)
            dst_name = os.path.join(dst, name.replace('.pyt', '.py').replace(PKG_PLACEHOLDER, self.pkg_name))
            if os.path.islink(src_name):
                shutil.copy(src_name, dst_name)
            elif os.path.isdir(src_name):
                self.copy_template_tree(src_name, dst_name)
            else:
                self.copy_template_file(src_name, dst_name)
        safe_copystat(src, dst)

    def build_upload(self, platform):
        env = os.environ.copy()
        args = ['python', 'setup.py']
        if platform == 'src':
            args += ['sdist']
        else:
            env['TARGET_PLATFORM'] = platform
            args += ['bdist_wheel', '--universal']
        args += ['upload', '-r', 'yandex']
        proc = subprocess.Popen(args, env=env, cwd=self.cwd)
        proc.communicate()
        if proc.returncode:
            raise Exception('Failed to build tool for platform {platform}, exit code: {code}'.format(
                platform=platform,
                code=proc.returncode)
            )

    def sync(self, platform):
        if platform == 'src':
            platform = 'linux'
        uri = 'https://tools.sec.yandex-team.ru/api/v1/release/{name}/{platform}/{version}/info'.format(
            name=self.tool_name,
            platform=platform,
            version=self.version
        )
        body = urlopen(uri)
        info = json.loads(body.read())
        version = info['result']['version']
        with open(os.path.join(self.cwd, self.pkg_name + '_bin', 'version.py'), 'w') as f:
            f.write('LATEST = "%s"' % version)
        print('%s version synced to version: %s' % (self.tool_name, version))

    def prepare_pypirc(self, path):
        config = PYPIRC_TEMPLACE.format(repo=PYPI_REPO, username=PYPI_LOGIN, password=PYPI_PASSWORD)
        with open(path, 'wt') as f:
            f.write(config)


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('tool', type=str,
                        help='security tool name')
    parser.add_argument('--version', type=str, default='latest',
                        help='secuity tool version')
    parser.add_argument('--platforms', type=str, default='linux, windows, darwin',
                        help='comma-separated list of needed platforms')
    parser.add_argument('--workdir', type=str, default='',
                        help='work directory')
    parser.add_argument('--author', type=str,
                        help='package author in email format')

    args = parser.parse_args()
    tool_name = args.tool
    version = args.version
    author = args.author if args.author else 'unknown author'
    platforms = [x.strip() for x in args.platforms.split(',')] + ['src']
    if not args.workdir:
        work_dir = tempfile.mkdtemp()
    else:
        work_dir = args.workdir
    src_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'template')
    home_dir = os.path.expanduser('~')
    pypirc_path = os.path.join(home_dir, '.pypirc')

    builder = Builder(tool_name, version, author, work_dir)
    print('copy %s to %s' % (src_dir, work_dir))
    builder.copy_template_tree(src_dir, work_dir)

    print('try to sync version')
    builder.sync(platforms[0])

    builder.prepare_pypirc(pypirc_path)
    try:
        for platform in platforms:
            print('build&upload for platform: ' + platform)
            builder.build_upload(platform)
    finally:
        os.remove(pypirc_path)
