#!/usr/bin/python

# This script is used to update platform SDK prebuilts, Support Library, and a variety of other
# prebuilt libraries used by Android's Makefile builds. For details on how to use this script,
# visit go/update-prebuilts.
import os, sys, getopt, zipfile, re
import argparse
import subprocess
from shutil import copyfile, rmtree
from distutils.version import LooseVersion

current_path = 'current'
system_path = 'system_current'
support_dir = os.path.join(current_path, 'support')
extras_dir = os.path.join(current_path, 'extras')

# See go/fetch_artifact for details on this script.
FETCH_ARTIFACT = '/google/data/ro/projects/android/fetch_artifact'

# Does not import support-v4, which is handled as a separate Android.mk (../support-v4) to
# statically include dependencies. Similarly, the support-v13 module is imported as
# support-v13-nodeps and then handled as a separate Android.mk (../support-v13) to statically
# include dependencies.
maven_to_make = {
    'animated-vector-drawable':     ['android-support-animatedvectordrawable',      'graphics/drawable'],
    'appcompat-v7':                 ['android-support-v7-appcompat-nodeps',         'v7/appcompat'],
    'cardview-v7':                  ['android-support-v7-cardview',                 'v7/cardview'],
    'customtabs':                   ['android-support-customtabs',                  'customtabs'],
    'design':                       ['android-support-design',                      'design'],
    'exifinterface':                ['android-support-exifinterface',               'exifinterface'],
    'gridlayout-v7':                ['android-support-v7-gridlayout',               'v7/gridlayout'],
    'leanback-v17':                 ['android-support-v17-leanback',                'v17/leanback'],
    'mediarouter-v7':               ['android-support-v7-mediarouter',              'v7/mediarouter'],
    'multidex':                     ['android-support-multidex',                    'multidex/library'],
    'multidex-instrumentation':     ['android-support-multidex-instrumentation',    'multidex/instrumentation'],
    'palette-v7':                   ['android-support-v7-palette',                  'v7/palette'],
    'percent':                      ['android-support-percent',                     'percent'],
    'preference-leanback-v17':      ['android-support-v17-preference-leanback',     'v17/preference-leanback'],
    'preference-v14':               ['android-support-v14-preference',              'v14/preference'],
    'preference-v7':                ['android-support-v7-preference',               'v7/preference'],
    'recommendation':               ['android-support-recommendation',              'recommendation'],
    'recyclerview-v7':              ['android-support-v7-recyclerview',             'v7/recyclerview'],
    'support-annotations':          ['android-support-annotations',                 'annotations'],
    'support-compat':               ['android-support-compat',                      'compat'],
    'support-core-ui':              ['android-support-core-ui',                     'core-ui'],
    'support-core-utils':           ['android-support-core-utils',                  'core-utils'],
    'support-dynamic-animation':    ['android-support-dynamic-animation',           'dynamic-animation'],
    'support-emoji':                ['android-support-emoji',                       'emoji'],
    'support-emoji-appcompat':      ['android-support-emoji-appcompat',             'emoji-appcompat'],
    'support-emoji-bundled':        ['android-support-emoji-bundled',               'emoji-bundled'],
    'support-fragment':             ['android-support-fragment',                    'fragment'],
    'support-media-compat':         ['android-support-media-compat',                'media-compat'],
    'support-tv-provider':          ['android-support-tv-provider',                 'tv-provider'],
    'support-v4':                   ['android-support-v4-nodeps',                   'v4'],
    'support-v13':                  ['android-support-v13-nodeps',                  'v13'],
    'support-vector-drawable':      ['android-support-vectordrawable',              'graphics/drawable'],
    'transition':                   ['android-support-transition',                  'transition'],
    'wear':                         ['android-support-wear',                        'wear'],
    'constraint-layout':            ['android-support-constraint-layout',           'constraint-layout'],
    'constraint-layout-solver':     ['android-support-constraint-layout-solver',    'constraint-layout-solver']
}

# Always remove these files.
blacklist_files = [
    'annotations.zip',
    'public.txt',
    'R.txt',
    'AndroidManifest.xml',
    os.path.join('libs','noto-emoji-compat-java.jar')
]

artifact_pattern = re.compile(r"^(.+?)-(\d+\.\d+\.\d+(?:-\w+\d+)?(?:-[\d.]+)*)\.(jar|aar)$")


def touch(fname, times=None):
    with open(fname, 'a'):
        os.utime(fname, times)


def path(*path_parts):
    return reduce((lambda x, y: os.path.join(x, y)), path_parts)


def flatten(list):
    return reduce((lambda x, y: "%s %s" % (x, y)), list)


def rm(path):
    if os.path.isdir(path):
        rmtree(path)
    elif os.path.exists(path):
        os.remove(path)


def mv(src_path, dst_path):
    if os.path.exists(dst_path):
        rm(dst_path)
    if not os.path.exists(os.path.dirname(dst_path)):
        os.makedirs(os.path.dirname(dst_path))
    os.rename(src_path, dst_path)


def detect_artifacts(repo_dirs):
    maven_lib_info = {}

    # Find the latest revision for each artifact, remove others
    for repo_dir in repo_dirs:
        for root, dirs, files in os.walk(repo_dir):
            for file in files:
                matcher = artifact_pattern.match(file)
                if matcher:
                    maven_lib_name = matcher.group(1)
                    maven_lib_vers = LooseVersion(matcher.group(2))

                    if maven_lib_name in maven_to_make:
                        if maven_lib_name not in maven_lib_info \
                                or maven_lib_vers > maven_lib_info[maven_lib_name][0]:
                            maven_lib_info[maven_lib_name] = [maven_lib_vers, repo_dir, root, file]

    return maven_lib_info


def transform_maven_repo(repo_dirs, update_dir, extract_res=True, extract_manifests=[]):
    cwd = os.getcwd()

    # Use a temporary working directory.
    working_dir = os.path.join(cwd, 'support_tmp')
    maven_lib_info = detect_artifacts(repo_dirs)

    for info in maven_lib_info.values():
        transform_maven_lib(working_dir, info[1], info[2], info[3], extract_res, extract_manifests)

    with open(os.path.join(working_dir, 'Android.mk'), 'w') as f:
        args = ["pom2mk"]
        args.extend(["-rewrite=^" + name + "$=" + maven_to_make[name][0] for name in maven_to_make])
        args.extend(["."])
        subprocess.check_call(args, stdout=f, cwd=working_dir)

    # Replace the old directory.
    output_dir = os.path.join(cwd, update_dir)
    mv(working_dir, output_dir)


def transform_maven_lib(working_dir, repo_dir, root, file, extract_res, extract_manifests):
    # Move library into working dir
    new_dir = os.path.join(working_dir, os.path.relpath(root, repo_dir))
    mv(root, new_dir)

    for dirpath, dirs, files in os.walk(new_dir):
        for f in files:
            if '-sources.jar' in f:
                os.remove(os.path.join(dirpath, f))

    matcher = artifact_pattern.match(file)
    maven_lib_name = matcher.group(1)
    maven_lib_vers = matcher.group(2)
    maven_lib_type = matcher.group(3)

    make_lib_name = maven_to_make[maven_lib_name][0]
    make_dir_name = maven_to_make[maven_lib_name][1]

    if extract_res:
        artifact_file = os.path.join(new_dir, file)
        target_dir = os.path.join(working_dir, make_dir_name)
        if not os.path.exists(target_dir):
            os.makedirs(target_dir)

        if maven_lib_type == "aar":
            process_aar(artifact_file, target_dir, make_lib_name)

    if maven_lib_name in extract_manifests:
        with zipfile.ZipFile(artifact_file) as zip:
            zip.extract("AndroidManifest.xml", os.path.join(working_dir, maven_lib_name))

    print maven_lib_vers, ":", maven_lib_name, "->", make_lib_name


def process_aar(artifact_file, target_dir, make_lib_name):
    # Extract AAR file to target_dir.
    with zipfile.ZipFile(artifact_file) as zip:
        zip.extractall(target_dir)

    # Remove classes.jar
    classes_jar = os.path.join(target_dir, "classes.jar")
    if os.path.exists(classes_jar):
        os.remove(classes_jar)

    # Remove or preserve empty dirs.
    for root, dirs, files in os.walk(target_dir):
        for dir in dirs:
            dir_path = os.path.join(root, dir)
            if not os.listdir(dir_path):
                os.rmdir(dir_path)

    # Remove top-level cruft.
    for file in blacklist_files:
        file_path = os.path.join(target_dir, file)
        if os.path.exists(file_path):
            os.remove(file_path)


def fetch_artifact(target, build_id, artifact_path):
    print 'Fetching %s from %s...' % (artifact_path, target)
    fetch_cmd = [FETCH_ARTIFACT, '--bid', str(build_id), '--target', target, artifact_path]
    try:
        subprocess.check_output(fetch_cmd, stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError:
        print >> sys.stderr, 'FAIL: Unable to retrieve %s artifact for build ID %d' % (artifact_path, build_id)
        return None
    return artifact_path


def fetch_and_extract(target, build_id, file):
    artifact_path = fetch_artifact(target, build_id, file)
    if not artifact_path:
        return None

    # Unzip the repo archive into a separate directory.
    repo_dir = os.path.basename(artifact_path)[:-4]
    with zipfile.ZipFile(artifact_path) as zipFile:
        zipFile.extractall(repo_dir)

    return repo_dir


def update_support(target, build_id):
    repo_file = 'top-of-tree-m2repository-%s.zip' % build_id
    repo_dir = fetch_and_extract(target, build_id, repo_file)
    if not repo_dir:
        print >> sys.stderr, 'Failed to extract Support Library repository'
        return False

    # Transform the repo archive into a Makefile-compatible format.
    transform_maven_repo([repo_dir], support_dir, extract_manifests=['support-v4', 'support-v13'])
    return True


def update_constraint(target, build_id):
    layout_dir = fetch_and_extract(target, build_id, 'com.android.support.constraint-constraint-layout-%s.zip' % build_id)
    solver_dir = fetch_and_extract(target, build_id, 'com.android.support.constraint-constraint-layout-solver-%s.zip' % build_id)
    if not layout_dir or not solver_dir:
        return False

    # Passing False here is an inelegant solution, but it means we can replace
    # the top-level directory without worrying about other child directories.
    transform_maven_repo([layout_dir, solver_dir], os.path.join(extras_dir, 'constraint-layout'), extract_res=False)
    return True


def extract_to(zip_file, paths, filename, parent_path):
    zip_path = filter(lambda path: filename in path, paths)[0]
    src_path = zip_file.extract(zip_path)
    dst_path = path(parent_path, filename)
    mv(src_path, dst_path)


def update_sdk_repo(target, build_id):
    platform = 'darwin' if 'mac' in target else 'linux'
    artifact_path = fetch_artifact(
        target, build_id, 'sdk-repo-%s-platforms-%s.zip' % (platform, build_id))
    if not artifact_path:
        return False

    with zipfile.ZipFile(artifact_path) as zipFile:
        paths = zipFile.namelist()

        extract_to(zipFile, paths, 'android.jar', current_path)
        extract_to(zipFile, paths, 'uiautomator.jar', current_path)
        extract_to(zipFile, paths, 'framework.aidl', current_path)
        extract_to(zipFile, paths, 'optional/android.test.mock.jar', current_path)
        extract_to(zipFile, paths, 'optional/android.test.runner.jar', current_path)

        # Unclear if this is actually necessary.
        extract_to(zipFile, paths, 'framework.aidl', system_path)
    return True


def update_system(target, build_id):
    artifact_path = fetch_artifact(target, build_id, 'android_system.jar')
    if not artifact_path:
        return False

    mv(artifact_path, path(system_path, 'android.jar'))
    return True


def append(text, more_text):
    if text:
        return "%s, %s" % (text, more_text)
    return more_text


parser = argparse.ArgumentParser(
    description=('Update current prebuilts'))
parser.add_argument(
    'buildId',
    type=int,
    help='Build server build ID')
parser.add_argument(
    '-c', '--constraint', action="store_true",
    help='If specified, updates only Constraint Layout')
parser.add_argument(
    '-s', '--support', action="store_true",
    help='If specified, updates only the Support Library')
parser.add_argument(
    '-p', '--platform', action="store_true",
    help='If specified, updates only the Android Platform')
args = parser.parse_args()
if not args.buildId:
    parser.error("You must specify a build ID")
    sys.exit(1)
if not (args.support or args.platform or args.constraint):
    parser.error("You must specify at least one of --constraint, --support, or --platform")
    sys.exit(1)

try:
    # Make sure we don't overwrite any pending changes.
    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)

try:
    components = None
    if args.constraint:
        if update_constraint('studio', args.buildId):
            components = append(components, 'Constraint Layout')
            print >> sys.stderr, 'Failed to update Constraint Layout, aborting...'
        else:
            sys.exit(1)
    if args.support:
        if update_support('support_library', args.buildId):
            components = append(components, 'Support Library')
        else:
            print >> sys.stderr, 'Failed to update Support Library, aborting...'
            sys.exit(1)
    if args.platform:
        if update_sdk_repo('sdk_phone_armv7-sdk_mac', args.buildId) \
                and update_system('sdk_phone_armv7-sdk_mac', args.buildId):
            components = append(components, 'platform SDK')
        else:
            print >> sys.stderr, 'Failed to update platform SDK, aborting...'
            sys.exit(1)

    # Commit all changes.
    subprocess.check_call(['git', 'add', current_path])
    subprocess.check_call(['git', 'add', system_path])
    msg = "Import %s from build %s\n\n%s" % (components, args.buildId, flatten(sys.argv))
    subprocess.check_call(['git', 'commit', '-m', msg])
    print 'Remember to test this change before uploading it 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!!!"
