// 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:flutter_tools/src/base/build.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/process.dart';
import 'package:flutter_tools/src/build_system/build_system.dart';
import 'package:flutter_tools/src/build_system/targets/dart.dart';
import 'package:flutter_tools/src/build_system/targets/macos.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/macos/cocoapods.dart';
import 'package:flutter_tools/src/macos/xcode.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:mockito/mockito.dart';
import 'package:process/process.dart';
import 'package:platform/platform.dart';

import '../../../src/common.dart';
import '../../../src/testbed.dart';

const String _kInputPrefix = 'bin/cache/artifacts/engine/darwin-x64/FlutterMacOS.framework';
const String _kOutputPrefix = 'FlutterMacOS.framework';

final List<File> inputs = <File>[
  globals.fs.file('$_kInputPrefix/FlutterMacOS'),
  // Headers
  globals.fs.file('$_kInputPrefix/Headers/FlutterDartProject.h'),
  globals.fs.file('$_kInputPrefix/Headers/FlutterEngine.h'),
  globals.fs.file('$_kInputPrefix/Headers/FlutterViewController.h'),
  globals.fs.file('$_kInputPrefix/Headers/FlutterBinaryMessenger.h'),
  globals.fs.file('$_kInputPrefix/Headers/FlutterChannels.h'),
  globals.fs.file('$_kInputPrefix/Headers/FlutterCodecs.h'),
  globals.fs.file('$_kInputPrefix/Headers/FlutterMacros.h'),
  globals.fs.file('$_kInputPrefix/Headers/FlutterPluginMacOS.h'),
  globals.fs.file('$_kInputPrefix/Headers/FlutterPluginRegistrarMacOS.h'),
  globals.fs.file('$_kInputPrefix/Headers/FlutterMacOS.h'),
  // Modules
  globals.fs.file('$_kInputPrefix/Modules/module.modulemap'),
  // Resources
  globals.fs.file('$_kInputPrefix/Resources/icudtl.dat'),
  globals.fs.file('$_kInputPrefix/Resources/Info.plist'),
  // Ignore Versions folder for now
  globals.fs.file('packages/flutter_tools/lib/src/build_system/targets/macos.dart'),
];

void main() {
  Testbed testbed;
  Environment environment;
  MockPlatform mockPlatform;
  MockXcode mockXcode;

  setUpAll(() {
    Cache.disableLocking();
    Cache.flutterRoot = '';
  });

  setUp(() {
    mockXcode = MockXcode();
    mockPlatform = MockPlatform();
    when(mockPlatform.isWindows).thenReturn(false);
    when(mockPlatform.isMacOS).thenReturn(true);
    when(mockPlatform.isLinux).thenReturn(false);
    when(mockPlatform.environment).thenReturn(const <String, String>{});
    testbed = Testbed(setup: () {
      globals.fs.file(globals.fs.path.join('bin', 'cache', 'pkg', 'sky_engine', 'lib', 'ui',
          'ui.dart')).createSync(recursive: true);
      globals.fs.file(globals.fs.path.join('bin', 'cache', 'pkg', 'sky_engine', 'sdk_ext',
          'vmservice_io.dart')).createSync(recursive: true);

    environment = Environment.test(
      globals.fs.currentDirectory,
      defines: <String, String>{
          kBuildMode: 'debug',
          kTargetPlatform: 'darwin-x64',
        },
      );
    }, overrides: <Type, Generator>{
      ProcessManager: () => MockProcessManager(),
      Platform: () => mockPlatform,
    });
  });

  test('Copies files to correct cache directory', () => testbed.run(() async {
    for (final File input in inputs) {
      input.createSync(recursive: true);
    }
    // Create output directory so we can test that it is deleted.
    environment.outputDir.childDirectory(_kOutputPrefix)
        .createSync(recursive: true);

    when(globals.processManager.run(any)).thenAnswer((Invocation invocation) async {
      final List<String> arguments = invocation.positionalArguments.first as List<String>;
      final String sourcePath = arguments[arguments.length - 2];
      final String targetPath = arguments.last;
      final Directory source = globals.fs.directory(sourcePath);
      final Directory target = globals.fs.directory(targetPath);

      // verify directory was deleted by command.
      expect(target.existsSync(), false);
      target.createSync(recursive: true);

      for (final FileSystemEntity entity in source.listSync(recursive: true)) {
        if (entity is File) {
          final String relative = globals.fs.path.relative(entity.path, from: source.path);
          final String destination = globals.fs.path.join(target.path, relative);
          if (!globals.fs.file(destination).parent.existsSync()) {
            globals.fs.file(destination).parent.createSync();
          }
          entity.copySync(destination);
        }
      }
      return FakeProcessResult()..exitCode = 0;
    });
    await const DebugUnpackMacOS().build(environment);

    expect(globals.fs.directory('$_kOutputPrefix').existsSync(), true);
    for (final File file in inputs) {
      expect(globals.fs.file(file.path.replaceFirst(_kInputPrefix, _kOutputPrefix)).existsSync(), true);
    }
  }));

  test('debug macOS application fails if App.framework missing', () => testbed.run(() async {
    final String inputKernel = globals.fs.path.join(environment.buildDir.path, 'app.dill');
    globals.fs.file(inputKernel)
      ..createSync(recursive: true)
      ..writeAsStringSync('testing');

    expect(() async => await const DebugMacOSBundleFlutterAssets().build(environment),
        throwsException);
  }));

  test('debug macOS application creates correctly structured framework', () => testbed.run(() async {
    globals.fs.file(globals.fs.path.join('bin', 'cache', 'artifacts', 'engine', 'darwin-x64',
        'vm_isolate_snapshot.bin')).createSync(recursive: true);
    globals.fs.file(globals.fs.path.join('bin', 'cache', 'artifacts', 'engine', 'darwin-x64',
        'isolate_snapshot.bin')).createSync(recursive: true);
    globals.fs.file(globals.fs.path.join(environment.buildDir.path, 'App.framework', 'App'))
        ..createSync(recursive: true);

    final String inputKernel = globals.fs.path.join(environment.buildDir.path, 'app.dill');
    final String outputKernel = globals.fs.path.join('App.framework', 'Versions', 'A', 'Resources',
        'flutter_assets', 'kernel_blob.bin');
    final String outputPlist = globals.fs.path.join('App.framework', 'Versions', 'A', 'Resources',
        'Info.plist');
    globals.fs.file(inputKernel)
      ..createSync(recursive: true)
      ..writeAsStringSync('testing');

    await const DebugMacOSBundleFlutterAssets().build(environment);

    expect(globals.fs.file(outputKernel).readAsStringSync(), 'testing');
    expect(globals.fs.file(outputPlist).readAsStringSync(), contains('io.flutter.flutter.app'));
  }));

  test('release/profile macOS application has no blob or precompiled runtime', () => testbed.run(() async {
    globals.fs.file(globals.fs.path.join('bin', 'cache', 'artifacts', 'engine', 'darwin-x64',
        'vm_isolate_snapshot.bin')).createSync(recursive: true);
    globals.fs.file(globals.fs.path.join('bin', 'cache', 'artifacts', 'engine', 'darwin-x64',
        'isolate_snapshot.bin')).createSync(recursive: true);
    globals.fs.file(globals.fs.path.join(environment.buildDir.path, 'App.framework', 'App'))
        ..createSync(recursive: true);
    final String outputKernel = globals.fs.path.join('App.framework', 'Resources',
        'flutter_assets', 'kernel_blob.bin');
    final String precompiledVm = globals.fs.path.join('App.framework', 'Resources',
        'flutter_assets', 'vm_snapshot_data');
    final String precompiledIsolate = globals.fs.path.join('App.framework', 'Resources',
        'flutter_assets', 'isolate_snapshot_data');
    await const ProfileMacOSBundleFlutterAssets().build(environment..defines[kBuildMode] = 'profile');

    expect(globals.fs.file(outputKernel).existsSync(), false);
    expect(globals.fs.file(precompiledVm).existsSync(), false);
    expect(globals.fs.file(precompiledIsolate).existsSync(), false);
  }));

  test('release/profile macOS application updates when App.framework updates', () => testbed.run(() async {
    globals.fs.file(globals.fs.path.join('bin', 'cache', 'artifacts', 'engine', 'darwin-x64',
        'vm_isolate_snapshot.bin')).createSync(recursive: true);
    globals.fs.file(globals.fs.path.join('bin', 'cache', 'artifacts', 'engine', 'darwin-x64',
        'isolate_snapshot.bin')).createSync(recursive: true);
    final File inputFramework = globals.fs.file(globals.fs.path.join(environment.buildDir.path, 'App.framework', 'App'))
        ..createSync(recursive: true)
        ..writeAsStringSync('ABC');

    await const ProfileMacOSBundleFlutterAssets().build(environment..defines[kBuildMode] = 'profile');
    final File outputFramework = globals.fs.file(globals.fs.path.join(environment.outputDir.path, 'App.framework', 'App'));

    expect(outputFramework.readAsStringSync(), 'ABC');

    inputFramework.writeAsStringSync('DEF');
    await const ProfileMacOSBundleFlutterAssets().build(environment..defines[kBuildMode] = 'profile');

    expect(outputFramework.readAsStringSync(), 'DEF');
  }));

  test('release/profile macOS compilation uses correct gen_snapshot', () => testbed.run(() async {
    when(genSnapshot.run(
      snapshotType: anyNamed('snapshotType'),
      additionalArgs: anyNamed('additionalArgs'),
      darwinArch: anyNamed('darwinArch'),
    )).thenAnswer((Invocation invocation) {
      environment.buildDir.childFile('snapshot_assembly.o').createSync();
      environment.buildDir.childFile('snapshot_assembly.S').createSync();
      return Future<int>.value(0);
    });
    when(mockXcode.cc(any)).thenAnswer((Invocation invocation) {
      return Future<RunResult>.value(RunResult(FakeProcessResult()..exitCode = 0, <String>['test']));
    });
    when(mockXcode.clang(any)).thenAnswer((Invocation invocation) {
      return Future<RunResult>.value(RunResult(FakeProcessResult()..exitCode = 0, <String>['test']));
    });
    environment.buildDir.childFile('app.dill').createSync(recursive: true);
    globals.fs.file('.packages')
      ..createSync()
      ..writeAsStringSync('''
# Generated
sky_engine:file:///bin/cache/pkg/sky_engine/lib/
flutter_tools:lib/''');
    await const CompileMacOSFramework().build(environment..defines[kBuildMode] = 'release');
  }, overrides: <Type, Generator>{
    GenSnapshot: () => MockGenSnapshot(),
    Xcode: () => mockXcode,
  }));
}

class MockPlatform extends Mock implements Platform {}
class MockCocoaPods extends Mock implements CocoaPods {}
class MockProcessManager extends Mock implements ProcessManager {}
class MockGenSnapshot extends Mock implements GenSnapshot {}
class MockXcode extends Mock implements Xcode {}
class FakeProcessResult implements ProcessResult {
  @override
  int exitCode;

  @override
  int pid = 0;

  @override
  String stderr = '';

  @override
  String stdout = '';
}
