// 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.

// @dart = 2.8

import 'dart:convert';

import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/base/utils.dart';
import 'package:flutter_tools/src/ios/plist_parser.dart';
import 'package:flutter_tools/src/macos/application_package.dart';
import 'package:test/fake.dart';

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

void main() {
group('PrebuiltMacOSApp', () {
    FakeOperatingSystemUtils os;
    FileSystem fileSystem;
    BufferLogger logger;

    final Map<Type, Generator> overrides = <Type, Generator>{
      FileSystem: () => fileSystem,
      ProcessManager: () => FakeProcessManager.any(),
      PlistParser: () => FakePlistUtils(fileSystem),
      OperatingSystemUtils: () => os,
      Logger: () => logger,
    };

    setUp(() {
      fileSystem = MemoryFileSystem.test();
      os = FakeOperatingSystemUtils();
      logger = BufferLogger.test();
    });

    testUsingContext('Error on non-existing file', () {
      final PrebuiltMacOSApp macosApp = MacOSApp.fromPrebuiltApp(fileSystem.file('not_existing.app')) as PrebuiltMacOSApp;

      expect(macosApp, isNull);
      expect(logger.errorText, contains('File "not_existing.app" does not exist.'));
    }, overrides: overrides);

    testUsingContext('Error on non-app-bundle folder', () {
      fileSystem.directory('regular_folder').createSync();
      final PrebuiltMacOSApp macosApp = MacOSApp.fromPrebuiltApp(fileSystem.file('regular_folder')) as PrebuiltMacOSApp;

      expect(macosApp, isNull);
      expect(logger.errorText, contains('Folder "regular_folder" is not an app bundle.'));
    }, overrides: overrides);

    testUsingContext('Error on no info.plist', () {
      fileSystem.directory('bundle.app').createSync();
      final PrebuiltMacOSApp macosApp = MacOSApp.fromPrebuiltApp(fileSystem.file('bundle.app')) as PrebuiltMacOSApp;

      expect(macosApp, isNull);
      expect(logger.errorText, contains('Invalid prebuilt macOS app. Does not contain Info.plist.'));
    }, overrides: overrides);

    testUsingContext('Error on info.plist missing bundle identifier', () {
      final String contentsDirectory = fileSystem.path.join('bundle.app', 'Contents');
      fileSystem.directory(contentsDirectory).createSync(recursive: true);
      fileSystem
        .file(fileSystem.path.join('bundle.app', 'Contents', 'Info.plist'))
        .writeAsStringSync(badPlistData);
      final PrebuiltMacOSApp macosApp = MacOSApp.fromPrebuiltApp(fileSystem.file('bundle.app')) as PrebuiltMacOSApp;

      expect(macosApp, isNull);
      expect(logger.errorText, contains('Invalid prebuilt macOS app. Info.plist does not contain bundle identifier'));
    }, overrides: overrides);

    testUsingContext('Error on info.plist missing executable', () {
      final String contentsDirectory = fileSystem.path.join('bundle.app', 'Contents');
      fileSystem.directory(contentsDirectory).createSync(recursive: true);
      fileSystem
        .file(fileSystem.path.join('bundle.app', 'Contents', 'Info.plist'))
        .writeAsStringSync(badPlistDataNoExecutable);
      final PrebuiltMacOSApp macosApp = MacOSApp.fromPrebuiltApp(fileSystem.file('bundle.app')) as PrebuiltMacOSApp;

      expect(macosApp, isNull);
      expect(logger.errorText, contains('Invalid prebuilt macOS app. Info.plist does not contain bundle executable'));
    }, overrides: overrides);

    testUsingContext('Success with app bundle', () {
      final String appDirectory = fileSystem.path.join('bundle.app', 'Contents', 'MacOS');
      fileSystem.directory(appDirectory).createSync(recursive: true);
      fileSystem
        .file(fileSystem.path.join('bundle.app', 'Contents', 'Info.plist'))
        .writeAsStringSync(plistData);
      fileSystem
        .file(fileSystem.path.join(appDirectory, executableName))
        .createSync();
      final PrebuiltMacOSApp macosApp = MacOSApp.fromPrebuiltApp(fileSystem.file('bundle.app')) as PrebuiltMacOSApp;

      expect(logger.errorText, isEmpty);
      expect(macosApp.bundleDir.path, 'bundle.app');
      expect(macosApp.id, 'fooBundleId');
      expect(macosApp.bundleName, 'bundle.app');
    }, overrides: overrides);

    testUsingContext('Bad zipped app, no payload dir', () {
      fileSystem.file('app.zip').createSync();
      final PrebuiltMacOSApp macosApp = MacOSApp.fromPrebuiltApp(fileSystem.file('app.zip')) as PrebuiltMacOSApp;

      expect(macosApp, isNull);
      expect(logger.errorText, contains('Archive "app.zip" does not contain a single app bundle.'));
    }, overrides: overrides);

    testUsingContext('Bad zipped app, two app bundles', () {
      fileSystem.file('app.zip').createSync();
      os.unzipOverride = (File zipFile, Directory targetDirectory) {
        if (zipFile.path != 'app.zip') {
          return;
        }
        final String bundlePath1 = fileSystem.path.join(targetDirectory.path, 'bundle1.app');
        final String bundlePath2 = fileSystem.path.join(targetDirectory.path, 'bundle2.app');
        fileSystem.directory(bundlePath1).createSync(recursive: true);
        fileSystem.directory(bundlePath2).createSync(recursive: true);
      };
      final PrebuiltMacOSApp macosApp = MacOSApp.fromPrebuiltApp(fileSystem.file('app.zip')) as PrebuiltMacOSApp;

      expect(macosApp, isNull);
      expect(logger.errorText, contains('Archive "app.zip" does not contain a single app bundle.'));
    }, overrides: overrides);

    testUsingContext('Success with zipped app', () {
      fileSystem.file('app.zip').createSync();
      os.unzipOverride = (File zipFile, Directory targetDirectory) {
        if (zipFile.path != 'app.zip') {
          return;
        }
        final Directory bundleAppContentsDir = fileSystem.directory(fileSystem.path.join(targetDirectory.path, 'bundle.app', 'Contents'));
        bundleAppContentsDir.createSync(recursive: true);
        fileSystem
          .file(fileSystem.path.join(bundleAppContentsDir.path, 'Info.plist'))
          .writeAsStringSync(plistData);
        fileSystem
          .directory(fileSystem.path.join(bundleAppContentsDir.path, 'MacOS'))
          .createSync();
        fileSystem
          .file(fileSystem.path
          .join(bundleAppContentsDir.path, 'MacOS', executableName))
          .createSync();
      };
      final PrebuiltMacOSApp macosApp = MacOSApp.fromPrebuiltApp(fileSystem.file('app.zip')) as PrebuiltMacOSApp;

      expect(logger.errorText, isEmpty);
      expect(macosApp.bundleDir.path, endsWith('bundle.app'));
      expect(macosApp.id, 'fooBundleId');
      expect(macosApp.bundleName, endsWith('bundle.app'));
    }, overrides: overrides);
  });
}

class FakeOperatingSystemUtils extends Fake implements OperatingSystemUtils {
  FakeOperatingSystemUtils();

  void Function(File, Directory) unzipOverride;

  @override
  void unzip(File file, Directory targetDirectory) {
    unzipOverride?.call(file, targetDirectory);
  }
}

class FakePlistUtils extends Fake implements PlistParser {
  FakePlistUtils(this.fileSystem);

  final FileSystem fileSystem;

  @override
  Map<String, dynamic> parseFile(String plistFilePath) {
    final File file = fileSystem.file(plistFilePath);
    if (!file.existsSync()) {
      return <String, dynamic>{};
    }
    return castStringKeyedMap(json.decode(file.readAsStringSync()));
  }
}

// Contains no bundle identifier.
const String badPlistData = '''
{}
''';

// Contains no bundle executable.
const String badPlistDataNoExecutable = '''
{"CFBundleIdentifier": "fooBundleId"}
''';

const String executableName = 'foo';

const String plistData = '''
{"CFBundleIdentifier": "fooBundleId", "CFBundleExecutable": "$executableName"}
''';
