// 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 'dart:io' as io show ProcessSignal;

import 'package:file/file.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:process/process.dart';
import 'package:test/fake.dart';

import '../src/common.dart';
import '../src/fake_process_manager.dart';
import '../src/fakes.dart';
import 'test_utils.dart';

final String dart = fileSystem.path
    .join(getFlutterRoot(), 'bin', platform.isWindows ? 'dart.bat' : 'dart');

void main() {
  group('Cache.lock', () {
    // Windows locking is too flaky for this to work reliably.
    if (platform.isWindows) {
      return;
    }
    testWithoutContext(
        'should log a message to stderr when lock is not acquired', () async {
      final String? oldRoot = Cache.flutterRoot;
      final Directory tempDir = fileSystem.systemTempDirectory.createTempSync('cache_test.');
      final BufferLogger logger = BufferLogger(
        terminal: Terminal.test(supportsColor: false, supportsEmoji: false),
        outputPreferences: OutputPreferences(),
      );
      logger.fatalWarnings = true;
      Process? process;
      try {
        Cache.flutterRoot = tempDir.absolute.path;
        final Cache cache = Cache.test(
          fileSystem: fileSystem,
          processManager: FakeProcessManager.any(),
          logger: logger,
        );
        final File cacheFile = fileSystem.file(fileSystem.path
            .join(Cache.flutterRoot!, 'bin', 'cache', 'lockfile'))
          ..createSync(recursive: true);
        final File script = fileSystem.file(fileSystem.path
            .join(Cache.flutterRoot!, 'bin', 'cache', 'test_lock.dart'));
        script.writeAsStringSync(r'''
import 'dart:async';
import 'dart:io';

Future<void> main(List<String> args) async {
  File file = File(args[0]);
  final RandomAccessFile lock = file.openSync(mode: FileMode.write);
  while (true) {
    try {
      lock.lockSync();
      break;
    } on FileSystemException {}
  }
  await Future<void>.delayed(const Duration(seconds: 1));
  exit(0);
}
''');
        // Locks are per-process, so we have to launch a separate process to
        // test out cache locking.
        process = await const LocalProcessManager().start(
          <String>[dart, script.absolute.path, cacheFile.absolute.path],
        );
        // Wait for the script to lock the test cache file before checking to
        // see that the cache is unable to.
        bool locked = false;
        while (!locked) {
          // Give the script a chance to try for the lock much more often.
          await Future<void>.delayed(const Duration(milliseconds: 100));
          final RandomAccessFile lock = cacheFile.openSync(mode: FileMode.write);
          try {
            // If we can lock it, unlock immediately to give the script a
            // chance.
            lock.lockSync();
            lock.unlockSync();
          } on FileSystemException {
            // If we can't lock it, then the child script succeeded in locking
            // it, and we can now test.
            locked = true;
            break;
          }
        }
        // Finally, test that the cache cannot lock a locked file. This should
        // print a message if it can't lock the file.
        await cache.lock();
      } finally {
        // Just to keep from leaving the process hanging around.
        process?.kill(io.ProcessSignal.sighup);
        tryToDelete(tempDir);
        Cache.flutterRoot = oldRoot;
      }
      expect(logger.statusText, isEmpty);
      expect(logger.errorText, isEmpty);
      expect(logger.warningText,
          equals('Waiting for another flutter command to release the startup lock...\n'));
      expect(logger.hadErrorOutput, isFalse);
      // Should still be false, since the particular "Waiting..." message above
      // aims to avoid triggering failure as a fatal warning.
      expect(logger.hadWarningOutput, isFalse);
    });
    testWithoutContext(
        'should log a warning message for unknown version ', () async {
      final String? oldRoot = Cache.flutterRoot;
      final Directory tempDir = fileSystem.systemTempDirectory.createTempSync('cache_test.');
      final BufferLogger logger = BufferLogger(
        terminal: Terminal.test(supportsColor: false, supportsEmoji: false),
        outputPreferences: OutputPreferences(),
      );
      logger.fatalWarnings = true;
      try {
        Cache.flutterRoot = tempDir.absolute.path;
        final Cache cache = Cache.test(
          fileSystem: fileSystem,
          processManager: FakeProcessManager.any(),
          logger: logger,
        );
        final FakeVersionlessArtifact artifact = FakeVersionlessArtifact(cache);
        cache.registerArtifact(artifact);
        await artifact.update(FakeArtifactUpdater(), logger, fileSystem, FakeOperatingSystemUtils());
      } finally {
        tryToDelete(tempDir);
        Cache.flutterRoot = oldRoot;
      }
      expect(logger.statusText, isEmpty);
      expect(logger.warningText, equals('No known version for the artifact name "fake". '
        'Flutter can continue, but the artifact may be re-downloaded on '
        'subsequent invocations until the problem is resolved.\n'));
      expect(logger.hadErrorOutput, isFalse);
      expect(logger.hadWarningOutput, isTrue);
    });
  });

  testWithoutContext('Dart SDK target arch matches host arch', () async {
    if (platform.isWindows) {
      return;
    }
    final ProcessResult dartResult = await const LocalProcessManager().run(
      <String>[dart, '--version'],
    );
    // Parse 'arch' out of a string like '... "os_arch"\n'.
    final String dartTargetArch = (dartResult.stdout as String)
      .trim().split(' ').last.replaceAll('"', '').split('_')[1];
    final ProcessResult unameResult = await const LocalProcessManager().run(
      <String>['uname', '-m'],
    );
    final String unameArch = (unameResult.stdout as String)
      .trim().replaceAll('aarch64', 'arm64')
             .replaceAll('x86_64', 'x64');
    expect(dartTargetArch, equals(unameArch));
  });
}

class FakeArtifactUpdater extends Fake implements ArtifactUpdater {
  void Function(String, Uri, Directory)? onDownloadZipArchive;
  void Function(String, Uri, Directory)? onDownloadZipTarball;

  @override
  Future<void> downloadZippedTarball(String message, Uri url, Directory location) async {
    onDownloadZipTarball?.call(message, url, location);
  }

  @override
  Future<void> downloadZipArchive(String message, Uri url, Directory location) async {
    onDownloadZipArchive?.call(message, url, location);
  }

  @override
  void removeDownloadedFiles() { }
}

class FakeVersionlessArtifact extends CachedArtifact {
  FakeVersionlessArtifact(Cache cache) : super(
    'fake',
    cache,
    DevelopmentArtifact.universal,
  );

  @override
  String? get version => null;

  @override
  Future<void> updateInner(ArtifactUpdater artifactUpdater, FileSystem fileSystem, OperatingSystemUtils operatingSystemUtils) async { }
}
