// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:convert';
import 'dart:io';
import 'dart:math' as math;

import '../framework/devices.dart';
import '../framework/framework.dart';
import '../framework/task_result.dart';
import '../framework/utils.dart';
import 'build_test_task.dart';

final Directory galleryDirectory = dir('${flutterDirectory.path}/dev/integration_tests/flutter_gallery');

/// Temp function during gallery tests transition to build+test model.
///
/// https://github.com/flutter/flutter/issues/103542
TaskFunction createGalleryTransitionBuildTest(List<String> args, {bool semanticsEnabled = false}) {
  return GalleryTransitionBuildTest(args, semanticsEnabled: semanticsEnabled).call;
}

TaskFunction createGalleryTransitionTest({bool semanticsEnabled = false}) {
  return GalleryTransitionTest(semanticsEnabled: semanticsEnabled).call;
}

TaskFunction createGalleryTransitionE2EBuildTest(
  List<String> args, {
  bool semanticsEnabled = false,
  bool? enableImpeller,
}) {
  return GalleryTransitionBuildTest(
    args,
    testFile: semanticsEnabled ? 'transitions_perf_e2e_with_semantics' : 'transitions_perf_e2e',
    needFullTimeline: false,
    timelineSummaryFile: 'e2e_perf_summary',
    transitionDurationFile: null,
    timelineTraceFile: null,
    driverFile: 'transitions_perf_e2e_test',
    enableImpeller: enableImpeller,
  ).call;
}

TaskFunction createGalleryTransitionE2ETest({
  bool semanticsEnabled = false,
  bool? enableImpeller,
}) {
  return GalleryTransitionTest(
    testFile: semanticsEnabled
        ? 'transitions_perf_e2e_with_semantics'
        : 'transitions_perf_e2e',
    needFullTimeline: false,
    timelineSummaryFile: 'e2e_perf_summary',
    transitionDurationFile: null,
    timelineTraceFile: null,
    driverFile: 'transitions_perf_e2e_test',
    enableImpeller: enableImpeller,
  ).call;
}

TaskFunction createGalleryTransitionHybridBuildTest(
  List<String> args, {
  bool semanticsEnabled = false,
}) {
  return GalleryTransitionBuildTest(
    args,
    semanticsEnabled: semanticsEnabled,
    driverFile: semanticsEnabled ? 'transitions_perf_hybrid_with_semantics_test' : 'transitions_perf_hybrid_test',
  ).call;
}

TaskFunction createGalleryTransitionHybridTest({bool semanticsEnabled = false}) {
  return GalleryTransitionTest(
    semanticsEnabled: semanticsEnabled,
    driverFile: semanticsEnabled
        ? 'transitions_perf_hybrid_with_semantics_test'
        : 'transitions_perf_hybrid_test',
  ).call;
}

class GalleryTransitionTest {
  GalleryTransitionTest({
    this.semanticsEnabled = false,
    this.testFile = 'transitions_perf',
    this.needFullTimeline = true,
    this.timelineSummaryFile = 'transitions.timeline_summary',
    this.timelineTraceFile = 'transitions.timeline',
    this.transitionDurationFile = 'transition_durations.timeline',
    this.driverFile,
    this.measureCpuGpu = true,
    this.measureMemory = true,
    this.enableImpeller,
  });

  final bool semanticsEnabled;
  final bool needFullTimeline;
  final bool measureCpuGpu;
  final bool measureMemory;
  final bool? enableImpeller;
  final String testFile;
  final String timelineSummaryFile;
  final String? timelineTraceFile;
  final String? transitionDurationFile;
  final String? driverFile;

  Future<TaskResult> call() async {
    final Device device = await devices.workingDevice;
    await device.unlock();
    final String deviceId = device.deviceId;
    final Directory galleryDirectory = dir('${flutterDirectory.path}/dev/integration_tests/flutter_gallery');
    await inDirectory<void>(galleryDirectory, () async {
      String? applicationBinaryPath;
      if (deviceOperatingSystem == DeviceOperatingSystem.android) {
        section('BUILDING APPLICATION');
        await flutter(
          'build',
          options: <String>[
            'apk',
            '--no-android-gradle-daemon',
            '--profile',
            '-t',
            'test_driver/$testFile.dart',
            '--target-platform',
            'android-arm,android-arm64',
          ],
        );
        applicationBinaryPath = 'build/app/outputs/flutter-apk/app-profile.apk';
      }

      final String testDriver = driverFile ?? (semanticsEnabled
          ? '${testFile}_with_semantics_test'
          : '${testFile}_test');
      section('DRIVE START');
      await flutter('drive', options: <String>[
        '--no-dds',
        '--profile',
        if (enableImpeller != null && enableImpeller!) '--enable-impeller',
        if (enableImpeller != null && !enableImpeller!) '--no-enable-impeller',
        if (needFullTimeline)
          '--trace-startup',
        if (applicationBinaryPath != null)
          '--use-application-binary=$applicationBinaryPath'
        else
          ...<String>[
            '-t',
            'test_driver/$testFile.dart',
          ],
        '--driver',
        'test_driver/$testDriver.dart',
        '-d',
        deviceId,
        '-v',
        '--verbose-system-logs'
      ]);
      await flutter('install', options: <String>['--uninstall-only', '-d', deviceId]);
    });

    final String testOutputDirectory = Platform.environment['FLUTTER_TEST_OUTPUTS_DIR'] ?? '${galleryDirectory.path}/build';
    final Map<String, dynamic> summary = json.decode(
      file('$testOutputDirectory/$timelineSummaryFile.json').readAsStringSync(),
    ) as Map<String, dynamic>;

    if (transitionDurationFile != null) {
      final Map<String, dynamic> original = json.decode(
        file('$testOutputDirectory/$transitionDurationFile.json').readAsStringSync(),
      ) as Map<String, dynamic>;
      final Map<String, List<int>> transitions = <String, List<int>>{};
      for (final String key in original.keys) {
        transitions[key] = List<int>.from(original[key] as List<dynamic>);
      }
      summary['transitions'] = transitions;
      summary['missed_transition_count'] = _countMissedTransitions(transitions);
    }

    final bool isAndroid = deviceOperatingSystem == DeviceOperatingSystem.android;
    return TaskResult.success(summary,
      detailFiles: <String>[
        if (transitionDurationFile != null)
          '$testOutputDirectory/$transitionDurationFile.json',
        if (timelineTraceFile != null)
          '$testOutputDirectory/$timelineTraceFile.json',
      ],
      benchmarkScoreKeys: <String>[
        if (transitionDurationFile != null)
          'missed_transition_count',
        'average_frame_build_time_millis',
        'worst_frame_build_time_millis',
        '90th_percentile_frame_build_time_millis',
        '99th_percentile_frame_build_time_millis',
        'average_frame_rasterizer_time_millis',
        'stddev_frame_rasterizer_time_millis',
        'worst_frame_rasterizer_time_millis',
        '90th_percentile_frame_rasterizer_time_millis',
        '99th_percentile_frame_rasterizer_time_millis',
        'average_layer_cache_count',
        '90th_percentile_layer_cache_count',
        '99th_percentile_layer_cache_count',
        'worst_layer_cache_count',
        'average_layer_cache_memory',
        '90th_percentile_layer_cache_memory',
        '99th_percentile_layer_cache_memory',
        'worst_layer_cache_memory',
        'average_picture_cache_count',
        '90th_percentile_picture_cache_count',
        '99th_percentile_picture_cache_count',
        'worst_picture_cache_count',
        'average_picture_cache_memory',
        '90th_percentile_picture_cache_memory',
        '99th_percentile_picture_cache_memory',
        'worst_picture_cache_memory',
        if (measureCpuGpu && !isAndroid) ...<String>[
          // See https://github.com/flutter/flutter/issues/68888
          if (summary['average_cpu_usage'] != null) 'average_cpu_usage',
          if (summary['average_gpu_usage'] != null) 'average_gpu_usage',
        ],
        if (measureMemory && !isAndroid) ...<String>[
          // See https://github.com/flutter/flutter/issues/68888
          if (summary['average_memory_usage'] != null) 'average_memory_usage',
          if (summary['90th_percentile_memory_usage'] != null) '90th_percentile_memory_usage',
          if (summary['99th_percentile_memory_usage'] != null) '99th_percentile_memory_usage',
        ],
      ],
    );
  }
}

class GalleryTransitionBuildTest extends BuildTestTask {
  GalleryTransitionBuildTest(
    super.args, {
    this.semanticsEnabled = false,
    this.testFile = 'transitions_perf',
    this.needFullTimeline = true,
    this.timelineSummaryFile = 'transitions.timeline_summary',
    this.timelineTraceFile = 'transitions.timeline',
    this.transitionDurationFile = 'transition_durations.timeline',
    this.driverFile,
    this.measureCpuGpu = true,
    this.measureMemory = true,
    this.enableImpeller,
  }) : super(workingDirectory: galleryDirectory);

  final bool semanticsEnabled;
  final bool needFullTimeline;
  final bool measureCpuGpu;
  final bool measureMemory;
  final bool? enableImpeller;
  final String testFile;
  final String timelineSummaryFile;
  final String? timelineTraceFile;
  final String? transitionDurationFile;
  final String? driverFile;

  final String testOutputDirectory = Platform.environment['FLUTTER_TEST_OUTPUTS_DIR'] ?? '${galleryDirectory.path}/build';

  @override
  void copyArtifacts() {
    if (applicationBinaryPath == null) {
      return;
    }
    if (deviceOperatingSystem == DeviceOperatingSystem.android) {
      copy(
        file('${galleryDirectory.path}/build/app/outputs/flutter-apk/app-profile.apk'),
        Directory(applicationBinaryPath!),
      );
    } else if (deviceOperatingSystem == DeviceOperatingSystem.ios) {
      recursiveCopy(
        Directory('${galleryDirectory.path}/build/ios/iphoneos'),
        Directory(applicationBinaryPath!),
      );
    }
  }

  @override
  List<String> getBuildArgs(DeviceOperatingSystem deviceOperatingSystem) {
    if (deviceOperatingSystem == DeviceOperatingSystem.android) {
      return <String>[
        'apk',
        '--no-android-gradle-daemon',
        '--profile',
        '-t',
        'test_driver/$testFile.dart',
        '--target-platform',
        'android-arm,android-arm64',
      ];
    } else if (deviceOperatingSystem == DeviceOperatingSystem.ios) {
      return <String>[
        'ios',
        '--codesign',
        '--profile',
        '-t',
        'test_driver/$testFile.dart',
      ];
    }
    throw Exception('$deviceOperatingSystem has no build configuration');
  }

  @override
  List<String> getTestArgs(DeviceOperatingSystem deviceOperatingSystem, String deviceId) {
    final String testDriver = driverFile ?? (semanticsEnabled ? '${testFile}_with_semantics_test' : '${testFile}_test');
    return <String>[
      '--no-dds',
      '--profile',
      if (enableImpeller != null && enableImpeller!) '--enable-impeller',
      if (enableImpeller != null && !enableImpeller!) '--no-enable-impeller',
      if (needFullTimeline) '--trace-startup',
      '-t',
      'test_driver/$testFile.dart',
      if (applicationBinaryPath != null) '--use-application-binary=${getApplicationBinaryPath()}',
      '--driver',
      'test_driver/$testDriver.dart',
      '-d',
      deviceId,
    ];
  }

  @override
  Future<TaskResult> parseTaskResult() async {
    final Map<String, dynamic> summary = json.decode(
      file('$testOutputDirectory/$timelineSummaryFile.json').readAsStringSync(),
    ) as Map<String, dynamic>;

    if (transitionDurationFile != null) {
      final Map<String, dynamic> original = json.decode(
        file('$testOutputDirectory/$transitionDurationFile.json').readAsStringSync(),
      ) as Map<String, dynamic>;
      final Map<String, List<int>> transitions = <String, List<int>>{};
      for (final String key in original.keys) {
        transitions[key] = List<int>.from(original[key] as List<dynamic>);
      }
      summary['transitions'] = transitions;
      summary['missed_transition_count'] = _countMissedTransitions(transitions);
    }

    final bool isAndroid = deviceOperatingSystem == DeviceOperatingSystem.android;
    return TaskResult.success(
      summary,
      detailFiles: <String>[
        if (transitionDurationFile != null) '$testOutputDirectory/$transitionDurationFile.json',
        if (timelineTraceFile != null) '$testOutputDirectory/$timelineTraceFile.json',
      ],
      benchmarkScoreKeys: <String>[
        if (transitionDurationFile != null) 'missed_transition_count',
        'average_frame_build_time_millis',
        'worst_frame_build_time_millis',
        '90th_percentile_frame_build_time_millis',
        '99th_percentile_frame_build_time_millis',
        'average_frame_rasterizer_time_millis',
        'worst_frame_rasterizer_time_millis',
        '90th_percentile_frame_rasterizer_time_millis',
        '99th_percentile_frame_rasterizer_time_millis',
        'average_layer_cache_count',
        '90th_percentile_layer_cache_count',
        '99th_percentile_layer_cache_count',
        'worst_layer_cache_count',
        'average_layer_cache_memory',
        '90th_percentile_layer_cache_memory',
        '99th_percentile_layer_cache_memory',
        'worst_layer_cache_memory',
        'average_picture_cache_count',
        '90th_percentile_picture_cache_count',
        '99th_percentile_picture_cache_count',
        'worst_picture_cache_count',
        'average_picture_cache_memory',
        '90th_percentile_picture_cache_memory',
        '99th_percentile_picture_cache_memory',
        'worst_picture_cache_memory',
        if (measureCpuGpu && !isAndroid) ...<String>[
          // See https://github.com/flutter/flutter/issues/68888
          if (summary['average_cpu_usage'] != null) 'average_cpu_usage',
          if (summary['average_gpu_usage'] != null) 'average_gpu_usage',
        ],
        if (measureMemory && !isAndroid) ...<String>[
          // See https://github.com/flutter/flutter/issues/68888
          if (summary['average_memory_usage'] != null) 'average_memory_usage',
          if (summary['90th_percentile_memory_usage'] != null) '90th_percentile_memory_usage',
          if (summary['99th_percentile_memory_usage'] != null) '99th_percentile_memory_usage',
        ],
      ],
    );
  }

  @override
  String getApplicationBinaryPath() {
    if (deviceOperatingSystem == DeviceOperatingSystem.android) {
      return '$applicationBinaryPath/app-profile.apk';
    } else if (deviceOperatingSystem == DeviceOperatingSystem.ios) {
      return '$applicationBinaryPath/Flutter Gallery.app';
    } else {
      return applicationBinaryPath!;
    }
  }
}

int _countMissedTransitions(Map<String, List<int>> transitions) {
  const int kTransitionBudget = 100000; // µs
  int count = 0;
  transitions.forEach((String demoName, List<int> durations) {
    final int longestDuration = durations.reduce(math.max);
    if (longestDuration > kTransitionBudget) {
      print('$demoName missed transition time budget ($longestDuration µs > $kTransitionBudget µs)');
      count++;
    }
  });
  return count;
}
