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

import 'package:collection/collection.dart' show ListEquality, MapEquality;

import 'package:flutter_devicelab/framework/devices.dart';
import 'package:meta/meta.dart';

import 'common.dart';

void main() {
  group('device', () {
    late Device device;

    setUp(() {
      FakeDevice.resetLog();
      device = FakeDevice(deviceId: 'fakeDeviceId');
    });

    tearDown(() {
      FakeDevice.resetLog();
    });

    group('cpu check', () {
      test('arm64', () async {
        FakeDevice.pretendArm64();
        final androidDevice = device as AndroidDevice;
        expect(await androidDevice.isArm64(), isTrue);
        expectLog(<CommandArgs>[
          cmd(
            command: 'getprop',
            arguments: <String>[
              'ro.bootimage.build.fingerprint',
              ';',
              'getprop',
              'ro.build.version.release',
              ';',
              'getprop',
              'ro.build.version.sdk',
            ],
          ),
          cmd(command: 'getprop', arguments: <String>['ro.product.cpu.abi']),
        ]);
      });
    });

    group('isAwake/isAsleep', () {
      test('reads Awake', () async {
        FakeDevice.pretendAwake();
        expect(await device.isAwake(), isTrue);
        expect(await device.isAsleep(), isFalse);
      });

      test('reads Awake - samsung devices', () async {
        FakeDevice.pretendAwakeSamsung();
        expect(await device.isAwake(), isTrue);
        expect(await device.isAsleep(), isFalse);
      });

      test('reads Asleep', () async {
        FakeDevice.pretendAsleep();
        expect(await device.isAwake(), isFalse);
        expect(await device.isAsleep(), isTrue);
      });
    });

    group('togglePower', () {
      test('sends power event', () async {
        await device.togglePower();
        expectLog(<CommandArgs>[
          cmd(
            command: 'getprop',
            arguments: <String>[
              'ro.bootimage.build.fingerprint',
              ';',
              'getprop',
              'ro.build.version.release',
              ';',
              'getprop',
              'ro.build.version.sdk',
            ],
          ),
          cmd(command: 'input', arguments: <String>['keyevent', '26']),
        ]);
      });
    });

    group('wakeUp', () {
      test('when awake', () async {
        FakeDevice.pretendAwake();
        await device.wakeUp();
        expectLog(<CommandArgs>[
          cmd(
            command: 'getprop',
            arguments: <String>[
              'ro.bootimage.build.fingerprint',
              ';',
              'getprop',
              'ro.build.version.release',
              ';',
              'getprop',
              'ro.build.version.sdk',
            ],
          ),
          cmd(command: 'dumpsys', arguments: <String>['power']),
        ]);
      });

      test('when asleep', () async {
        FakeDevice.pretendAsleep();
        await device.wakeUp();
        expectLog(<CommandArgs>[
          cmd(
            command: 'getprop',
            arguments: <String>[
              'ro.bootimage.build.fingerprint',
              ';',
              'getprop',
              'ro.build.version.release',
              ';',
              'getprop',
              'ro.build.version.sdk',
            ],
          ),
          cmd(command: 'dumpsys', arguments: <String>['power']),
          cmd(command: 'input', arguments: <String>['keyevent', '26']),
        ]);
      });
    });

    group('sendToSleep', () {
      test('when asleep', () async {
        FakeDevice.pretendAsleep();
        await device.sendToSleep();
        expectLog(<CommandArgs>[
          cmd(
            command: 'getprop',
            arguments: <String>[
              'ro.bootimage.build.fingerprint',
              ';',
              'getprop',
              'ro.build.version.release',
              ';',
              'getprop',
              'ro.build.version.sdk',
            ],
          ),
          cmd(command: 'dumpsys', arguments: <String>['power']),
        ]);
      });

      test('when awake', () async {
        FakeDevice.pretendAwake();
        await device.sendToSleep();
        expectLog(<CommandArgs>[
          cmd(
            command: 'getprop',
            arguments: <String>[
              'ro.bootimage.build.fingerprint',
              ';',
              'getprop',
              'ro.build.version.release',
              ';',
              'getprop',
              'ro.build.version.sdk',
            ],
          ),
          cmd(command: 'dumpsys', arguments: <String>['power']),
          cmd(command: 'input', arguments: <String>['keyevent', '26']),
        ]);
      });
    });

    group('unlock', () {
      test('sends unlock event', () async {
        FakeDevice.pretendAwake();
        await device.unlock();
        expectLog(<CommandArgs>[
          cmd(
            command: 'getprop',
            arguments: <String>[
              'ro.bootimage.build.fingerprint',
              ';',
              'getprop',
              'ro.build.version.release',
              ';',
              'getprop',
              'ro.build.version.sdk',
            ],
          ),
          cmd(command: 'dumpsys', arguments: <String>['power']),
          cmd(command: 'input', arguments: <String>['keyevent', '82']),
        ]);
      });
    });

    group('adb', () {
      test('tap', () async {
        FakeDevice.resetLog();
        await device.tap(100, 200);
        expectLog(<CommandArgs>[
          cmd(command: 'input', arguments: <String>['tap', '100', '200']),
        ]);
      });

      test('awaitDevice', () async {
        FakeDevice.resetLog();
        // The expected value from `adb shell getprop sys.boot_completed`
        FakeDevice.output = '1';
        await device.awaitDevice();
        expectLog(<CommandArgs>[
          cmd(
            command: 'adb',
            environment: <String, String>{FakeDevice.canFailKey: 'false'},
            arguments: <String>['-s', device.deviceId, 'wait-for-device'],
          ),
          cmd(
            command: 'adb',
            environment: <String, String>{FakeDevice.canFailKey: 'false'},
            arguments: <String>['-s', device.deviceId, 'shell', 'getprop sys.boot_completed'],
          ),
        ]);
      });

      test('reboot', () async {
        FakeDevice.resetLog();
        await device.reboot();
        expectLog(<CommandArgs>[
          cmd(
            command: 'adb',
            environment: <String, String>{FakeDevice.canFailKey: 'false'},
            arguments: <String>['-s', device.deviceId, 'reboot'],
          ),
        ]);
      });

      test('clearLog', () async {
        FakeDevice.resetLog();
        await device.clearLogs();
        expectLog(<CommandArgs>[
          cmd(
            command: 'adb',
            environment: <String, String>{FakeDevice.canFailKey: 'true'},
            arguments: <String>['-s', device.deviceId, 'logcat', '-c'],
          ),
        ]);
      });

      test('startLoggingToSink calls adb', () async {
        FakeDevice.resetLog();
        await device.startLoggingToSink(IOSink(_MemoryIOSink()));
        expectLog(<CommandArgs>[
          cmd(
            command: 'adb',
            environment: <String, String>{FakeDevice.canFailKey: 'true'},
            arguments: <String>['-s', device.deviceId, 'logcat', '--clear'],
          ),
        ]);
      });
    });
  });
}

void expectLog(List<CommandArgs> log) {
  expect(FakeDevice.commandLog, log);
}

CommandArgs cmd({
  required String command,
  List<String>? arguments,
  Map<String, String>? environment,
}) {
  return CommandArgs(command: command, arguments: arguments, environment: environment);
}

@immutable
class CommandArgs {
  const CommandArgs({required this.command, this.arguments, this.environment});

  final String command;
  final List<String>? arguments;
  final Map<String, String>? environment;

  @override
  String toString() =>
      'CommandArgs(command: $command, arguments: $arguments, environment: $environment)';

  @override
  bool operator ==(Object other) {
    if (other.runtimeType != CommandArgs) {
      return false;
    }
    return other is CommandArgs &&
        other.command == command &&
        const ListEquality<String>().equals(other.arguments, arguments) &&
        const MapEquality<String, String>().equals(other.environment, environment);
  }

  @override
  int get hashCode {
    return Object.hash(
      command,
      Object.hashAll(arguments ?? const <String>[]),
      Object.hashAllUnordered(environment?.keys ?? const <String>[]),
      Object.hashAllUnordered(environment?.values ?? const <String>[]),
    );
  }
}

class FakeDevice extends AndroidDevice {
  FakeDevice({required super.deviceId});

  static const String canFailKey = 'canFail';

  static String output = '';

  static List<CommandArgs> commandLog = <CommandArgs>[];

  static void resetLog() {
    commandLog.clear();
  }

  static void pretendAwake() {
    // Emit an integer value in addition to the state string to ensure only
    // the state string is matched.
    //
    // Regression testing for https://github.com/flutter/flutter/issues/174952.
    output = '''
      mWakefulness=1
      mWakefulness=Awake

    ''';
  }

  static void pretendAwakeSamsung() {
    // Emit an integer value in addition to the state string to ensure only
    // the state string is matched.
    //
    // Regression testing for https://github.com/flutter/flutter/issues/174952.
    output = '''
      getWakefulnessLocked()=1
      getWakefulnessLocked()=Awake

    ''';
  }

  static void pretendAsleep() {
    // Emit an integer value in addition to the state string to ensure only
    // the state string is matched.
    //
    // Regression testing for https://github.com/flutter/flutter/issues/174952.
    output = '''
      mWakefulness=0
      mWakefulness=Asleep

    ''';
  }

  static void pretendArm64() {
    output = '''
      arm64
    ''';
  }

  @override
  Future<String> adb(
    List<String> arguments, {
    Map<String, String>? environment,
    bool silent = false,
    bool canFail = false,
  }) async {
    environment ??= <String, String>{};
    commandLog.add(
      CommandArgs(
        command: 'adb',
        // ignore: prefer_spread_collections
        arguments: <String>['-s', deviceId]..addAll(arguments),
        environment: environment..putIfAbsent('canFail', () => '$canFail'),
      ),
    );
    return output;
  }

  @override
  Future<String> shellEval(
    String command,
    List<String> arguments, {
    Map<String, String>? environment,
    bool silent = false,
  }) async {
    commandLog.add(CommandArgs(command: command, arguments: arguments, environment: environment));
    return output;
  }

  @override
  Future<void> shellExec(
    String command,
    List<String> arguments, {
    Map<String, String>? environment,
    bool silent = false,
  }) async {
    commandLog.add(CommandArgs(command: command, arguments: arguments, environment: environment));
  }
}

/// An IOSink that collects whatever is written to it.
/// Inspired by packages/flutter_tools/lib/src/base/net.dart
class _MemoryIOSink implements IOSink {
  @override
  Encoding encoding = utf8;

  final BytesBuilder writes = BytesBuilder(copy: false);

  @override
  void add(List<int> data) {
    writes.add(data);
  }

  @override
  Future<void> addStream(Stream<List<int>> stream) {
    final completer = Completer<void>();
    stream.listen(add).onDone(completer.complete);
    return completer.future;
  }

  @override
  void writeCharCode(int charCode) {
    add(<int>[charCode]);
  }

  @override
  void write(Object? obj) {
    add(encoding.encode('$obj'));
  }

  @override
  void writeln([Object? obj = '']) {
    add(encoding.encode('$obj\n'));
  }

  @override
  void writeAll(Iterable<dynamic> objects, [String separator = '']) {
    var addSeparator = false;
    for (final dynamic object in objects) {
      if (addSeparator) {
        write(separator);
      }
      write(object);
      addSeparator = true;
    }
  }

  @override
  void addError(dynamic error, [StackTrace? stackTrace]) {
    throw UnimplementedError();
  }

  @override
  Future<void> get done => close();

  @override
  Future<void> close() async {}

  @override
  Future<void> flush() async {}
}
