#!/usr/bin/env python3
# Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.

import argparse
import datetime
import os
import re
import statistics
import sys
import time

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

import adb_utils
import apk_utils
import perfetto_utils
import utils


def setup(options):
    # Increase screen off timeout to avoid device screen turns off.
    twenty_four_hours_in_millis = 24 * 60 * 60 * 1000
    previous_screen_off_timeout = adb_utils.get_screen_off_timeout(
        options.device_id)
    adb_utils.set_screen_off_timeout(twenty_four_hours_in_millis,
                                     options.device_id)

    # Unlock device.
    adb_utils.unlock(options.device_id, options.device_pin)

    teardown_options = {
        'previous_screen_off_timeout': previous_screen_off_timeout
    }
    return teardown_options


def teardown(options, teardown_options):
    # Reset screen off timeout.
    adb_utils.set_screen_off_timeout(
        teardown_options['previous_screen_off_timeout'], options.device_id)


def run_all(apk_or_apks, options, tmp_dir):
    # Launch app while collecting information.
    data_total = {}
    for iteration in range(1, options.iterations + 1):
        print('Starting iteration %i' % iteration)
        out_dir = os.path.join(options.out_dir, str(iteration))
        teardown_options = setup_for_run(apk_or_apks, out_dir, options)
        data = run(out_dir, options, tmp_dir)
        teardown_for_run(out_dir, options, teardown_options)
        add_data(data_total, data)
        print('Result:')
        print(data)
        print(compute_data_summary(data_total))
        print('Done')
    print('Average result:')
    data_summary = compute_data_summary(data_total)
    print(data_summary)
    write_data_to_dir(options.out_dir, data_summary)
    if options.out:
        write_data_to_file(options.out, data_summary)


def compute_data_summary(data_total):
    data_summary = {}
    for key, value in data_total.items():
        if not isinstance(value, list):
            data_summary[key] = value
            continue
        data_summary['%s_avg' % key] = round(statistics.mean(value), 1)
        data_summary['%s_med' % key] = statistics.median(value)
        data_summary['%s_min' % key] = min(value)
        data_summary['%s_max' % key] = max(value)
    return data_summary


def setup_for_run(apk_or_apks, out_dir, options):
    adb_utils.root(options.device_id)

    print('Installing')
    adb_utils.uninstall(options.app_id, options.device_id)
    if apk_or_apks['apk']:
        adb_utils.install(apk_or_apks['apk'], options.device_id)
    else:
        assert apk_or_apks['apks']
        adb_utils.install_apks(apk_or_apks['apks'], options.device_id)

    os.makedirs(out_dir, exist_ok=True)

    # Grant notifications.
    if options.grant_post_notification_permission:
        adb_utils.grant(options.app_id, 'android.permission.POST_NOTIFICATIONS',
                        options.device_id)

    # AOT compile.
    if options.aot:
        print('AOT compiling')
        if options.baseline_profile:
            adb_utils.clear_profile_data(options.app_id, options.device_id)
            if options.baseline_profile_install == 'adb':
                adb_utils.install_profile_using_adb(options.app_id,
                                                    options.baseline_profile,
                                                    options.device_id)
            else:
                assert options.baseline_profile_install == 'profileinstaller'
                adb_utils.install_profile_using_profileinstaller(
                    options.app_id, options.device_id)
        else:
            adb_utils.force_compilation(options.app_id, options.device_id)

    # Cooldown and then unlock device.
    if options.cooldown > 0:
        print('Cooling down for %i seconds' % options.cooldown)
        assert adb_utils.get_screen_state(options.device_id).is_off()
        time.sleep(options.cooldown)
        teardown_options = adb_utils.prepare_for_interaction_with_device(
            options.device_id, options.device_pin)
    else:
        teardown_options = None

    # Prelaunch for hot startup.
    if options.hot_startup:
        print('Prelaunching')
        adb_utils.launch_activity(options.app_id,
                                  options.main_activity,
                                  options.device_id,
                                  wait_for_activity_to_launch=False)
        time.sleep(options.startup_duration)
        adb_utils.navigate_to_home_screen(options.device_id)
        time.sleep(1)

    # Drop caches before run.
    adb_utils.drop_caches(options.device_id)
    return teardown_options


def teardown_for_run(out_dir, options, teardown_options):
    assert adb_utils.get_screen_state(
        options.device_id).is_on_and_unlocked_or_unknown()

    if options.capture_screen:
        target = os.path.join(out_dir, 'screen.png')
        adb_utils.capture_screen(target, options.device_id)

    if options.cooldown > 0:
        adb_utils.teardown_after_interaction_with_device(
            teardown_options, options.device_id)
        adb_utils.ensure_screen_off(options.device_id)
    else:
        assert teardown_options is None


def run(out_dir, options, tmp_dir):
    assert adb_utils.get_screen_state(
        options.device_id).is_on_and_unlocked_or_unknown()

    # Start logcat for time to fully drawn.
    logcat_process = None
    if options.fully_drawn_logcat_message:
        adb_utils.clear_logcat(options.device_id)
        logcat_process = adb_utils.start_logcat(
            options.device_id,
            format='time',
            filter='%s ActivityTaskManager:I' %
            options.fully_drawn_logcat_filter,
            silent=True)

    # Start perfetto trace collector.
    perfetto_process = None
    perfetto_trace_path = None
    if options.perfetto:
        perfetto_process, perfetto_trace_path = perfetto_utils.record_android_trace(
            out_dir, tmp_dir, options.device_id)

    # Launch main activity.
    launch_activity_result = adb_utils.launch_activity(
        options.app_id,
        options.main_activity,
        options.device_id,
        intent_data_uri=options.intent_data_uri,
        wait_for_activity_to_launch=True)

    # Wait for app to be fully drawn.
    logcat = None
    if logcat_process is not None:
        wait_until_fully_drawn(logcat_process, options)
        logcat = adb_utils.stop_logcat(logcat_process)

    # Wait for perfetto trace collector to stop.
    if options.perfetto:
        perfetto_utils.stop_record_android_trace(perfetto_process, out_dir)

    # Get minor and major page faults from app process.
    data = compute_data(launch_activity_result, logcat, perfetto_trace_path,
                        options)
    write_data_to_dir(out_dir, data)
    return data


def wait_until_fully_drawn(logcat_process, options):
    print('Waiting until app is fully drawn')
    while True:
        is_fully_drawn = any(
            is_app_fully_drawn_logcat_message(line, options) \
            for line in logcat_process.lines)
        if is_fully_drawn:
            break
        time.sleep(1)
    print('Done')


def compute_time_to_fully_drawn_from_time_to_first_frame(logcat, options):
    displayed_time = None
    fully_drawn_time = None
    for line in logcat:
        if is_app_displayed_logcat_message(line, options):
            displayed_time = get_timestamp_from_logcat_message(line)
        elif is_app_fully_drawn_logcat_message(line, options):
            fully_drawn_time = get_timestamp_from_logcat_message(line)
    assert displayed_time is not None
    assert fully_drawn_time is not None
    assert fully_drawn_time >= displayed_time
    return fully_drawn_time - displayed_time


def get_timestamp_from_logcat_message(line):
    time_end_index = len('00-00 00:00:00.000')
    time_format = '%m-%d %H:%M:%S.%f'
    time_str = line[0:time_end_index] + '000'
    time_seconds = datetime.datetime.strptime(time_str, time_format).timestamp()
    return int(time_seconds * 1000)


def is_app_displayed_logcat_message(line, options):
    substring = 'Displayed %s' % adb_utils.get_component_name(
        options.app_id, options.main_activity)
    return substring in line


def is_app_fully_drawn_logcat_message(line, options):
    return re.search(options.fully_drawn_logcat_message, line)


def add_data(data_total, data):
    for key, value in data.items():
        if key == 'app_id':
            assert data_total.get(key, value) == value
            data_total[key] = value
        if key == 'time':
            continue
        if key in data_total:
            if key == 'app_id':
                assert data_total[key] == value
            else:
                existing_value = data_total[key]
                assert isinstance(value, int)
                assert isinstance(existing_value, list)
                existing_value.append(value)
        else:
            assert isinstance(value, int), key
            data_total[key] = [value]


def compute_data(launch_activity_result, logcat, perfetto_trace_path, options):
    minfl, majfl = adb_utils.get_minor_major_page_faults(
        options.app_id, options.device_id)
    meminfo = adb_utils.get_meminfo(options.app_id, options.device_id)
    data = {
        'app_id': options.app_id,
        'time': time.ctime(time.time()),
        'minfl': minfl,
        'majfl': majfl
    }
    data.update(meminfo)
    startup_data = compute_startup_data(launch_activity_result, logcat,
                                        perfetto_trace_path, options)
    return data | startup_data


def compute_startup_data(launch_activity_result, logcat, perfetto_trace_path,
                         options):
    time_to_first_frame = launch_activity_result.get('total_time')
    startup_data = {'adb_startup': time_to_first_frame}

    # Time to fully drawn.
    if options.fully_drawn_logcat_message:
        startup_data['time_to_fully_drawn'] = \
            compute_time_to_fully_drawn_from_time_to_first_frame(logcat, options) \
                + time_to_first_frame

    # Perfetto stats.
    perfetto_startup_data = {}
    if options.perfetto:
        TraceProcessor = perfetto_utils.get_trace_processor()
        trace_processor = TraceProcessor(file_path=perfetto_trace_path)

        # Compute time to first frame according to the builtin android_startup
        # metric.
        startup_metric = trace_processor.metric(['android_startup'])
        time_to_first_frame_ms = \
            startup_metric.android_startup.startup[0].to_first_frame.dur_ms
        perfetto_startup_data['perfetto_startup'] = round(
            time_to_first_frame_ms)

        if not options.hot_startup:
            # Compute time to first and last doFrame event.
            bind_application_slice = perfetto_utils.find_unique_slice_by_name(
                'bindApplication', options, trace_processor)
            activity_start_slice = perfetto_utils.find_unique_slice_by_name(
                'activityStart', options, trace_processor)
            do_frame_slices = perfetto_utils.find_slices_by_name(
                'Choreographer#doFrame', options, trace_processor)
            first_do_frame_slice = next(do_frame_slices)
            *_, last_do_frame_slice = do_frame_slices

            perfetto_startup_data.update({
                'time_to_first_choreographer_do_frame_ms':
                    round(
                        perfetto_utils.get_slice_end_since_start(
                            first_do_frame_slice, bind_application_slice)),
                'time_to_last_choreographer_do_frame_ms':
                    round(
                        perfetto_utils.get_slice_end_since_start(
                            last_do_frame_slice, bind_application_slice))
            })

    # Return combined startup data.
    return startup_data | perfetto_startup_data


def write_data_to_dir(out_dir, data):
    data_path = os.path.join(out_dir, 'data.txt')
    write_data_to_file(data_path, data)


def write_data_to_file(out_file, data):
    with open(out_file, 'w') as f:
        for key, value in data.items():
            f.write('%s=%s\n' % (key, str(value)))


def parse_options(argv):
    result = argparse.ArgumentParser(
        description='Generate a perfetto trace file.')
    result.add_argument('--app-id',
                        help='The application ID of interest',
                        required=True)
    result.add_argument('--aot',
                        help='Enable force compilation',
                        default=False,
                        action='store_true')
    result.add_argument('--apk', help='Path to the .apk')
    result.add_argument('--apks', help='Path to the .apks')
    result.add_argument('--bundle', help='Path to the .aab')
    result.add_argument('--capture-screen',
                        help='Take a screenshot after each test',
                        default=False,
                        action='store_true')
    result.add_argument('--cooldown',
                        help='Seconds to wait before running each iteration',
                        default=0,
                        type=int)
    result.add_argument('--device-id', help='Device id (e.g., emulator-5554).')
    result.add_argument('--device-pin', help='Device pin code (e.g., 1234)')
    result.add_argument('--fully-drawn-logcat-filter',
                        help='Logcat filter for the fully drawn message '
                        '(e.g., "tag:I")')
    result.add_argument('--fully-drawn-logcat-message',
                        help='Logcat message that indicates that the app is '
                        'fully drawn (regexp)')
    result.add_argument('--grant-post-notification-permission',
                        help='Grants the android.permission.POST_NOTIFICATIONS '
                        'permission before launching the app',
                        default=False,
                        action='store_true')
    result.add_argument('--hot-startup',
                        help='Measure hot startup instead of cold startup',
                        default=False,
                        action='store_true')
    result.add_argument('--intent-data-uri',
                        help='Value to use for the -d argument to the intent '
                        'that is used to launch the app')
    result.add_argument('--iterations',
                        help='Number of traces to generate',
                        default=1,
                        type=int)
    result.add_argument('--main-activity',
                        help='Main activity class name',
                        required=True)
    result.add_argument('--no-perfetto',
                        help='Disables perfetto trace generation',
                        action='store_true',
                        default=False)
    result.add_argument('--out', help='File to store result in')
    result.add_argument('--out-dir',
                        help='Directory to store trace files in',
                        required=True)
    result.add_argument('--baseline-profile',
                        help='Baseline profile (.prof) in binary format')
    result.add_argument('--baseline-profile-metadata',
                        help='Baseline profile metadata (.profm) in binary '
                        'format')
    result.add_argument('--baseline-profile-install',
                        help='Whether to install profile using adb or '
                        'profileinstaller',
                        choices=['adb', 'profileinstaller'],
                        default='profileinstaller')
    result.add_argument('--startup-duration',
                        help='Duration in seconds before shutting down app',
                        default=15,
                        type=int)
    options, args = result.parse_known_args(argv)
    setattr(options, 'perfetto', not options.no_perfetto)

    paths = [
        path for path in [options.apk, options.apks, options.bundle]
        if path is not None
    ]
    assert len(paths) == 1, 'Expected exactly one .apk, .apks, or .aab file.'

    # Build .apks file up front to avoid building the bundle upon each install.
    if options.bundle:
        os.makedirs(options.out_dir, exist_ok=True)
        options.apks = os.path.join(options.out_dir, 'Bundle.apks')
        adb_utils.build_apks_from_bundle(options.bundle,
                                         options.apks,
                                         overwrite=True)
        del options.bundle

    # Profile is only used with --aot.
    assert options.aot or not options.baseline_profile

    # Fully drawn logcat filter and message is absent or both present.
    assert (options.fully_drawn_logcat_filter is None) == \
        (options.fully_drawn_logcat_message is None)

    return options, args


def global_setup(options):
    # If there is no cooldown then unlock the screen once. Otherwise we turn off
    # the screen during the cooldown and unlock the screen before each iteration.
    teardown_options = None
    if options.cooldown == 0:
        teardown_options = adb_utils.prepare_for_interaction_with_device(
            options.device_id, options.device_pin)
        assert adb_utils.get_screen_state(options.device_id).is_on_or_unknown()
    else:
        adb_utils.ensure_screen_off(options.device_id)
    return teardown_options


def global_teardown(options, teardown_options):
    if options.cooldown == 0:
        adb_utils.teardown_after_interaction_with_device(
            teardown_options, options.device_id)
    else:
        assert teardown_options is None


def main(argv):
    (options, args) = parse_options(argv)
    with utils.TempDir() as tmp_dir:
        apk_or_apks = {'apk': options.apk, 'apks': options.apks}
        if options.baseline_profile \
            and options.baseline_profile_install == 'profileinstaller':
            assert not options.apks, 'Unimplemented'
            apk_or_apks['apk'] = apk_utils.add_baseline_profile_to_apk(
                options.apk, options.baseline_profile,
                options.baseline_profile_metadata, tmp_dir)
        teardown_options = global_setup(options)
        run_all(apk_or_apks, options, tmp_dir)
        global_teardown(options, teardown_options)


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