// 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/file.dart';
import 'package:file/local.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:process/process.dart';
import 'package:vm_service/vm_service.dart';

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

/// The [FileSystem] for the integration test environment.
const FileSystem fileSystem = LocalFileSystem();

/// The [Platform] for the integration test environment.
const Platform platform = LocalPlatform();

/// The [ProcessManager] for the integration test environment.
const ProcessManager processManager = LocalProcessManager();

/// Creates a temporary directory but resolves any symlinks to return the real
/// underlying path to avoid issues with breakpoints/hot reload.
/// https://github.com/flutter/flutter/pull/21741
Directory createResolvedTempDirectorySync(String prefix) {
  assert(prefix.endsWith('.'));
  final Directory tempDirectory = fileSystem.systemTempDirectory.createTempSync('flutter_$prefix');
  return fileSystem.directory(tempDirectory.resolveSymbolicLinksSync());
}

void writeFile(String path, String content, {bool writeFutureModifiedDate = false}) {
  final File file = fileSystem.file(path)
    ..createSync(recursive: true)
    ..writeAsStringSync(content, flush: true);
    // Some integration tests on Windows to not see this file as being modified
    // recently enough for the hot reload to pick this change up unless the
    // modified time is written in the future.
    if (writeFutureModifiedDate) {
      file.setLastModifiedSync(DateTime.now().add(const Duration(seconds: 5)));
    }
}

void writeBytesFile(String path, List<int> content) {
  fileSystem.file(path)
    ..createSync(recursive: true)
    ..writeAsBytesSync(content, flush: true);
}

void writePackages(String folder) {
  writeFile(fileSystem.path.join(folder, '.packages'), '''
test:${fileSystem.path.join(fileSystem.currentDirectory.path, 'lib')}/
''');
}

Future<void> getPackages(String folder) async {
  final List<String> command = <String>[
    fileSystem.path.join(getFlutterRoot(), 'bin', 'flutter'),
    'pub',
    'get',
  ];
  final ProcessResult result = await processManager.run(command, workingDirectory: folder);
  if (result.exitCode != 0) {
    throw Exception('flutter pub get failed: ${result.stderr}\n${result.stdout}');
  }
}

const String kLocalEngineEnvironment = 'FLUTTER_LOCAL_ENGINE';
const String kLocalEngineHostEnvironment = 'FLUTTER_LOCAL_ENGINE_HOST';
const String kLocalEngineLocation = 'FLUTTER_LOCAL_ENGINE_SRC_PATH';

List<String> getLocalEngineArguments() {
  return <String>[
    if (platform.environment.containsKey(kLocalEngineEnvironment))
      '--local-engine=${platform.environment[kLocalEngineEnvironment]}',
    if (platform.environment.containsKey(kLocalEngineLocation))
      '--local-engine-src-path=${platform.environment[kLocalEngineLocation]}',
    if (platform.environment.containsKey(kLocalEngineHostEnvironment))
      '--local-engine-host=${platform.environment[kLocalEngineHostEnvironment]}',
  ];
}

Future<void> pollForServiceExtensionValue<T>({
  required FlutterTestDriver testDriver,
  required String extension,
  required T continuePollingValue,
  required Matcher matches,
  String valueKey = 'value',
}) async {
  for (int i = 0; i < 10; i++) {
    final Response response = await testDriver.callServiceExtension(extension);
    if (response.json?[valueKey] as T == continuePollingValue) {
      await Future<void>.delayed(const Duration(seconds: 1));
    } else {
      expect(response.json?[valueKey] as T, matches);
      return;
    }
  }
  fail(
    "Did not find expected value for service extension '$extension'. All call"
    " attempts responded with '$continuePollingValue'.",
  );
}

abstract final class AppleTestUtils {
  static const List<String> requiredSymbols = <String>[
    '_kDartIsolateSnapshotData',
    '_kDartIsolateSnapshotInstructions',
    '_kDartVmSnapshotData',
    '_kDartVmSnapshotInstructions'
  ];

  static List<String> getExportedSymbols(String dwarfPath) {
    final ProcessResult nm = processManager.runSync(
      <String>[
        'nm',
        '--debug-syms',  // nm docs: 'Show all symbols, even debugger only'
        '--defined-only',
        '--just-symbol-name',
        dwarfPath,
        '-arch',
        'arm64',
      ],
    );
    final String nmOutput = (nm.stdout as String).trim();
    return nmOutput.isEmpty ? const <String>[] : nmOutput.split('\n');
  }
}

/// Matcher to be used for [ProcessResult] returned
/// from a process run
///
/// The default for [exitCode] will be 0 while
/// [stdoutPattern] and [stderrPattern] are both optional
class ProcessResultMatcher extends Matcher {
  const ProcessResultMatcher({
    this.exitCode = 0,
    this.stdoutPattern,
    this.stderrPattern,
  });

  /// The expected exit code to get returned from a process run
  final int exitCode;

  /// Substring to find in the process's stdout
  final Pattern? stdoutPattern;

  /// Substring to find in the process's stderr
  final Pattern? stderrPattern;

  @override
  Description describe(Description description) {
    description.add('a process with exit code $exitCode');
    if (stdoutPattern != null) {
      description.add(' and stdout: "$stdoutPattern"');
    }
    if (stderrPattern != null) {
      description.add(' and stderr: "$stderrPattern"');
    }

    return description;
  }

  @override
  bool matches(dynamic item, Map<dynamic, dynamic> matchState) {
    final ProcessResult result = item as ProcessResult;
    bool foundStdout = true;
    bool foundStderr = true;

    final String stdout = result.stdout as String;
    final String stderr = result.stderr as String;
    if (stdoutPattern != null) {
      foundStdout = stdout.contains(stdoutPattern!);
      matchState['stdout'] = stdout;
    } else if (stdout.isNotEmpty) {
      // even if we were not asserting on stdout, show stdout for debug purposes
      matchState['stdout'] = stdout;
    }

    if (stderrPattern != null) {
      foundStderr = stderr.contains(stderrPattern!);
      matchState['stderr'] = stderr;
    } else if (stderr.isNotEmpty) {
      matchState['stderr'] = stderr;
    }

    return result.exitCode == exitCode && foundStdout && foundStderr;
  }

  @override
  Description describeMismatch(
    Object? item,
    Description mismatchDescription,
    Map<dynamic, dynamic> matchState,
    bool verbose,
  ) {
    final ProcessResult result = item! as ProcessResult;

    if (result.exitCode != exitCode) {
      mismatchDescription.add('Actual exitCode was ${result.exitCode}\n');
    }

    if (matchState.containsKey('stdout')) {
      mismatchDescription.add('Actual stdout:\n${matchState["stdout"]}\n');
    }

    if (matchState.containsKey('stderr')) {
      mismatchDescription.add('Actual stderr:\n${matchState["stderr"]}\n');
    }

    return mismatchDescription;
  }
}
