// 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:convert';

import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';

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

class SwiftPackageManagerUtils {
  static Future<void> enableSwiftPackageManager(
    String flutterBin,
    String workingDirectory,
  ) async {
    final ProcessResult result = await processManager.run(
      <String>[
        flutterBin,
        ...getLocalEngineArguments(),
        'config',
        '--enable-swift-package-manager',
        '-v',
      ],
      workingDirectory: workingDirectory,
    );
    expect(
      result.exitCode,
      0,
      reason: 'Failed to enable Swift Package Manager: \n'
          'stdout: \n${result.stdout}\n'
          'stderr: \n${result.stderr}\n',
      verbose: true,
    );
  }

  static Future<void> disableSwiftPackageManager(
    String flutterBin,
    String workingDirectory,
  ) async {
    final ProcessResult result = await processManager.run(
      <String>[
        flutterBin,
        ...getLocalEngineArguments(),
        'config',
        '--no-enable-swift-package-manager',
        '-v',
      ],
      workingDirectory: workingDirectory,
    );
    expect(
      result.exitCode,
      0,
      reason: 'Failed to disable Swift Package Manager: \n'
          'stdout: \n${result.stdout}\n'
          'stderr: \n${result.stderr}\n',
      verbose: true,
    );
  }

  static Future<String> createApp(
    String flutterBin,
    String workingDirectory, {
    required String platform,
    required String iosLanguage,
    required List<String> options,
    bool usesSwiftPackageManager = false,
  }) async {
    final String appTemplateType = usesSwiftPackageManager ? 'spm' : 'default';

    final String appName = '${platform}_${iosLanguage}_${appTemplateType}_app';
    final ProcessResult result = await processManager.run(
      <String>[
        flutterBin,
        ...getLocalEngineArguments(),
        'create',
        '--org',
        'io.flutter.devicelab',
        '-i',
        iosLanguage,
        ...options,
        appName,
      ],
      workingDirectory: workingDirectory,
    );

    expect(
      result.exitCode,
      0,
      reason: 'Failed to create app: \n'
          'stdout: \n${result.stdout}\n'
          'stderr: \n${result.stderr}\n',
    );

    return fileSystem.path.join(
      workingDirectory,
      appName,
    );
  }

  static Future<void> buildApp(
    String flutterBin,
    String workingDirectory, {
    required List<String> options,
    List<Pattern>? expectedLines,
    List<String>? unexpectedLines,
  }) async {
    final List<Pattern> remainingExpectedLines = expectedLines ?? <Pattern>[];
    final List<String> unexpectedLinesFound = <String>[];
    final List<String> command = <String>[
      flutterBin,
      ...getLocalEngineArguments(),
      'build',
      ...options,
    ];

    final ProcessResult result = await processManager.run(
      command,
      workingDirectory: workingDirectory,
    );

    final List<String> stdout = LineSplitter.split(result.stdout.toString()).toList();
    final List<String> stderr = LineSplitter.split(result.stderr.toString()).toList();
    final List<String> output = stdout + stderr;
    for (final String line in output) {
      // Remove "[   +3 ms] " prefix
      String trimmedLine = line.trim();
      if (trimmedLine.startsWith('[')) {
        final int prefixEndIndex = trimmedLine.indexOf(']');
        if (prefixEndIndex > 0) {
          trimmedLine = trimmedLine
              .substring(prefixEndIndex + 1, trimmedLine.length)
              .trim();
        }
      }
      remainingExpectedLines.remove(trimmedLine);
      remainingExpectedLines.removeWhere((Pattern expectedLine) => trimmedLine.contains(expectedLine));
      if (unexpectedLines != null) {
        if (unexpectedLines.where((String unexpectedLine) => trimmedLine.contains(unexpectedLine)).firstOrNull != null) {
          unexpectedLinesFound.add(trimmedLine);
        }
      }
    }
    expect(
      result.exitCode,
      0,
      reason: 'Failed to build app for "${command.join(' ')}":\n'
          'stdout: \n${result.stdout}\n'
          'stderr: \n${result.stderr}\n',
    );
    expect(
      remainingExpectedLines,
      isEmpty,
      reason: 'Did not find expected lines for "${command.join(' ')}":\n'
          'stdout: \n${result.stdout}\n'
          'stderr: \n${result.stderr}\n',
    );
    expect(
      unexpectedLinesFound,
      isEmpty,
      reason: 'Found unexpected lines for "${command.join(' ')}":\n'
          'stdout: \n${result.stdout}\n'
          'stderr: \n${result.stderr}\n',
    );
  }

  static Future<void> cleanApp(String flutterBin, String workingDirectory) async {
    final ProcessResult result = await processManager.run(
      <String>[
        flutterBin,
        ...getLocalEngineArguments(),
        'clean',
      ],
      workingDirectory: workingDirectory,
    );
    expect(
      result.exitCode,
      0,
      reason: 'Failed to clean app: \n'
          'stdout: \n${result.stdout}\n'
          'stderr: \n${result.stderr}\n',
    );
  }

  static Future<SwiftPackageManagerPlugin> createPlugin(
    String flutterBin,
    String workingDirectory, {
    required String platform,
    required String iosLanguage,
    bool usesSwiftPackageManager = false,
  }) async {
    final String dependencyManager = usesSwiftPackageManager ? 'spm' : 'cocoapods';

    // Create plugin
    final String pluginName = '${platform}_${iosLanguage}_${dependencyManager}_plugin';
    final ProcessResult result = await processManager.run(
      <String>[
        flutterBin,
        ...getLocalEngineArguments(),
        'create',
        '--org',
        'io.flutter.devicelab',
        '--template=plugin',
        '--platforms=$platform',
        '-i',
        iosLanguage,
        pluginName,
      ],
      workingDirectory: workingDirectory,
    );

    expect(
      result.exitCode,
      0,
      reason: 'Failed to create plugin: \n'
          'stdout: \n${result.stdout}\n'
          'stderr: \n${result.stderr}\n',
    );

    final Directory pluginDirectory = fileSystem.directory(
      fileSystem.path.join(workingDirectory, pluginName),
    );

    return SwiftPackageManagerPlugin(
      pluginName: pluginName,
      pluginPath: pluginDirectory.path,
      platform: platform,
    );
  }

  static void addDependency({
    required SwiftPackageManagerPlugin plugin,
    required String appDirectoryPath,
  }) {
    final File pubspec = fileSystem.file(
      fileSystem.path.join(appDirectoryPath, 'pubspec.yaml'),
    );
    final String pubspecContent = pubspec.readAsStringSync();
    pubspec.writeAsStringSync(
      pubspecContent.replaceFirst(
        '\ndependencies:\n',
        '\ndependencies:\n  ${plugin.pluginName}:\n    path: ${plugin.pluginPath}\n',
      ),
    );
  }

  static void disableSwiftPackageManagerByPubspec({
    required String appDirectoryPath,
  }) {
    final File pubspec = fileSystem.file(
      fileSystem.path.join(appDirectoryPath, 'pubspec.yaml'),
    );
    final String pubspecContent = pubspec.readAsStringSync();
    pubspec.writeAsStringSync(
      pubspecContent.replaceFirst(
        '\n# The following section is specific to Flutter packages.\nflutter:\n',
        '\n# The following section is specific to Flutter packages.\nflutter:\n  disable-swift-package-manager: true',
      ),
    );
  }

  static SwiftPackageManagerPlugin integrationTestPlugin(String platform) {
    final String flutterRoot = getFlutterRoot();
    return SwiftPackageManagerPlugin(
      platform: platform,
      pluginName:
          (platform == 'ios') ? 'integration_test' : 'integration_test_macos',
      pluginPath: (platform == 'ios')
          ? fileSystem.path.join(flutterRoot, 'packages', 'integration_test')
          : fileSystem.path.join(flutterRoot, 'packages', 'integration_test', 'integration_test_macos'),
    );
  }

  static List<Pattern> expectedLines({
    required String platform,
    required String appDirectoryPath,
    SwiftPackageManagerPlugin? cocoaPodsPlugin,
    SwiftPackageManagerPlugin? swiftPackagePlugin,
    bool swiftPackageMangerEnabled = false,
    bool migrated = false,
  }) {
    final String frameworkName = platform == 'ios' ? 'Flutter' : 'FlutterMacOS';
    final String appPlatformDirectoryPath = fileSystem.path.join(
      appDirectoryPath,
      platform,
    );

    final List<Pattern> expectedLines = <Pattern>[];
    if (swiftPackageMangerEnabled) {
      expectedLines.addAll(<String>[
        'FlutterGeneratedPluginSwiftPackage: $appPlatformDirectoryPath/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage',
        "➜ Explicit dependency on target 'FlutterGeneratedPluginSwiftPackage' in project 'FlutterGeneratedPluginSwiftPackage'",
      ]);
    }
    if (swiftPackagePlugin != null) {
      // If using a Swift Package plugin, but Swift Package Manager is not enabled, it falls back to being used as a CocoaPods plugin.
      if (swiftPackageMangerEnabled) {
        expectedLines.addAll(<Pattern>[
          RegExp('${swiftPackagePlugin.pluginName}: [/private]*${swiftPackagePlugin.pluginPath}/$platform/${swiftPackagePlugin.pluginName} @ local'),
          "➜ Explicit dependency on target '${swiftPackagePlugin.pluginName}' in project '${swiftPackagePlugin.pluginName}'",
        ]);
      } else {
        expectedLines.addAll(<String>[
          '-> Installing ${swiftPackagePlugin.pluginName} (0.0.1)',
          "➜ Explicit dependency on target '${swiftPackagePlugin.pluginName}' in project 'Pods'",
        ]);
      }
    }
    if (cocoaPodsPlugin != null) {
      expectedLines.addAll(<String>[
        'Running pod install...',
        '-> Installing $frameworkName (1.0.0)',
        '-> Installing ${cocoaPodsPlugin.pluginName} (0.0.1)',
        "Target 'Pods-Runner' in project 'Pods'",
        "➜ Explicit dependency on target '$frameworkName' in project 'Pods'",
        "➜ Explicit dependency on target '${cocoaPodsPlugin.pluginName}' in project 'Pods'",
      ]);
    }
    if (migrated) {
      expectedLines.addAll(<String>[
        'Adding Swift Package Manager integration...',
        'Running pod install...',
        "Target 'Pods-Runner' in project 'Pods'",
      ]);
    }
    return expectedLines;
  }

  static List<String> unexpectedLines({
    required String platform,
    required String appDirectoryPath,
    SwiftPackageManagerPlugin? cocoaPodsPlugin,
    SwiftPackageManagerPlugin? swiftPackagePlugin,
    bool swiftPackageMangerEnabled = false,
    bool migrated = false,
  }) {
    final String frameworkName = platform == 'ios' ? 'Flutter' : 'FlutterMacOS';
    final List<String> unexpectedLines = <String>[];
    if (cocoaPodsPlugin == null && !migrated) {
      unexpectedLines.addAll(<String>[
        'Running pod install...',
        '-> Installing $frameworkName (1.0.0)',
        "Target 'Pods-Runner' in project 'Pods'",
      ]);
    }
    if (swiftPackagePlugin != null) {
      if (swiftPackageMangerEnabled) {
        unexpectedLines.addAll(<String>[
          '-> Installing ${swiftPackagePlugin.pluginName} (0.0.1)',
          "➜ Explicit dependency on target '${swiftPackagePlugin.pluginName}' in project 'Pods'",
        ]);
      } else {
        unexpectedLines.addAll(<String>[
          '${swiftPackagePlugin.pluginName}: ${swiftPackagePlugin.pluginPath}/$platform/${swiftPackagePlugin.pluginName} @ local',
          "➜ Explicit dependency on target '${swiftPackagePlugin.pluginName}' in project '${swiftPackagePlugin.pluginName}'",
        ]);
      }
    }
    if (!migrated) {
      unexpectedLines.addAll(<String>[
        'Adding Swift Package Manager integration...',
      ]);
    }
    return unexpectedLines;
  }
}

class SwiftPackageManagerPlugin {
  SwiftPackageManagerPlugin({
    required this.pluginName,
    required this.pluginPath,
    required this.platform,
  });

  final String pluginName;
  final String pluginPath;
  final String platform;
  String get exampleAppPath => fileSystem.path.join(pluginPath, 'example');
  String get exampleAppPlatformPath => fileSystem.path.join(exampleAppPath, platform);
}
