#! /usr/bin/env python
#
# Copyright (C) 2017 Sony Interactive Entertainment Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1.  Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
# 2.  Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import argparse
import json
import os
import sys

try:
    from urllib.request import urlopen, Request
    from urllib.error import URLError
except ImportError:
    from urllib2 import urlopen, Request, URLError

PUBLIC_GITHUB_API_ENDPOINT = 'https://api.github.com/'

DESCRIPTION = '''Downloads a release binary from a GitHub repository.
(Requests the latest release unless a specific tag is provided.)

Intended for download of vswhere.exe and WinCairoRequirements.zip,
but may be used for arbitrary binaries / repositories.

Checks whether the desired version already exists in the output directory
(by looking for a .version file saved alongside the release binary) --
if so, download is skipped; otherwise any existing version is overwritten.
'''


class Status:
    DOWNLOADED = 0
    UP_TO_DATE = 1
    COULD_NOT_FIND = 2
    USING_EXISTING = 3


def parse_args(argv):
    parser = argparse.ArgumentParser(description=DESCRIPTION, formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('repo', help='GitHub repository slug (e.g., "org/repo")')
    parser.add_argument('filename', help='filename of release binary to download (e.g., "foo.exe", "bar.zip")')
    parser.add_argument('-o', '--output-dir', default='.', help='output directory (defaults to working directory)')
    parser.add_argument('-e', '--endpoint', default=PUBLIC_GITHUB_API_ENDPOINT, help='GitHub API endpoint (defaults to api.github.com)')
    parser.add_argument('-t', '--token', default=None, help='GitHub API OAuth token (for private repos/endpoints)')
    parser.add_argument('-r', '--release-tag', default=None, help='release tag to download (defaults to latest)')
    return parser.parse_args(argv)


def find_release(endpoint, repo, filename, token, tag):
    release_name = 'tags/{}'.format(tag) if tag else 'latest'
    url = '{}/repos/{}/releases/{}'.format(endpoint.rstrip('/'), repo, release_name)

    request = Request(url)
    request.add_header('Accept', 'application/vnd.github.v3+json')
    if token:
        request.add_header('Authorization', 'token {}'.format(token))

    try:
        response = urlopen(request)
    except URLError as error:
        print(error)
        return None, None

    data = json.loads(response.read())
    for asset in data['assets']:
        if asset['name'] == filename:
            version_info = {'tag_name': data['tag_name'], 'updated_at': asset['updated_at']}
            return asset['url'], version_info
    return None, None


def download_release(source_url, target_path, token):
    request = Request(source_url)
    request.add_header('Accept', 'application/octet-stream')
    if token:
        request.add_header('Authorization', 'token {}'.format(token))

    with open(target_path, 'wb') as file:
        file.write(urlopen(request).read())


def load_version_info(version_info_path):
    if not os.path.exists(version_info_path):
        return None

    with open(version_info_path) as file:
        return json.load(file)


def save_version_info(version_info_path, version_info):
    with open(version_info_path, 'w') as file:
        json.dump(version_info, file)


def main(argv):
    args = parse_args(argv)

    binary_path = os.path.join(args.output_dir, args.filename)
    version_info_path = binary_path + '.version'

    print('Updating {}...'.format(args.filename))

    existing_version_info = load_version_info(version_info_path)
    if existing_version_info:
        print('Found existing release: {}'.format(existing_version_info['tag_name']))
    else:
        print('No existing release found.')

    release_title = 'release "{}"'.format(args.release_tag) if args.release_tag else 'latest release'
    print('Seeking {} from {}...'.format(release_title, args.repo))
    release_url, target_version_info = find_release(args.endpoint, args.repo, args.filename, args.token, args.release_tag)

    if not target_version_info:
        if existing_version_info:
            print('Falling back to existing release!')
            return Status.USING_EXISTING

        print('No release found!')
        return Status.COULD_NOT_FIND

    print('Found release to download: {}'.format(target_version_info['tag_name']))

    if target_version_info == existing_version_info:
        print('Already up-to-date!')
        return Status.UP_TO_DATE

    if not os.path.exists(args.output_dir):
        os.makedirs(args.output_dir)

    print('Downloading to {}...'.format(os.path.abspath(args.output_dir)))
    download_release(release_url, binary_path, args.token)
    save_version_info(version_info_path, target_version_info)
    print('Done!')

    return Status.DOWNLOADED


if __name__ == '__main__':
    result = main(sys.argv[1:])

    if result == Status.COULD_NOT_FIND:
        sys.exit(1)
