#!/usr/bin/env python3
#
# Copyright (C) 2019 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.
#
# Sample Usage:
# $ python update_profiles.py 500000 ALL --profdata-suffix 2019-04-15
#
# Additional/frequently-used arguments:
#   -b BUG adds a 'Bug: <BUG>' to the commit message when adding the profiles.
#   --do-not-merge adds a 'DO NOT MERGE' tag to the commit message to restrict
#                  automerge of profiles from release branches.
#
# Try '-h' for a full list of command line arguments.

import argparse
import os
import shutil
import subprocess
import sys
import tempfile
import zipfile

import utils

from android_build_client import AndroidBuildClient


class Benchmark(object):

    def __init__(self, name):
        self.name = name

    def apct_test_tag(self):
        raise NotImplementedError()

    def profdata_file(self, suffix=''):
        profdata = os.path.join(self.name, '{}.profdata'.format(self.name))
        if suffix:
            profdata += '.' + suffix
        return profdata

    def profraw_files(self):
        raise NotImplementedError()

    def merge_profraws(self, profile_dir, output):
        profraws = [
            os.path.join(profile_dir, p)
            for p in self.profraw_files(profile_dir)
        ]
        utils.run_llvm_profdata(profraws, output)


class APKBenchmark(Benchmark):

    def apct_test_tag(self):
        return 'apct/perf/pgo/apk-profile-collector'

    def profdata_file(self, suffix=''):
        profdata = os.path.join('art',
                                '{}_arm_arm64.profdata'.format(self.name))
        if suffix:
            profdata += '.' + suffix
        return profdata

    def profraw_files(self, profile_dir):
        return os.listdir(profile_dir)


def BenchmarkFactory(benchmark_name):
    if benchmark_name == 'dex2oat':
        return APKBenchmark(benchmark_name)
    else:
        raise RuntimeError('Unknown benchmark ' + benchmark_name)


def extract_profiles(build, test_tag, build_client, output_dir):
    pgo_zip = build_client.download_pgo_zip(build, test_tag, output_dir)

    zipfile_name = os.path.join(pgo_zip)
    zip_ref = zipfile.ZipFile(zipfile_name)
    zip_ref.extractall(output_dir)
    zip_ref.close()


KNOWN_BENCHMARKS = ['ALL', 'dex2oat']


def parse_args():
    """Parses and returns command line arguments."""
    parser = argparse.ArgumentParser()

    parser.add_argument(
        'build',
        metavar='BUILD',
        help='Build number to pull from the build server.')

    parser.add_argument(
        '-b', '--bug', type=int, help='Bug to reference in commit message.')

    parser.add_argument(
        '--use-current-branch',
        action='store_true',
        help='Do not repo start a new branch for the update.')

    parser.add_argument(
        '--add-do-not-merge',
        action='store_true',
        help='Add \'DO NOT MERGE\' to the commit message.')

    parser.add_argument(
        '--profdata-suffix',
        type=str,
        default='',
        help='Suffix to append to merged profdata file')

    parser.add_argument(
        'benchmark',
        metavar='BENCHMARK',
        help='Update profiles for BENCHMARK.  Choices are {}'.format(
            KNOWN_BENCHMARKS))

    parser.add_argument(
        '--skip-cleanup',
        '-sc',
        action='store_true',
        default=False,
        help='Skip the cleanup, and leave intermediate files (in /tmp/pgo-profiles-*)'
    )

    return parser.parse_args()


def get_current_profile(benchmark):
    profile = benchmark.profdata_file()
    dirname, basename = os.path.split(profile)

    old_profiles = [f for f in os.listdir(dirname) if f.startswith(basename)]
    if len(old_profiles) == 0:
        return ''
    return os.path.join(dirname, old_profiles[0])


def main():
    args = parse_args()
    utils.check_gcertstatus()

    if args.benchmark == 'ALL':
        worklist = KNOWN_BENCHMARKS[1:]
    else:
        worklist = [args.benchmark]

    profiles_project = os.path.join(utils.android_build_top(), 'toolchain',
                                    'pgo-profiles')
    os.chdir(profiles_project)

    if not args.use_current_branch:
        branch_name = 'update-profiles-' + args.build
        utils.check_call(['repo', 'start', branch_name, '.'])

    build_client = AndroidBuildClient()

    for benchmark_name in worklist:
        benchmark = BenchmarkFactory(benchmark_name)

        # Existing profile file, which gets 'rm'-ed from 'git' down below.
        current_profile = get_current_profile(benchmark)

        # Extract profiles to a temporary directory.  After extraction, we
        # expect to find one subdirectory with profraw files under the temporary
        # directory.
        extract_dir = tempfile.mkdtemp(prefix='pgo-profiles-' + benchmark_name)
        extract_profiles(args.build, benchmark.apct_test_tag(), build_client,
                         extract_dir)

        extract_subdirs = [
            os.path.join(extract_dir, sub)
            for sub in os.listdir(extract_dir)
            if os.path.isdir(os.path.join(extract_dir, sub))
        ]
        if len(extract_subdirs) != 1:
            raise RuntimeError(
                'Expected one subdir under {}'.format(extract_dir))

        # Merge profiles.
        profdata = benchmark.profdata_file(args.profdata_suffix)
        benchmark.merge_profraws(extract_subdirs[0], profdata)

        # Construct 'git' commit message.
        message_lines = [
            'Update PGO profiles for {}'.format(benchmark_name), '',
            'The profiles are from build {}.'.format(args.build), ''
        ]

        if args.add_do_not_merge:
            message_lines[0] = '[DO NOT MERGE] ' + message_lines[0]

        if args.bug:
            message_lines.append('')
            message_lines.append('Bug: http://b/{}'.format(args.bug))
        message_lines.append('Test: Build (TH)')
        message = '\n'.join(message_lines)

        # Invoke git: Delete current profile, add new profile and commit these
        # changes.
        if current_profile:
            utils.check_call(['git', 'rm', current_profile])
        utils.check_call(['git', 'add', profdata])
        utils.check_call(['git', 'commit', '-m', message])

        if not args.skip_cleanup:
            shutil.rmtree(extract_dir)


if __name__ == '__main__':
    main()
