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

import 'package:flutter/material.dart';

import 'pair.dart';

enum TestStatus { ok, pending, failed, complete }

typedef TestStep = Future<TestStepResult> Function();

const String nothing = '-';

/// Result of a test step checking a nested communication handshake
/// between the Flutter app and the platform:
///
/// - The Flutter app sends a message to the platform.
/// - The platform, on receipt, echos the message back to Flutter in a separate message.
/// - The Flutter app records the incoming message echo and replies.
/// - The platform, on receipt of reply, echos the reply back to Flutter in a separate message.
/// - The Flutter app records the incoming reply echo.
/// - The platform finally replies to the original message with another echo.
class TestStepResult {
  const TestStepResult(
    this.name,
    this.description,
    this.status, {
    this.messageSent = nothing,
    this.messageEcho = nothing,
    this.messageReceived = nothing,
    this.replyEcho = nothing,
    this.error = nothing,
  });

  factory TestStepResult.fromSnapshot(AsyncSnapshot<TestStepResult> snapshot) {
    switch (snapshot.connectionState) {
      case ConnectionState.none:
        return const TestStepResult('Not started', nothing, TestStatus.ok);
      case ConnectionState.waiting:
        return const TestStepResult('Executing', nothing, TestStatus.pending);
      case ConnectionState.done:
        if (snapshot.hasData) {
          return snapshot.data!;
        }
        return snapshot.error! as TestStepResult;
      default:
        throw 'Unsupported state ${snapshot.connectionState}';
    }
  }

  final String name;
  final String description;
  final TestStatus status;
  final dynamic messageSent;
  final dynamic messageEcho;
  final dynamic messageReceived;
  final dynamic replyEcho;
  final dynamic error;

  static const TextStyle bold = TextStyle(fontWeight: FontWeight.bold);
  static const TestStepResult complete = TestStepResult(
    'Test complete',
    nothing,
    TestStatus.complete,
  );

  Widget asWidget(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Text('Step: $name', style: bold),
        Text(description),
        const Text(' '),
        Text('Msg sent: ${_toString(messageSent)}'),
        Text('Msg rvcd: ${_toString(messageReceived)}'),
        Text('Reply echo: ${_toString(replyEcho)}'),
        Text('Msg echo: ${_toString(messageEcho)}'),
        Text('Error: ${_toString(error)}'),
        const Text(' '),
        Text(
          status.toString().substring('TestStatus.'.length),
          key: ValueKey<String>(
              status == TestStatus.pending ? 'nostatus' : 'status'),
          style: bold,
        ),
      ],
    );
  }
}

Future<TestStepResult> resultOfHandshake(
  String name,
  String description,
  dynamic message,
  List<dynamic> received,
  dynamic messageEcho,
  dynamic error,
) async {
  assert(message != nothing);
  while (received.length < 2)
    received.add(nothing);
  TestStatus status;
  if (!_deepEquals(messageEcho, message) ||
      received.length != 2 ||
      !_deepEquals(received[0], message) ||
      !_deepEquals(received[1], message)) {
    status = TestStatus.failed;
  } else if (error != nothing) {
    status = TestStatus.failed;
  } else {
    status = TestStatus.ok;
  }
  return TestStepResult(
    name,
    description,
    status,
    messageSent: message,
    messageEcho: messageEcho,
    messageReceived: received[0],
    replyEcho: received[1],
    error: error,
  );
}

String _toString(dynamic message) {
  if (message is ByteData)
    return message.buffer
        .asUint8List(message.offsetInBytes, message.lengthInBytes)
        .toString();
  else
    return '$message';
}

bool _deepEquals(dynamic a, dynamic b) {
  if (a == b)
    return true;
  if (a is double && a.isNaN)
    return b is double && b.isNaN;
  if (a is ByteData)
    return b is ByteData && _deepEqualsByteData(a, b);
  if (a is List)
    return b is List && _deepEqualsList(a, b);
  if (a is Map)
    return b is Map && _deepEqualsMap(a, b);
  if (a is Pair)
    return b is Pair && _deepEqualsPair(a, b);
  return false;
}

bool _deepEqualsByteData(ByteData a, ByteData b) {
  return _deepEqualsList(
    a.buffer.asUint8List(a.offsetInBytes, a.lengthInBytes),
    b.buffer.asUint8List(b.offsetInBytes, b.lengthInBytes),
  );
}

bool _deepEqualsList(List<dynamic> a, List<dynamic> b) {
  if (a.length != b.length)
    return false;
  for (int i = 0; i < a.length; i++) {
    if (!_deepEquals(a[i], b[i]))
      return false;
  }
  return true;
}

bool _deepEqualsMap(Map<dynamic, dynamic> a, Map<dynamic, dynamic> b) {
  if (a.length != b.length)
    return false;
  for (final dynamic key in a.keys) {
    if (!b.containsKey(key) || !_deepEquals(a[key], b[key]))
      return false;
  }
  return true;
}

bool _deepEqualsPair(Pair a, Pair b) {
  return _deepEquals(a.left, b.left) && _deepEquals(a.right, b.right);
}
