// 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:math' as math;
import 'dart:typed_data';

import 'package:flutter/foundation.dart' show kDebugMode;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

import 'package:microbenchmarks/common.dart';

List<Object> _makeTestBuffer(int size) {
  final List<Object> answer = <Object>[];
  for (int i = 0; i < size; ++i) {
    switch (i % 9) {
      case 0:
        answer.add(1);
        break;
      case 1:
        answer.add(math.pow(2, 65));
        break;
      case 2:
        answer.add(1234.0);
        break;
      case 3:
        answer.add(null);
        break;
      case 4:
        answer.add(<int>[1234]);
        break;
      case 5:
        answer.add(<String, int>{'hello': 1234});
        break;
      case 6:
        answer.add('this is a test');
        break;
      case 7:
        answer.add(true);
        break;
      case 8:
        answer.add(Uint8List(64));
        break;
    }
  }
  return answer;
}

Future<double> _runBasicStandardSmall(
    BasicMessageChannel<Object> basicStandard, int count) async {
  final Stopwatch watch = Stopwatch();
  watch.start();
  for (int i = 0; i < count; ++i) {
    await basicStandard.send(1234);
  }
  watch.stop();
  return watch.elapsedMicroseconds / count;
}

Future<double> _runBasicStandardLarge(BasicMessageChannel<Object> basicStandard,
    List<Object> largeBuffer, int count) async {
  int size = 0;
  final Stopwatch watch = Stopwatch();
  watch.start();
  for (int i = 0; i < count; ++i) {
    final List<Object> result =
        await basicStandard.send(largeBuffer) as List<Object>;
    // This check should be tiny compared to the actual channel send/receive.
    size += (result == null) ? 0 : result.length;
  }
  watch.stop();

  if (size != largeBuffer.length * count) {
    throw Exception(
      "There is an error with the echo channel, the results don't add up: $size",
    );
  }

  return watch.elapsedMicroseconds / count;
}

Future<double> _runBasicBinary(BasicMessageChannel<ByteData> basicBinary,
    ByteData buffer, int count) async {
  int size = 0;
  final Stopwatch watch = Stopwatch();
  watch.start();
  for (int i = 0; i < count; ++i) {
    final ByteData result = await basicBinary.send(buffer);
    // This check should be tiny compared to the actual channel send/receive.
    size += (result == null) ? 0 : result.lengthInBytes;
  }
  watch.stop();
  if (size != buffer.lengthInBytes * count) {
    throw Exception(
      "There is an error with the echo channel, the results don't add up: $size",
    );
  }

  return watch.elapsedMicroseconds / count;
}

Future<void> _runTests() async {
  if (kDebugMode) {
    throw Exception(
      "Must be run in profile mode! Use 'flutter run --profile'.",
    );
  }

  const BasicMessageChannel<Object> basicStandard = BasicMessageChannel<Object>(
    'dev.flutter.echo.basic.standard',
    StandardMessageCodec(),
  );
  const BasicMessageChannel<ByteData> basicBinary =
      BasicMessageChannel<ByteData>(
    'dev.flutter.echo.basic.binary',
    BinaryCodec(),
  );

  /// WARNING: Don't change the following line of code, it will invalidate
  /// `Large` tests.  Instead make a different test.  The size of largeBuffer
  /// serialized is 14214 bytes.
  final List<Object> largeBuffer = _makeTestBuffer(1000);
  final ByteData largeBufferBytes =
      const StandardMessageCodec().encodeMessage(largeBuffer);
  final ByteData oneMB = ByteData(1024 * 1024);

  const int numMessages = 2500;

  final BenchmarkResultPrinter printer = BenchmarkResultPrinter();
  await _runBasicStandardSmall(basicStandard, 1); // Warmup.
  printer.addResult(
    description: 'BasicMessageChannel/StandardMessageCodec/Flutter->Host/Small',
    value: await _runBasicStandardSmall(basicStandard, numMessages),
    unit: 'µs',
    name: 'platform_channel_basic_standard_2host_small',
  );
  await _runBasicStandardLarge(basicStandard, largeBuffer, 1); // Warmup.
  printer.addResult(
    description: 'BasicMessageChannel/StandardMessageCodec/Flutter->Host/Large',
    value:
        await _runBasicStandardLarge(basicStandard, largeBuffer, numMessages),
    unit: 'µs',
    name: 'platform_channel_basic_standard_2host_large',
  );
  await _runBasicBinary(basicBinary, largeBufferBytes, 1); // Warmup.
  printer.addResult(
    description: 'BasicMessageChannel/BinaryCodec/Flutter->Host/Large',
    value: await _runBasicBinary(basicBinary, largeBufferBytes, numMessages),
    unit: 'µs',
    name: 'platform_channel_basic_binary_2host_large',
  );
  await _runBasicBinary(basicBinary, oneMB, 1); // Warmup.
  printer.addResult(
    description: 'BasicMessageChannel/BinaryCodec/Flutter->Host/1MB',
    value: await _runBasicBinary(basicBinary, oneMB, numMessages),
    unit: 'µs',
    name: 'platform_channel_basic_binary_2host_1MB',
  );
  printer.printToStdout();
}

class _BenchmarkWidget extends StatefulWidget {
  const _BenchmarkWidget(this.tests, {Key key}) : super(key: key);

  final Future<void> Function() tests;

  @override
  _BenchmarkWidgetState createState() => _BenchmarkWidgetState();
}

class _BenchmarkWidgetState extends State<_BenchmarkWidget> {
  @override
  void initState() {
    widget.tests();
    super.initState();
  }

  @override
  Widget build(BuildContext context) => Container();
}

void main() {
  runApp(const _BenchmarkWidget(_runTests));
}
