// 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'],
          ),
        ]);
      });

      test('getMemoryStats throws DeviceException if dumpsys meminfo fails to parse', () {
        FakeDevice.output = 'Some garbage output';
        expect(device.getMemoryStats('com.example'), throwsA(isA<DeviceException>()));
      });

      test('getMemoryStats returns memory stats if dumpsys meminfo parses successfully', () async {
        FakeDevice.resetLog();
        FakeDevice.output = 'TOTAL      12345';
        final Map<String, dynamic> stats = await device.getMemoryStats('com.example');
        expect(stats, <String, dynamic>{'total_kb': 12345});
        expectLog(const <CommandArgs>[
          CommandArgs(command: 'dumpsys', arguments: <String>['meminfo', 'com.example']),
        ]);
      });
    });
  });
}

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 {}
}
