// 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 '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/windows/application_package.dart';
import 'package:test/fake.dart';

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

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

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

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

    testUsingContext('Error on non-existing exe file', () {
      final PrebuiltWindowsApp windowsApp = WindowsApp.fromPrebuiltApp(fileSystem.file('not_existing.exe')) as PrebuiltWindowsApp;

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

    testUsingContext('Success on exe file', () {
      fileSystem.file('file.exe').createSync();
      final PrebuiltWindowsApp windowsApp = WindowsApp.fromPrebuiltApp(fileSystem.file('file.exe')) as PrebuiltWindowsApp;

      expect(windowsApp.name, 'file.exe');
    }, overrides: overrides);

    testUsingContext('Error on non-existing zip file', () {
      final PrebuiltWindowsApp windowsApp = WindowsApp.fromPrebuiltApp(fileSystem.file('not_existing.zip')) as PrebuiltWindowsApp;

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

    testUsingContext('Bad zipped app, no payload dir', () {
      fileSystem.file('app.zip').createSync();
      final PrebuiltWindowsApp windowsApp = WindowsApp.fromPrebuiltApp(fileSystem.file('app.zip')) as PrebuiltWindowsApp;

      expect(windowsApp, isNull);
      expect(logger.errorText, contains('Cannot find .exe files in the zip archive.'));
    }, overrides: overrides);

    testUsingContext('Bad zipped app, two .exe files', () {
      fileSystem.file('app.zip').createSync();
      os.unzipOverride = (File zipFile, Directory targetDirectory) {
        if (zipFile.path != 'app.zip') {
          return;
        }
        final String exePath1 = fileSystem.path.join(targetDirectory.path, 'app1.exe');
        final String exePath2 = fileSystem.path.join(targetDirectory.path, 'app2.exe');
        fileSystem.directory(exePath1).createSync(recursive: true);
        fileSystem.directory(exePath2).createSync(recursive: true);
      };
      final PrebuiltWindowsApp windowsApp = WindowsApp.fromPrebuiltApp(fileSystem.file('app.zip')) as PrebuiltWindowsApp;

      expect(windowsApp, isNull);
      expect(logger.errorText, contains('Archive "app.zip" contains more than one .exe files.'));
    }, overrides: overrides);

    testUsingContext('Success with zipped app', () {
      fileSystem.file('app.zip').createSync();
      String exePath;
      os.unzipOverride = (File zipFile, Directory targetDirectory) {
        if (zipFile.path != 'app.zip') {
          return;
        }
        exePath = fileSystem.path.join(targetDirectory.path, 'app.exe');
        fileSystem.directory(exePath).createSync(recursive: true);
      };
      final PrebuiltWindowsApp windowsApp = WindowsApp.fromPrebuiltApp(fileSystem.file('app.zip')) as PrebuiltWindowsApp;

      expect(logger.errorText, isEmpty);
      expect(windowsApp.name, exePath);
      expect(windowsApp.applicationPackage.path, 'app.zip');
    }, overrides: overrides);

    testUsingContext('Error on unknown file type', () {
      fileSystem.file('not_existing.app').createSync();
      final PrebuiltWindowsApp windowsApp = WindowsApp.fromPrebuiltApp(fileSystem.file('not_existing.app')) as PrebuiltWindowsApp;

      expect(windowsApp, isNull);
      expect(logger.errorText, contains('Unknown windows application type.'));
    }, 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);
  }
}
