// 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 'package:file/memory.dart';
import 'package:file_testing/file_testing.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/build.dart';
import 'package:flutter_tools/src/fuchsia/fuchsia_kernel_compiler.dart';
import 'package:flutter_tools/src/fuchsia/fuchsia_pm.dart';
import 'package:flutter_tools/src/fuchsia/fuchsia_sdk.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:meta/meta.dart';
import 'package:mockito/mockito.dart';
import 'package:process/process.dart';

import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/mocks.dart';

// Defined globally for mocks to use.
FileSystem fileSystem;

void main() {
  Cache.disableLocking();

  final Platform linuxPlatform = FakePlatform(
    operatingSystem: 'linux',
    environment: const <String, String>{
      'FLUTTER_ROOT': '/',
    },
  );
  final Platform windowsPlatform = FakePlatform(
    operatingSystem: 'windows',
    environment: const <String, String>{
      'FLUTTER_ROOT': '/'
    },
  );
  MockFuchsiaSdk fuchsiaSdk;

  setUp(() {
    fuchsiaSdk = MockFuchsiaSdk();
    fileSystem = MemoryFileSystem.test();
  });

  group('Fuchsia build fails gracefully when', () {
    testUsingContext('there is no Fuchsia project', () async {
      final BuildCommand command = BuildCommand();

      expect(
        createTestCommandRunner(command).run(const <String>['build', 'fuchsia']),
        throwsToolExit(),
      );
    }, overrides: <Type, Generator>{
      Platform: () => linuxPlatform,
      FileSystem: () => fileSystem,
      ProcessManager: () => FakeProcessManager.any(),
    });

    testUsingContext('there is no cmx file', () async {
      final BuildCommand command = BuildCommand();
      fileSystem.directory('fuchsia').createSync(recursive: true);
      fileSystem.file('.packages').createSync();
      fileSystem.file('pubspec.yaml').createSync();

      expect(
        createTestCommandRunner(command).run(const <String>['build', 'fuchsia']),
        throwsToolExit(),
      );
    }, overrides: <Type, Generator>{
      Platform: () => linuxPlatform,
      FileSystem: () => fileSystem,
      ProcessManager: () => FakeProcessManager.any(),
    });

    testUsingContext('on Windows platform', () async {
      final BuildCommand command = BuildCommand();
      const String appName = 'app_name';
      fileSystem
        .file(fileSystem.path.join('fuchsia', 'meta', '$appName.cmx'))
        ..createSync(recursive: true)
        ..writeAsStringSync('{}');
      fileSystem.file('.packages').createSync();
      final File pubspecFile = fileSystem.file('pubspec.yaml')..createSync();
      pubspecFile.writeAsStringSync('name: $appName');

      expect(
        createTestCommandRunner(command).run(const <String>['build', 'fuchsia']),
        throwsToolExit(),
      );
    }, overrides: <Type, Generator>{
      Platform: () => windowsPlatform,
      FileSystem: () => fileSystem,
      ProcessManager: () => FakeProcessManager.any(),
    });

    testUsingContext('there is no Fuchsia kernel compiler', () async {
      final BuildCommand command = BuildCommand();
      const String appName = 'app_name';
      fileSystem
        .file(fileSystem.path.join('fuchsia', 'meta', '$appName.cmx'))
        ..createSync(recursive: true)
        ..writeAsStringSync('{}');
      fileSystem.file('.packages').createSync();
      fileSystem.file(fileSystem.path.join('lib', 'main.dart')).createSync(recursive: true);
      final File pubspecFile = fileSystem.file('pubspec.yaml')..createSync();
      pubspecFile.writeAsStringSync('name: $appName');

      expect(
        createTestCommandRunner(command).run(const <String>['build', 'fuchsia']),
        throwsToolExit(),
      );
    }, overrides: <Type, Generator>{
      Platform: () => linuxPlatform,
      FileSystem: () => fileSystem,
      ProcessManager: () => FakeProcessManager.any(),
    });
  });

  testUsingContext('Fuchsia build parts fit together right', () async {
    final BuildCommand command = BuildCommand();
    applyMocksToCommand(command);
    const String appName = 'app_name';
    fileSystem
        .file(fileSystem.path.join('fuchsia', 'meta', '$appName.cmx'))
        ..createSync(recursive: true)
        ..writeAsStringSync('{}');
    fileSystem.file('.packages').createSync();
    fileSystem.file(fileSystem.path.join('lib', 'main.dart')).createSync(recursive: true);
    final File pubspecFile = fileSystem.file('pubspec.yaml')..createSync();
    pubspecFile.writeAsStringSync('name: $appName');

    await createTestCommandRunner(command)
      .run(const <String>['build', 'fuchsia']);
    final String farPath = fileSystem.path.join(
      getFuchsiaBuildDirectory(), 'pkg', 'app_name-0.far',
    );

    expect(fileSystem.file(farPath), exists);
  }, overrides: <Type, Generator>{
    Platform: () => linuxPlatform,
    FileSystem: () => fileSystem,
    ProcessManager: () => FakeProcessManager.any(),
    FuchsiaSdk: () => fuchsiaSdk,
  });
}

class MockFuchsiaPM extends Mock implements FuchsiaPM {
  String _appName;

  @override
  Future<bool> init(String buildPath, String appName) async {
    if (!fileSystem.directory(buildPath).existsSync()) {
      return false;
    }
    fileSystem
        .file(fileSystem.path.join(buildPath, 'meta', 'package'))
        .createSync(recursive: true);
    _appName = appName;
    return true;
  }

  @override
  Future<bool> genkey(String buildPath, String outKeyPath) async {
    if (!fileSystem.file(fileSystem.path.join(buildPath, 'meta', 'package')).existsSync()) {
      return false;
    }
    fileSystem.file(outKeyPath).createSync(recursive: true);
    return true;
  }

  @override
  Future<bool> build(String buildPath, String keyPath, String manifestPath) async {
    if (!fileSystem.file(fileSystem.path.join(buildPath, 'meta', 'package')).existsSync() ||
        !fileSystem.file(keyPath).existsSync() ||
        !fileSystem.file(manifestPath).existsSync()) {
      return false;
    }
    fileSystem.file(fileSystem.path.join(buildPath, 'meta.far')).createSync(recursive: true);
    return true;
  }

  @override
  Future<bool> archive(String buildPath, String keyPath, String manifestPath) async {
    if (!fileSystem.file(fileSystem.path.join(buildPath, 'meta', 'package')).existsSync() ||
        !fileSystem.file(keyPath).existsSync() ||
        !fileSystem.file(manifestPath).existsSync()) {
      return false;
    }
    if (_appName == null) {
      return false;
    }
    fileSystem
        .file(fileSystem.path.join(buildPath, '$_appName-0.far'))
        .createSync(recursive: true);
    return true;
  }
}

class MockFuchsiaKernelCompiler extends Mock implements FuchsiaKernelCompiler {
  @override
  Future<void> build({
    @required FuchsiaProject fuchsiaProject,
    @required String target, // E.g., lib/main.dart
    BuildInfo buildInfo = BuildInfo.debug,
  }) async {
    final String outDir = getFuchsiaBuildDirectory();
    final String appName = fuchsiaProject.project.manifest.appName;
    final String manifestPath = fileSystem.path.join(outDir, '$appName.dilpmanifest');
    fileSystem.file(manifestPath).createSync(recursive: true);
  }
}

class MockFuchsiaSdk extends Mock implements FuchsiaSdk {
  @override
  final FuchsiaPM fuchsiaPM = MockFuchsiaPM();

  @override
  final FuchsiaKernelCompiler fuchsiaKernelCompiler =
      MockFuchsiaKernelCompiler();
}
