#!/usr/bin/python
#
# Copyright 2014 Google Inc. All Rights Reserved.

import argparse
import os
import re
import shutil
import subprocess
import sys
import zipfile


ANDROID_SYSTEM_JAR = "android_system.jar"
ANDROID_JAR = "android.jar"

parser = argparse.ArgumentParser(
    description=('Update prebuilt android SDK'))
parser.add_argument(
    'buildId',
    type=int,
    nargs='?',
    help='Build server build ID')
parser.add_argument(
    '--target',
    default='sdk',
    help='Download from the specified build server target')
parser.add_argument(
    '--from-local-dir',
    dest='localDir',
    help='Copy prebuilts from local directory instead of buildserver')
parser.add_argument(
    '--no-git',
    action='store_true',
    help='Do not create a git commit for the import')
args = parser.parse_args()

if not args.buildId and not args.localDir:
    parser.error("you must specify either a build ID or --from-local-dir")
    sys.exit(1)


if not args.no_git:
    # Make sure we don't overwrite any pending changes
    try:
        subprocess.check_call(['git', 'diff', '--quiet', '--', '**'])
        subprocess.check_call(['git', 'diff', '--quiet', '--cached', '--', '**'])
    except subprocess.CalledProcessError:
        print >> sys.stderr, "FAIL: There are uncommitted changes here; please revert or stash"
        sys.exit(1)


def GetSSOCmdline(url):
    return ['sso_client', '--location', '--request_timeout', '90', '--url', url]
def SSOFetch(url):
    return subprocess.check_output(GetSSOCmdline(url), stderr=subprocess.STDOUT)
def FetchFile(srcFile, dstFile):
    if not args.localDir:
        fileURL = buildURL + '/' + srcFile
        subprocess.check_call(' '.join(GetSSOCmdline(fileURL) + ['>', dstFile]), shell=True)
    else:
        shutil.copyfile(os.path.join(args.localDir, srcFile), dstFile)


if not args.localDir:
    # to start, find the build server branch we're downloading from
    try:
        branch = SSOFetch("http://android-build/buildbot-update?op=GET-BRANCH&bid=%d" % args.buildId)
    except subprocess.CalledProcessError:
        print >> sys.stderr, "FAIL: Unable to retrieve branch for build ID %d" % args.buildId
        sys.exit(1)
    buildURL = "http://android-build/builds/%s-linux-%s/%d" % (branch, args.target, args.buildId)

    # fetch the list build artifacts
    try:
        listingText = SSOFetch(buildURL + "?output=text")
    except subprocess.CalledProcessError:
        print >> sys.stderr, "FAIL: Unable to retrieve listing for build ID %d" % args.buildId
        sys.exit(1)

    listing = listingText.strip().split('\n')
else:
    listing = os.listdir(args.localDir)


platformZipRE = re.compile(r'^sdk-repo-linux-platforms-.*\.zip$')
platformZipFile = None
for fname in listing:
    if platformZipRE.match(fname):
        platformZipFile = fname
        break
if not platformZipFile:
    src = 'directory' if args.localDir else 'build'
    print >> sys.stderr, "FAIL: The specified %s contains no platform ZIP" % src
    sys.exit(1)

try:
    FetchFile(platformZipFile, platformZipFile)
    FetchFile(ANDROID_SYSTEM_JAR, ANDROID_JAR)
except:
    print >> sys.stderr, "FAIL: Unable to fetch %s" % platformZipFile
    sys.exit(1)


try:    # make sure we delete the downloaded ZIP
    PLATFORM_DIRS = [
        ('android-5.0/data', 'data'),
        ('android-5.0/skins', 'skins'),
        ('android-5.0/templates', 'templates'),
    ]

    PLATFORM_FILES = [
        ('android-5.0/build.prop', 'build.prop'),
        ('android-5.0/framework.aidl', 'framework.aidl'),
        ('android-5.0/sdk.properties', 'sdk.properties'),
        ('android-5.0/source.properties', 'source.properties'),
        ('android-5.0/uiautomator.jar', 'uiautomator.jar'),
    ]

    subprocess.check_call(['git', 'add', ANDROID_JAR])

    with zipfile.ZipFile(platformZipFile) as platformZip:
        for fileEntry in PLATFORM_FILES:
            if os.path.exists(fileEntry[1]):
                if os.path.isdir(fileEntry[1]):
                    subprocess.check_call(['git', 'rm', '-rf', fileEntry[1]])
                else:
                    subprocess.check_call(['git', 'rm', fileEntry[1]])

            with platformZip.open(fileEntry[0], 'r') as infile:
                with open(fileEntry[1], 'w+') as outfile:
                    shutil.copyfileobj(infile, outfile)
            subprocess.check_call(['git', 'add', fileEntry[1]])

        for dirEntry in PLATFORM_DIRS:
            if os.path.exists(dirEntry[1]):
                if os.path.isdir(dirEntry[1]):
                    subprocess.check_call(['git', 'rm', '-rf', dirEntry[1]])
                else:
                    subprocess.check_call(['git', 'rm', dirEntry[1]])

            # extract the new version of the directory
            fileZipDir = dirEntry[0] + '/'

            for fname in platformZip.namelist():
                if (fname[-1] != '/'
                        and fname.startswith(dirEntry[0])):
                    relativePath = fname[len(fileZipDir):]
                    subdirs = os.path.join(dirEntry[1], os.path.dirname(relativePath))
                    if not os.path.exists(subdirs):
                        os.makedirs(subdirs)
                    with platformZip.open(fname, 'r') as infile:
                        with open(os.path.join(dirEntry[1], relativePath), 'w+') as outfile:
                            shutil.copyfileobj(infile, outfile)

            subprocess.check_call(['git', 'add', dirEntry[1]])

    # modify the build.prop and source.properties
    subprocess.check_call(['sed', '-i', 's/AndroidVersion.ApiLevel=20/AndroidVersion.ApiLevel=21/',
            'source.properties'])
    subprocess.check_call(['sed', '-i', '/AndroidVersion.CodeName=L/d', 'source.properties'])

    subprocess.check_call(['sed', '-i',
            's/ro.build.version.sdk=20/ro.build.version.sdk=21/', 'build.prop'])
    subprocess.check_call(['sed', '-i',
            's/ro.build.version.codename=L/ro.build.version.codename=REL/', 'build.prop'])

    subprocess.check_call(['git', 'add', 'source.properties'])
    subprocess.check_call(['git', 'add', 'build.prop'])

    if not args.no_git:
        # commit all changes
        if not args.localDir:
            # gather useful info
            buildInfo = dict(
                buildURL = buildURL,
                buildId = args.buildId,
                branch = branch,
                platformZipFile = platformZipFile,
                androidJar = ANDROID_SYSTEM_JAR,
            )
            msg = """Import L SDK from {branch} build {buildId}

{buildURL}/{platformZipFile}
{buildURL}/{androidJar}

build.prop & source.properties have been modified to make this appear
as API 21

android_system.jar has been submitted as android.jar
""".format(**buildInfo)
        else:
            msg = "DO NOT SUBMIT Import locally built android platform from %s" % args.localDir

        subprocess.check_call(['git', 'commit', '-m', msg])

        print 'Update the support library as well.'

        if args.target == 'sdk':
            print '\tcd support && ./update_support_libs.py %s' % (args.buildId)
        else:
            print '\tcd support && ./update_support_libs.py --target %s %s' % (args.target,
                    args.buildId)
        if not args.localDir:
            print 'Be sure to upload this manually to gerrit.'

finally:
    # revert all stray files, including the downloaded zip
    try:
        with open(os.devnull, 'w') as bitbucket:
            subprocess.check_call(['git', 'add', '-Af', '.'], stdout=bitbucket)
            subprocess.check_call(
                    ['git', 'commit', '-m', 'COMMIT TO REVERT - RESET ME!!!'], stdout=bitbucket)
            subprocess.check_call(['git', 'reset', '--hard', 'HEAD~1'], stdout=bitbucket)
    except subprocess.CalledProcessError:
        print >> sys.stderr, "ERROR: Failed cleaning up, manual cleanup required!!!"
