#!/usr/bin/env python
# Copyright (C) 2013 The Android Open Source Project
#
# 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.

from __future__ import print_function

import argparse
from hashlib import sha1
from os import environ, link, makedirs, path, remove
import shutil
from subprocess import check_call, CalledProcessError
from sys import stderr
from util import hash_file, resolve_url
from zipfile import ZipFile, BadZipfile, LargeZipFile

GERRIT_HOME = path.expanduser('~/.gerritcodereview')
CACHE_DIR = environ.get(
    'GERRIT_CACHE_HOME',
    path.join(GERRIT_HOME, 'bazel-cache', 'downloaded-artifacts'))

LOCAL_PROPERTIES = 'local.properties'


def safe_mkdirs(d):
    if path.isdir(d):
        return
    try:
        makedirs(d)
    except OSError as err:
        if not path.isdir(d):
            raise err


def download_properties(root_dir):
    """ Get the download properties.

    First tries to find the properties file in the given root directory,
    and if not found there, tries in the Gerrit settings folder in the
    user's home directory.

    Returns a set of download properties, which may be empty.

    """
    p = {}
    local_prop = path.join(root_dir, LOCAL_PROPERTIES)
    if not path.isfile(local_prop):
        local_prop = path.join(GERRIT_HOME, LOCAL_PROPERTIES)
    if path.isfile(local_prop):
        try:
            with open(local_prop) as fd:
                for line in fd:
                    if line.startswith('download.'):
                        d = [e.strip() for e in line.split('=', 1)]
                        name, url = d[0], d[1]
                        p[name[len('download.'):]] = url
        except OSError:
            pass
    return p


def cache_entry(args):
    if args.v:
        h = args.v
    else:
        h = sha1(args.u.encode('utf-8')).hexdigest()
    name = '%s-%s' % (path.basename(args.o), h)
    return path.join(CACHE_DIR, name)


parser = argparse.ArgumentParser()
parser.add_argument('-o', help='local output file')
parser.add_argument('-u', help='URL to download')
parser.add_argument('-v', help='expected content SHA-1')
parser.add_argument('-x', action='append', help='file to delete from ZIP')
parser.add_argument('--exclude_java_sources', action='store_true')
args = parser.parse_args()

root_dir = args.o
while root_dir and path.dirname(root_dir) != root_dir:
    root_dir, n = path.split(root_dir)
    if n == 'WORKSPACE':
        break

redirects = download_properties(root_dir)
cache_ent = cache_entry(args)
src_url = resolve_url(args.u, redirects)

if not path.exists(cache_ent):
    try:
        safe_mkdirs(path.dirname(cache_ent))
    except OSError as err:
        print('error creating directory %s: %s' %
              (path.dirname(cache_ent), err), file=stderr)
        exit(1)

    print('Download %s' % src_url, file=stderr)
    try:
        check_call(['curl', '--proxy-anyauth', '-ksSfLo', cache_ent, src_url])
    except OSError as err:
        print('could not invoke curl: %s\nis curl installed?' % err,
              file=stderr)
        exit(1)
    except CalledProcessError as err:
        print('error using curl: %s' % err, file=stderr)
        exit(1)

if args.v:
    have = hash_file(sha1(), cache_ent).hexdigest()
    if args.v != have:
        print((
            '%s:\n' +
            'expected %s\n' +
            'received %s\n') % (src_url, args.v, have), file=stderr)
        try:
            remove(cache_ent)
        except OSError as err:
            if path.exists(cache_ent):
                print('error removing %s: %s' % (cache_ent, err), file=stderr)
        exit(1)

exclude = []
if args.x:
    exclude += args.x
if args.exclude_java_sources:
    try:
        with ZipFile(cache_ent, 'r') as zf:
            for n in zf.namelist():
                if n.endswith('.java'):
                    exclude.append(n)
    except (BadZipfile, LargeZipFile) as err:
        print('error opening %s: %s' % (cache_ent, err), file=stderr)
        exit(1)

safe_mkdirs(path.dirname(args.o))
if exclude:
    try:
        shutil.copyfile(cache_ent, args.o)
    except (shutil.Error, IOError) as err:
        print('error copying to %s: %s' % (args.o, err), file=stderr)
        exit(1)
    try:
        check_call(['zip', '-d', args.o] + exclude)
    except CalledProcessError as err:
        print('error removing files from zip: %s' % err, file=stderr)
        exit(1)
else:
    try:
        link(cache_ent, args.o)
    except OSError as err:
        try:
            shutil.copyfile(cache_ent, args.o)
        except (shutil.Error, IOError) as err:
            print('error copying to %s: %s' % (args.o, err), file=stderr)
            exit(1)
