// Copyright 2013 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.
// @dart = 2.4
import 'dart:async';
import 'dart:io';

import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:fuchsia_ctl/fuchsia_ctl.dart';
import 'package:mockito/mockito.dart';
import 'package:process/process.dart';
import 'package:test/test.dart';

import 'fakes.dart';

void main() {
  const String deviceName = 'some-name-to-use';
  FakeSshKeyManager sshKeyManager;
  final MemoryFileSystem fs = MemoryFileSystem();
  FakeTar tar;
  MockProcessManager processManager;
  SshKeyManagerProvider sshKeyManagerProvider;

  setUp(() {
    processManager = MockProcessManager();
    sshKeyManager = const FakeSshKeyManager(true);
    sshKeyManagerProvider = ({
      ProcessManager processManager,
      FileSystem fs,
      String publicKeyPath,
    }) {
      return sshKeyManager;
    };
  });

  test('Tar fails', () async {
    tar = FakeTar(false, fs);
    when(processManager.start(any)).thenAnswer((_) async {
      return FakeProcess(0, <String>['Good job'], <String>['']);
    });

    final ImagePaver paver = ImagePaver(
      tar: tar,
      sshKeyManagerProvider: sshKeyManagerProvider,
      fs: fs,
      processManager: processManager,
    );

    final OperationResult result = await paver.pave(
      'generic-x64.tgz',
      deviceName,
      verbose: false,
    );

    verifyNever(processManager.start(any));
    expect(result.success, false);
    expect(result.error, 'tar failed');
  });

  test('Ssh fails', () async {
    sshKeyManager = const FakeSshKeyManager(false);
    tar = FakeTar(true, fs);
    when(processManager.start(any)).thenAnswer((_) async {
      return FakeProcess(0, <String>['Good job'], <String>['']);
    });

    final ImagePaver paver = ImagePaver(
      tar: tar,
      sshKeyManagerProvider: sshKeyManagerProvider,
      fs: fs,
      processManager: processManager,
    );

    final OperationResult result = await paver.pave(
      'generic-x64.tgz',
      deviceName,
      verbose: false,
    );

    verifyNever(processManager.start(any));
    expect(result.success, false);
    expect(result.error, 'ssh failed');
  });

  test('Pave times out', () async {
    tar = FakeTar(true, fs);

    when(processManager.start(any)).thenAnswer((_) async {
      return Future<Process>.delayed(const Duration(milliseconds: 10), () {
        return FakeProcess(0, <String>['Good job'], <String>['']);
      });
    });

    final ImagePaver paver = ImagePaver(
      tar: tar,
      sshKeyManagerProvider: sshKeyManagerProvider,
      fs: fs,
      processManager: processManager,
    );

    try {
      await paver.pave(
        'generic-x64.tgz',
        deviceName,
        verbose: false,
        timeoutMs: const Duration(milliseconds: 1),
      );
    } catch (e) {
      expect(e, isA<TimeoutException>());
    }
  });

  test('Happy path', () async {
    tar = FakeTar(true, fs);
    when(processManager.start(any)).thenAnswer((_) async {
      return FakeProcess(0, <String>['Good job'], <String>['']);
    });

    final ImagePaver paver = ImagePaver(
      tar: tar,
      sshKeyManagerProvider: sshKeyManagerProvider,
      fs: fs,
      processManager: processManager,
    );

    final OperationResult result = await paver.pave(
      'generic-x64.tgz',
      deviceName,
      verbose: false,
    );

    final List<String> capturedStartArgs = verify(
      processManager.start(captureAny),
    ).captured.cast<List<String>>().single;
    expect(capturedStartArgs.first, endsWith('/pave.sh'));
    expect(capturedStartArgs.skip(1).toList(), <String>[
      '--fail-fast',
      '-1',
      '--allow-zedboot-version-mismatch',
      '-n', deviceName, //
      '--authorized-keys', '.ssh/authorized_keys',
    ]);
    expect(result.success, true);
  });
}

class FakeTar implements Tar {
  const FakeTar(this.passes, this.fs)
      : assert(passes != null),
        assert(fs != null);

  final bool passes;
  final MemoryFileSystem fs;

  @override
  Future<OperationResult> untar(String src, String destination,
      {Duration timeoutMs}) async {
    if (passes) {
      final Directory dir = fs.directory(destination)
        ..createSync(recursive: true);
      dir.childFile('pave.sh').createSync();
      return OperationResult.success();
    }
    return OperationResult.error('tar failed');
  }
}

class FakeSshKeyManager implements SshKeyManager {
  const FakeSshKeyManager(this.passes);

  final bool passes;

  @override
  Future<OperationResult> createKeys({
    String destinationPath = '.ssh',
    bool force = false,
  }) async {
    if (passes) {
      return OperationResult.success();
    }
    return OperationResult.error('ssh failed');
  }
}

class MockProcessManager extends Mock implements ProcessManager {}
