// 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:package_config/package_config_types.dart';

import 'artifacts.dart';
import 'base/config.dart';
import 'base/context.dart';
import 'base/file_system.dart';
import 'base/logger.dart';
import 'base/os.dart';
import 'base/utils.dart';
import 'convert.dart';
import 'globals.dart' as globals;

/// Whether icon font subsetting is enabled by default.
const bool kIconTreeShakerEnabledDefault = true;

/// Information about a build to be performed or used.
class BuildInfo {
  const BuildInfo(
    this.mode,
    this.flavor, {
    this.trackWidgetCreation = false,
    List<String>? extraFrontEndOptions,
    List<String>? extraGenSnapshotOptions,
    List<String>? fileSystemRoots,
    this.androidProjectArgs = const <String>[],
    this.fileSystemScheme,
    this.buildNumber,
    this.buildName,
    this.splitDebugInfoPath,
    this.dartObfuscation = false,
    List<String>? dartDefines,
    this.bundleSkSLPath,
    List<String>? dartExperiments,
    required this.treeShakeIcons,
    this.performanceMeasurementFile,
    this.dartDefineConfigJsonMap,
    this.packagesPath = '.dart_tool/package_config.json', // TODO(zanderso): make this required and remove the default.
    this.nullSafetyMode = NullSafetyMode.sound,
    this.codeSizeDirectory,
    this.androidGradleDaemon = true,
    this.packageConfig = PackageConfig.empty,
    this.initializeFromDill,
    this.assumeInitializeFromDillUpToDate = false,
  }) : extraFrontEndOptions = extraFrontEndOptions ?? const <String>[],
       extraGenSnapshotOptions = extraGenSnapshotOptions ?? const <String>[],
       fileSystemRoots = fileSystemRoots ?? const <String>[],
       dartDefines = dartDefines ?? const <String>[],
       dartExperiments = dartExperiments ?? const <String>[];

  final BuildMode mode;

  /// The null safety mode the application should be run in.
  ///
  /// If not provided, defaults to [NullSafetyMode.autodetect].
  final NullSafetyMode nullSafetyMode;

  /// Whether the build should subset icon fonts.
  final bool treeShakeIcons;

  /// Represents a custom Android product flavor or an Xcode scheme, null for
  /// using the default.
  ///
  /// If not null, the Gradle build task will be `assembleFlavorMode` (e.g.
  /// `assemblePaidRelease`), and the Xcode build configuration will be
  /// Mode-Flavor (e.g. Release-Paid).
  final String? flavor;

  /// The path to the package configuration file to use for compilation.
  ///
  /// This is used by package:package_config to locate the actual package_config.json
  /// file. If not provided, defaults to `.dart_tool/package_config.json`.
  final String packagesPath;

  final List<String> fileSystemRoots;
  final String? fileSystemScheme;

  /// Whether the build should track widget creation locations.
  final bool trackWidgetCreation;

  /// Extra command-line options for front-end.
  final List<String> extraFrontEndOptions;

  /// Extra command-line options for gen_snapshot.
  final List<String> extraGenSnapshotOptions;

  /// Internal version number (not displayed to users).
  /// Each build must have a unique number to differentiate it from previous builds.
  /// It is used to determine whether one build is more recent than another, with higher numbers indicating more recent build.
  /// On Android it is used as versionCode.
  /// On Xcode builds it is used as CFBundleVersion.
  /// On Windows it is used as the build suffix for the product and file versions.
  final String? buildNumber;

  /// A "x.y.z" string used as the version number shown to users.
  /// For each new version of your app, you will provide a version number to differentiate it from previous versions.
  /// On Android it is used as versionName.
  /// On Xcode builds it is used as CFBundleShortVersionString.
  /// On Windows it is used as the major, minor, and patch parts of the product and file versions.
  final String? buildName;

  /// An optional directory path to save debugging information from dwarf stack
  /// traces. If null, stack trace information is not stripped from the
  /// executable.
  final String? splitDebugInfoPath;

  /// Whether to apply dart source code obfuscation.
  final bool dartObfuscation;

  /// An optional path to a JSON containing object SkSL shaders.
  ///
  /// Currently this is only supported for Android builds.
  final String? bundleSkSLPath;

  /// Additional constant values to be made available in the Dart program.
  ///
  /// These values can be used with the const `fromEnvironment` constructors of
  /// [bool], [String], [int], and [double].
  final List<String> dartDefines;

  /// A list of Dart experiments.
  final List<String> dartExperiments;

  /// The name of a file where flutter assemble will output performance
  /// information in a JSON format.
  ///
  /// This is not considered a build input and will not force assemble to
  /// rerun tasks.
  final String? performanceMeasurementFile;

  /// Configure a constant pool file.
  /// Additional constant values to be made available in the Dart program.
  ///
  /// These values can be used with the const `fromEnvironment` constructors of
  ///  [String] the key and field are json values
  /// json value
  ///
  /// An additional field `dartDefineConfigJsonMap` is provided to represent the native JSON value of the configuration file
  ///
  final Map<String, Object>? dartDefineConfigJsonMap;

  /// If provided, an output directory where one or more v8-style heap snapshots
  /// will be written for code size profiling.
  final String? codeSizeDirectory;

  /// Whether to enable the Gradle daemon when performing an Android build.
  ///
  /// Starting the daemon is the default behavior of the gradle wrapper script created
  /// in a Flutter project. Setting this value to false will cause the tool to pass
  /// `--no-daemon` to the gradle wrapper script, preventing it from spawning a daemon
  /// process.
  ///
  /// For one-off builds or CI systems, preventing the daemon from spawning will
  /// reduce system resource usage, at the cost of any subsequent builds starting
  /// up slightly slower.
  ///
  /// The Gradle daemon may also be disabled in the Android application's properties file.
  final bool androidGradleDaemon;

  /// Additional key value pairs that are passed directly to the gradle project via the `-P`
  /// flag.
  final List<String> androidProjectArgs;

  /// The package configuration for the loaded application.
  ///
  /// This is captured once during startup, but the actual package configuration
  /// may change during a 'flutter run` workflow.
  final PackageConfig packageConfig;

  /// The kernel file that the resident compiler will be initialized with.
  ///
  /// If this is null, it will be initialized from the default cached location.
  final String? initializeFromDill;

  /// If set, assumes that the file passed in [initializeFromDill] is up to date
  /// and skips the check and potential invalidation of files.
  final bool assumeInitializeFromDillUpToDate;

  static const BuildInfo debug = BuildInfo(BuildMode.debug, null, trackWidgetCreation: true, treeShakeIcons: false);
  static const BuildInfo profile = BuildInfo(BuildMode.profile, null, treeShakeIcons: kIconTreeShakerEnabledDefault);
  static const BuildInfo jitRelease = BuildInfo(BuildMode.jitRelease, null, treeShakeIcons: kIconTreeShakerEnabledDefault);
  static const BuildInfo release = BuildInfo(BuildMode.release, null, treeShakeIcons: kIconTreeShakerEnabledDefault);

  /// Returns whether a debug build is requested.
  ///
  /// Exactly one of [isDebug], [isProfile], or [isRelease] is true.
  bool get isDebug => mode == BuildMode.debug;

  /// Returns whether a profile build is requested.
  ///
  /// Exactly one of [isDebug], [isProfile], [isJitRelease],
  /// or [isRelease] is true.
  bool get isProfile => mode == BuildMode.profile;

  /// Returns whether a release build is requested.
  ///
  /// Exactly one of [isDebug], [isProfile], [isJitRelease],
  /// or [isRelease] is true.
  bool get isRelease => mode == BuildMode.release;

  /// Returns whether a JIT release build is requested.
  ///
  /// Exactly one of [isDebug], [isProfile], [isJitRelease],
  /// or [isRelease] is true.
  bool get isJitRelease => mode == BuildMode.jitRelease;

  bool get usesAot => isAotBuildMode(mode);
  bool get supportsEmulator => isEmulatorBuildMode(mode);
  bool get supportsSimulator => isEmulatorBuildMode(mode);
  String get modeName => getModeName(mode);
  String get friendlyModeName => getFriendlyModeName(mode);

  /// the flavor name in the output apk files is lower-cased (see flutter.gradle),
  /// so the lower cased flavor name is used to compute the output file name
  String? get lowerCasedFlavor => flavor?.toLowerCase();

  /// the flavor name in the output bundle files has the first character lower-cased,
  /// so the uncapitalized flavor name is used to compute the output file name
  String? get uncapitalizedFlavor => _uncapitalize(flavor);

  /// Convert to a structured string encoded structure appropriate for usage
  /// in build system [Environment.defines].
  ///
  /// Fields that are `null` are excluded from this configuration.
  Map<String, String> toBuildSystemEnvironment() {
    // packagesPath and performanceMeasurementFile are not passed into
    // the Environment map.
    return <String, String>{
      kBuildMode: getNameForBuildMode(mode),
      if (dartDefines.isNotEmpty)
        kDartDefines: encodeDartDefines(dartDefines),
      if (dartObfuscation != null)
        kDartObfuscation: dartObfuscation.toString(),
      if (extraFrontEndOptions.isNotEmpty)
        kExtraFrontEndOptions: extraFrontEndOptions.join(','),
      if (extraGenSnapshotOptions.isNotEmpty)
        kExtraGenSnapshotOptions: extraGenSnapshotOptions.join(','),
      if (splitDebugInfoPath != null)
        kSplitDebugInfo: splitDebugInfoPath!,
      if (trackWidgetCreation != null)
        kTrackWidgetCreation: trackWidgetCreation.toString(),
      if (treeShakeIcons != null)
        kIconTreeShakerFlag: treeShakeIcons.toString(),
      if (bundleSkSLPath != null)
        kBundleSkSLPath: bundleSkSLPath!,
      if (codeSizeDirectory != null)
        kCodeSizeDirectory: codeSizeDirectory!,
      if (fileSystemRoots.isNotEmpty)
        kFileSystemRoots: fileSystemRoots.join(','),
      if (fileSystemScheme != null)
        kFileSystemScheme: fileSystemScheme!,
      if (buildName != null)
        kBuildName: buildName!,
      if (buildNumber != null)
        kBuildNumber: buildNumber!,
    };
  }


  /// Convert to a structured string encoded structure appropriate for usage as
  /// environment variables or to embed in other scripts.
  ///
  /// Fields that are `null` are excluded from this configuration.
  Map<String, String> toEnvironmentConfig() {
    final Map<String, String> map = <String, String>{};
    dartDefineConfigJsonMap?.forEach((String key, Object value) {
      map[key] = '$value';
    });
    final Map<String, String> environmentMap = <String, String>{
      if (dartDefines.isNotEmpty)
        'DART_DEFINES': encodeDartDefines(dartDefines),
      if (dartObfuscation != null)
        'DART_OBFUSCATION': dartObfuscation.toString(),
      if (extraFrontEndOptions.isNotEmpty)
        'EXTRA_FRONT_END_OPTIONS': extraFrontEndOptions.join(','),
      if (extraGenSnapshotOptions.isNotEmpty)
        'EXTRA_GEN_SNAPSHOT_OPTIONS': extraGenSnapshotOptions.join(','),
      if (splitDebugInfoPath != null)
        'SPLIT_DEBUG_INFO': splitDebugInfoPath!,
      if (trackWidgetCreation != null)
        'TRACK_WIDGET_CREATION': trackWidgetCreation.toString(),
      if (treeShakeIcons != null)
        'TREE_SHAKE_ICONS': treeShakeIcons.toString(),
      if (performanceMeasurementFile != null)
        'PERFORMANCE_MEASUREMENT_FILE': performanceMeasurementFile!,
      if (bundleSkSLPath != null)
        'BUNDLE_SKSL_PATH': bundleSkSLPath!,
      if (packagesPath != null)
        'PACKAGE_CONFIG': packagesPath,
      if (codeSizeDirectory != null)
        'CODE_SIZE_DIRECTORY': codeSizeDirectory!,
    };
    map.forEach((String key, String value) {
      if (environmentMap.containsKey(key)) {
        globals.printWarning(
            'The key: [$key] already exists, you cannot use environment variables that have been used by the system!');
      } else {
        // System priority is greater than user priority
        environmentMap[key] = value;
      }
    });
    return environmentMap;
  }

  /// Convert this config to a series of project level arguments to be passed
  /// on the command line to gradle.
  List<String> toGradleConfig() {
    // PACKAGE_CONFIG not currently supported.
    final List<String> result = <String>[
      if (dartDefines.isNotEmpty)
        '-Pdart-defines=${encodeDartDefines(dartDefines)}',
      if (dartObfuscation != null)
        '-Pdart-obfuscation=$dartObfuscation',
      if (extraFrontEndOptions.isNotEmpty)
        '-Pextra-front-end-options=${extraFrontEndOptions.join(',')}',
      if (extraGenSnapshotOptions.isNotEmpty)
        '-Pextra-gen-snapshot-options=${extraGenSnapshotOptions.join(',')}',
      if (splitDebugInfoPath != null)
        '-Psplit-debug-info=$splitDebugInfoPath',
      if (trackWidgetCreation != null)
        '-Ptrack-widget-creation=$trackWidgetCreation',
      if (treeShakeIcons != null)
        '-Ptree-shake-icons=$treeShakeIcons',
      if (performanceMeasurementFile != null)
        '-Pperformance-measurement-file=$performanceMeasurementFile',
      if (bundleSkSLPath != null)
        '-Pbundle-sksl-path=$bundleSkSLPath',
      if (codeSizeDirectory != null)
        '-Pcode-size-directory=$codeSizeDirectory',
      for (String projectArg in androidProjectArgs)
        '-P$projectArg',
    ];
    if (dartDefineConfigJsonMap != null) {
      final Iterable<String> gradleConfKeys = result.map((final String gradleConf) => gradleConf.split('=')[0].substring(2));
      dartDefineConfigJsonMap!.forEach((String key, Object value) {
        if (gradleConfKeys.contains(key)) {
          globals.printWarning(
              'The key: [$key] already exists, you cannot use gradle variables that have been used by the system!');
        } else {
          result.add('-P$key=$value');
        }
      });
    }
    return result;
  }
}

/// Information about an Android build to be performed or used.
class AndroidBuildInfo {
  const AndroidBuildInfo(
    this.buildInfo, {
    this.targetArchs = const <AndroidArch>[
      AndroidArch.armeabi_v7a,
      AndroidArch.arm64_v8a,
      AndroidArch.x86_64,
    ],
    this.splitPerAbi = false,
    this.fastStart = false,
    this.multidexEnabled = false,
  });

  // The build info containing the mode and flavor.
  final BuildInfo buildInfo;

  /// Whether to split the shared library per ABI.
  ///
  /// When this is false, multiple ABIs will be contained within one primary
  /// build artifact. When this is true, multiple build artifacts (one per ABI)
  /// will be produced.
  final bool splitPerAbi;

  /// The target platforms for the build.
  final Iterable<AndroidArch> targetArchs;

  /// Whether to bootstrap an empty application.
  final bool fastStart;

  /// Whether to enable multidex support for apps with more than 64k methods.
  final bool multidexEnabled;
}

/// A summary of the compilation strategy used for Dart.
class BuildMode {
  const BuildMode._(this.name);

  factory BuildMode.fromName(String value) {
    switch (value) {
      case 'debug':
        return BuildMode.debug;
      case 'profile':
        return BuildMode.profile;
      case 'release':
        return BuildMode.release;
      case 'jit_release':
        return BuildMode.jitRelease;
    }
    throw ArgumentError('$value is not a supported build mode');
  }

  /// Built in JIT mode with no optimizations, enabled asserts, and an observatory.
  static const BuildMode debug = BuildMode._('debug');

  /// Built in AOT mode with some optimizations and an observatory.
  static const BuildMode profile = BuildMode._('profile');

  /// Built in AOT mode with all optimizations and no observatory.
  static const BuildMode release = BuildMode._('release');

  /// Built in JIT mode with all optimizations and no observatory.
  static const BuildMode jitRelease = BuildMode._('jit_release');

  static const List<BuildMode> values = <BuildMode>[
    debug,
    profile,
    release,
    jitRelease,
  ];
  static const Set<BuildMode> releaseModes = <BuildMode>{
    release,
    jitRelease,
  };
  static const Set<BuildMode> jitModes = <BuildMode>{
    debug,
    jitRelease,
  };

  /// Whether this mode is considered release.
  ///
  /// Useful for determining whether we should enable/disable asserts or
  /// other development features.
  bool get isRelease => releaseModes.contains(this);

  /// Whether this mode is using the JIT runtime.
  bool get isJit => jitModes.contains(this);

  /// Whether this mode is using the precompiled runtime.
  bool get isPrecompiled => !isJit;

  /// The name for this build mode.
  final String name;

  @override
  String toString() => name;
}

/// Return the name for the build mode, or "any" if null.
String getNameForBuildMode(BuildMode buildMode) {
  return buildMode.name;
}

/// Returns the [BuildMode] for a particular `name`.
BuildMode getBuildModeForName(String name) {
  return BuildMode.fromName(name);
}

/// Environment type of the target device.
enum EnvironmentType {
  physical,
  simulator,
}

String? validatedBuildNumberForPlatform(TargetPlatform targetPlatform, String? buildNumber, Logger logger) {
  if (buildNumber == null) {
    return null;
  }
  if (targetPlatform == TargetPlatform.ios ||
      targetPlatform == TargetPlatform.darwin) {
    // See CFBundleVersion at https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
    final RegExp disallowed = RegExp(r'[^\d\.]');
    String tmpBuildNumber = buildNumber.replaceAll(disallowed, '');
    if (tmpBuildNumber.isEmpty) {
      return null;
    }
    final List<String> segments = tmpBuildNumber
        .split('.')
        .where((String segment) => segment.isNotEmpty)
        .toList();
    if (segments.isEmpty) {
      segments.add('0');
    }
    tmpBuildNumber = segments.join('.');
    if (tmpBuildNumber != buildNumber) {
      logger.printTrace('Invalid build-number: $buildNumber for iOS/macOS, overridden by $tmpBuildNumber.\n'
          'See CFBundleVersion at https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html');
    }
    return tmpBuildNumber;
  }
  if (targetPlatform == TargetPlatform.android_arm ||
      targetPlatform == TargetPlatform.android_arm64 ||
      targetPlatform == TargetPlatform.android_x64 ||
      targetPlatform == TargetPlatform.android_x86) {
    // See versionCode at https://developer.android.com/studio/publish/versioning
    final RegExp disallowed = RegExp(r'[^\d]');
    String tmpBuildNumberStr = buildNumber.replaceAll(disallowed, '');
    int tmpBuildNumberInt = int.tryParse(tmpBuildNumberStr) ?? 0;
    if (tmpBuildNumberInt < 1) {
      tmpBuildNumberInt = 1;
    }
    tmpBuildNumberStr = tmpBuildNumberInt.toString();
    if (tmpBuildNumberStr != buildNumber) {
      logger.printTrace('Invalid build-number: $buildNumber for Android, overridden by $tmpBuildNumberStr.\n'
          'See versionCode at https://developer.android.com/studio/publish/versioning');
    }
    return tmpBuildNumberStr;
  }
  return buildNumber;
}

String? validatedBuildNameForPlatform(TargetPlatform targetPlatform, String? buildName, Logger logger) {
  if (buildName == null) {
    return null;
  }
  if (targetPlatform == TargetPlatform.ios ||
      targetPlatform == TargetPlatform.darwin) {
    // See CFBundleShortVersionString at https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
    final RegExp disallowed = RegExp(r'[^\d\.]');
    String tmpBuildName = buildName.replaceAll(disallowed, '');
    if (tmpBuildName.isEmpty) {
      return null;
    }
    final List<String> segments = tmpBuildName
        .split('.')
        .where((String segment) => segment.isNotEmpty)
        .toList();
    while (segments.length < 3) {
      segments.add('0');
    }
    tmpBuildName = segments.join('.');
    if (tmpBuildName != buildName) {
      logger.printTrace('Invalid build-name: $buildName for iOS/macOS, overridden by $tmpBuildName.\n'
          'See CFBundleShortVersionString at https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html');
    }
    return tmpBuildName;
  }
  if (targetPlatform == TargetPlatform.android ||
      targetPlatform == TargetPlatform.android_arm ||
      targetPlatform == TargetPlatform.android_arm64 ||
      targetPlatform == TargetPlatform.android_x64 ||
      targetPlatform == TargetPlatform.android_x86) {
    // See versionName at https://developer.android.com/studio/publish/versioning
    return buildName;
  }
  return buildName;
}

String getModeName(BuildMode mode) => getEnumName(mode);

String getFriendlyModeName(BuildMode mode) {
  return snakeCase(getModeName(mode)).replaceAll('_', ' ');
}

// Returns true if the selected build mode uses ahead-of-time compilation.
bool isAotBuildMode(BuildMode mode) {
  return mode == BuildMode.profile || mode == BuildMode.release;
}

// Returns true if the given build mode can be used on emulators / simulators.
bool isEmulatorBuildMode(BuildMode mode) {
  return mode == BuildMode.debug;
}

enum TargetPlatform {
  android,
  ios,
  darwin,
  linux_x64,
  linux_arm64,
  windows_x64,
  fuchsia_arm64,
  fuchsia_x64,
  tester,
  web_javascript,
  // The arch specific android target platforms are soft-deprecated.
  // Instead of using TargetPlatform as a combination arch + platform
  // the code will be updated to carry arch information in [DarwinArch]
  // and [AndroidArch].
  android_arm,
  android_arm64,
  android_x64,
  android_x86,
}

/// iOS and macOS target device architecture.
//
// TODO(cbracken): split TargetPlatform.ios into ios_armv7, ios_arm64.
enum DarwinArch {
  armv7, // Deprecated. Used to display 32-bit unsupported devices.
  arm64,
  x86_64,
}

// TODO(zanderso): replace all android TargetPlatform usage with AndroidArch.
enum AndroidArch {
  armeabi_v7a,
  arm64_v8a,
  x86,
  x86_64,
}

/// The default set of iOS device architectures to build for.
List<DarwinArch> defaultIOSArchsForEnvironment(
  EnvironmentType environmentType,
  Artifacts artifacts,
) {
  // Handle single-arch local engines.
  if (artifacts is LocalEngineArtifacts) {
    final String localEngineName = artifacts.localEngineName;
    if (localEngineName.contains('_arm64')) {
      return <DarwinArch>[ DarwinArch.arm64 ];
    }
    if (localEngineName.contains('_sim')) {
      return <DarwinArch>[ DarwinArch.x86_64 ];
    }
  } else if (environmentType == EnvironmentType.simulator) {
    return <DarwinArch>[
      DarwinArch.x86_64,
      DarwinArch.arm64,
    ];
  }
  return <DarwinArch>[
    DarwinArch.arm64,
  ];
}

/// The default set of macOS device architectures to build for.
List<DarwinArch> defaultMacOSArchsForEnvironment(Artifacts artifacts) {
  // Handle single-arch local engines.
  if (artifacts is LocalEngineArtifacts) {
    if (artifacts.localEngineName.contains('_arm64')) {
      return <DarwinArch>[ DarwinArch.arm64 ];
    }
    return <DarwinArch>[ DarwinArch.x86_64 ];
  }
  return <DarwinArch>[
    DarwinArch.x86_64,
    DarwinArch.arm64,
  ];
}

// Returns the Dart SDK's name for the specified target architecture.
//
// When building for Darwin platforms, the tool invokes architecture-specific
// variants of `gen_snapshot`, one for each target architecture. The output
// instructions are then built into architecture-specific binaries, which are
// merged into a universal binary using the `lipo` tool.
String getDartNameForDarwinArch(DarwinArch arch) {
  switch (arch) {
    case DarwinArch.armv7:
      return 'armv7';
    case DarwinArch.arm64:
      return 'arm64';
    case DarwinArch.x86_64:
      return 'x64';
  }
}

// Returns Apple's name for the specified target architecture.
//
// When invoking Apple tools such as `xcodebuild` or `lipo`, the tool often
// passes one or more target architectures as parameters. The names returned by
// this function reflect Apple's name for the specified architecture.
//
// For consistency with developer expectations, Flutter outputs also use these
// architecture names in its build products for Darwin target platforms.
String getNameForDarwinArch(DarwinArch arch) {
  switch (arch) {
    case DarwinArch.armv7:
      return 'armv7';
    case DarwinArch.arm64:
      return 'arm64';
    case DarwinArch.x86_64:
      return 'x86_64';
  }
}

DarwinArch getIOSArchForName(String arch) {
  switch (arch) {
    case 'armv7':
    case 'armv7f': // iPhone 4S.
    case 'armv7s': // iPad 4.
      return DarwinArch.armv7;
    case 'arm64':
    case 'arm64e': // iPhone XS/XS Max/XR and higher. arm64 runs on arm64e devices.
      return DarwinArch.arm64;
    case 'x86_64':
      return DarwinArch.x86_64;
  }
  throw Exception('Unsupported iOS arch name "$arch"');
}

DarwinArch getDarwinArchForName(String arch) {
  switch (arch) {
    case 'arm64':
      return DarwinArch.arm64;
    case 'x86_64':
      return DarwinArch.x86_64;
  }
  throw Exception('Unsupported MacOS arch name "$arch"');
}

String getNameForTargetPlatform(TargetPlatform platform, {DarwinArch? darwinArch}) {
  switch (platform) {
    case TargetPlatform.android_arm:
      return 'android-arm';
    case TargetPlatform.android_arm64:
      return 'android-arm64';
    case TargetPlatform.android_x64:
      return 'android-x64';
    case TargetPlatform.android_x86:
      return 'android-x86';
    case TargetPlatform.ios:
      if (darwinArch != null) {
        return 'ios-${getNameForDarwinArch(darwinArch)}';
      }
      return 'ios';
    case TargetPlatform.darwin:
      if (darwinArch != null) {
        return 'darwin-${getNameForDarwinArch(darwinArch)}';
      }
      return 'darwin';
    case TargetPlatform.linux_x64:
      return 'linux-x64';
    case TargetPlatform.linux_arm64:
      return 'linux-arm64';
    case TargetPlatform.windows_x64:
      return 'windows-x64';
    case TargetPlatform.fuchsia_arm64:
      return 'fuchsia-arm64';
    case TargetPlatform.fuchsia_x64:
      return 'fuchsia-x64';
    case TargetPlatform.tester:
      return 'flutter-tester';
    case TargetPlatform.web_javascript:
      return 'web-javascript';
    case TargetPlatform.android:
      return 'android';
  }
}

TargetPlatform getTargetPlatformForName(String platform) {
  switch (platform) {
    case 'android':
      return TargetPlatform.android;
    case 'android-arm':
      return TargetPlatform.android_arm;
    case 'android-arm64':
      return TargetPlatform.android_arm64;
    case 'android-x64':
      return TargetPlatform.android_x64;
    case 'android-x86':
      return TargetPlatform.android_x86;
    case 'fuchsia-arm64':
      return TargetPlatform.fuchsia_arm64;
    case 'fuchsia-x64':
      return TargetPlatform.fuchsia_x64;
    case 'ios':
      return TargetPlatform.ios;
    case 'darwin':
    // For backward-compatibility and also for Tester, where it must match
    // host platform name (HostPlatform.darwin_x64)
    case 'darwin-x64':
    case 'darwin-arm64':
      return TargetPlatform.darwin;
    case 'linux-x64':
      return TargetPlatform.linux_x64;
   case 'linux-arm64':
      return TargetPlatform.linux_arm64;
    case 'windows-x64':
      return TargetPlatform.windows_x64;
    case 'web-javascript':
      return TargetPlatform.web_javascript;
  }
  throw Exception('Unsupported platform name "$platform"');
}

AndroidArch getAndroidArchForName(String platform) {
  switch (platform) {
    case 'android-arm':
      return AndroidArch.armeabi_v7a;
    case 'android-arm64':
      return AndroidArch.arm64_v8a;
    case 'android-x64':
      return AndroidArch.x86_64;
    case 'android-x86':
      return AndroidArch.x86;
  }
  throw Exception('Unsupported Android arch name "$platform"');
}

String getNameForAndroidArch(AndroidArch arch) {
  switch (arch) {
    case AndroidArch.armeabi_v7a:
      return 'armeabi-v7a';
    case AndroidArch.arm64_v8a:
      return 'arm64-v8a';
    case AndroidArch.x86_64:
      return 'x86_64';
    case AndroidArch.x86:
      return 'x86';
  }
}

String getPlatformNameForAndroidArch(AndroidArch arch) {
  switch (arch) {
    case AndroidArch.armeabi_v7a:
      return 'android-arm';
    case AndroidArch.arm64_v8a:
      return 'android-arm64';
    case AndroidArch.x86_64:
      return 'android-x64';
    case AndroidArch.x86:
      return 'android-x86';
  }
}

String fuchsiaArchForTargetPlatform(TargetPlatform targetPlatform) {
  switch (targetPlatform) {
    case TargetPlatform.fuchsia_arm64:
      return 'arm64';
    case TargetPlatform.fuchsia_x64:
      return 'x64';
    case TargetPlatform.android:
    case TargetPlatform.android_arm:
    case TargetPlatform.android_arm64:
    case TargetPlatform.android_x64:
    case TargetPlatform.android_x86:
    case TargetPlatform.darwin:
    case TargetPlatform.ios:
    case TargetPlatform.linux_arm64:
    case TargetPlatform.linux_x64:
    case TargetPlatform.tester:
    case TargetPlatform.web_javascript:
    case TargetPlatform.windows_x64:
      throw UnsupportedError('Unexpected Fuchsia platform $targetPlatform');
  }
}

HostPlatform getCurrentHostPlatform() {
  if (globals.platform.isMacOS) {
    return HostPlatform.darwin_x64;
  }
  if (globals.platform.isLinux) {
    // support x64 and arm64 architecture.
    return globals.os.hostPlatform;
  }
  if (globals.platform.isWindows) {
    return HostPlatform.windows_x64;
  }

  globals.printWarning('Unsupported host platform, defaulting to Linux');

  return HostPlatform.linux_x64;
}

/// Returns the top-level build output directory.
String getBuildDirectory([Config? config, FileSystem? fileSystem]) {
  // TODO(johnmccutchan): Stop calling this function as part of setting
  // up command line argument processing.
  if (context == null) {
    return 'build';
  }
  final Config localConfig = config ?? globals.config;
  final FileSystem localFilesystem = fileSystem ?? globals.fs;
  if (localConfig == null) {
    return 'build';
  }

  final String buildDir = localConfig.getValue('build-dir') as String? ?? 'build';
  if (localFilesystem.path.isAbsolute(buildDir)) {
    throw Exception(
        'build-dir config setting in ${globals.config.configPath} must be relative');
  }
  return buildDir;
}

/// Returns the Android build output directory.
String getAndroidBuildDirectory() {
  // TODO(cbracken): move to android subdir.
  return getBuildDirectory();
}

/// Returns the AOT build output directory.
String getAotBuildDirectory() {
  return globals.fs.path.join(getBuildDirectory(), 'aot');
}

/// Returns the asset build output directory.
String getAssetBuildDirectory() {
  return globals.fs.path.join(getBuildDirectory(), 'flutter_assets');
}

/// Returns the iOS build output directory.
String getIosBuildDirectory() {
  return globals.fs.path.join(getBuildDirectory(), 'ios');
}

/// Returns the macOS build output directory.
String getMacOSBuildDirectory() {
  return globals.fs.path.join(getBuildDirectory(), 'macos');
}

/// Returns the web build output directory.
String getWebBuildDirectory() {
  return globals.fs.path.join(getBuildDirectory(), 'web');
}

/// Returns the Linux build output directory.
String getLinuxBuildDirectory([TargetPlatform? targetPlatform]) {
  final String arch = (targetPlatform == null) ?
      _getCurrentHostPlatformArchName() :
      getNameForTargetPlatformArch(targetPlatform);
  final String subDirs = 'linux/$arch';
  return globals.fs.path.join(getBuildDirectory(), subDirs);
}

/// Returns the Windows build output directory.
String getWindowsBuildDirectory() {
  return globals.fs.path.join(getBuildDirectory(), 'windows');
}

/// Returns the Fuchsia build output directory.
String getFuchsiaBuildDirectory() {
  return globals.fs.path.join(getBuildDirectory(), 'fuchsia');
}

/// Defines specified via the `--dart-define` command-line option.
///
/// These values are URI-encoded and then combined into a comma-separated string.
const String kDartDefines = 'DartDefines';

/// The define to pass a [BuildMode].
const String kBuildMode = 'BuildMode';

/// The define to pass whether we compile 64-bit android-arm code.
const String kTargetPlatform = 'TargetPlatform';

/// The define to control what target file is used.
const String kTargetFile = 'TargetFile';

/// Whether to enable or disable track widget creation.
const String kTrackWidgetCreation = 'TrackWidgetCreation';

/// Additional configuration passed to the dart front end.
///
/// This is expected to be a comma separated list of strings.
const String kExtraFrontEndOptions = 'ExtraFrontEndOptions';

/// Additional configuration passed to gen_snapshot.
///
/// This is expected to be a comma separated list of strings.
const String kExtraGenSnapshotOptions = 'ExtraGenSnapshotOptions';

/// Whether the build should run gen_snapshot as a split aot build for deferred
/// components.
const String kDeferredComponents = 'DeferredComponents';

/// Whether to strip source code information out of release builds and where to save it.
const String kSplitDebugInfo = 'SplitDebugInfo';

/// Alternative scheme for file URIs.
///
/// May be used along with [kFileSystemRoots] to support a multi-root
/// filesystem.
const String kFileSystemScheme = 'FileSystemScheme';

/// Additional filesystem roots.
///
/// If provided, must be used along with [kFileSystemScheme].
const String kFileSystemRoots = 'FileSystemRoots';

/// The define to control what iOS architectures are built for.
///
/// This is expected to be a space-delimited list of architectures. If not
/// provided, defaults to arm64.
const String kIosArchs = 'IosArchs';

/// The define to control what macOS architectures are built for.
///
/// This is expected to be a space-delimited list of architectures. If not
/// provided, defaults to x86_64.
///
/// Supported values are x86_64 and arm64.
const String kDarwinArchs = 'DarwinArchs';

/// Path to the SDK root to be used as the isysroot.
const String kSdkRoot = 'SdkRoot';

/// Whether to enable Dart obfuscation and where to save the symbol map.
const String kDartObfuscation = 'DartObfuscation';

/// An output directory where one or more code-size measurements may be written.
const String kCodeSizeDirectory = 'CodeSizeDirectory';

/// SHA identifier of the Apple developer code signing identity.
///
/// Same as EXPANDED_CODE_SIGN_IDENTITY Xcode build setting.
/// Also discoverable via `security find-identity -p codesigning`.
const String kCodesignIdentity = 'CodesignIdentity';

/// The build define controlling whether icon fonts should be stripped down to
/// only the glyphs used by the application.
const String kIconTreeShakerFlag = 'TreeShakeIcons';

/// The input key for an SkSL bundle path.
const String kBundleSkSLPath = 'BundleSkSLPath';

/// The define to pass build name
const String kBuildName = 'BuildName';

/// The define to pass build number
const String kBuildNumber = 'BuildNumber';

/// The action Xcode is taking.
///
/// Will be "build" when building and "install" when archiving.
const String kXcodeAction = 'Action';

final Converter<String, String> _defineEncoder = utf8.encoder.fuse(base64.encoder);
final Converter<String, String> _defineDecoder = base64.decoder.fuse(utf8.decoder);

/// Encode a List of dart defines in a base64 string.
///
/// This encoding does not include `,`, which is used to distinguish
/// the individual entries, nor does it include `%` which is often a
/// control character on windows command lines.
///
/// When decoding this string, it can be safely split on commas, since any
/// user provided commands will still be encoded.
///
/// If the presence of the `/` character ends up being an issue, this can
/// be changed to use base32 instead.
String encodeDartDefines(List<String> defines) {
  return defines.map(_defineEncoder.convert).join(',');
}

List<String> decodeCommaSeparated(Map<String, String> environmentDefines, String key) {
  if (!environmentDefines.containsKey(key) || environmentDefines[key]!.isEmpty) {
    return <String>[];
  }
  return environmentDefines[key]!
    .split(',')
    .cast<String>()
    .toList();
}

/// Dart defines are encoded inside [environmentDefines] as a comma-separated list.
List<String> decodeDartDefines(Map<String, String> environmentDefines, String key) {
  if (!environmentDefines.containsKey(key) || environmentDefines[key]!.isEmpty) {
    return <String>[];
  }
  return environmentDefines[key]!
    .split(',')
    .map<Object>(_defineDecoder.convert)
    .cast<String>()
    .toList();
}

/// The null safety runtime mode the app should be built in.
enum NullSafetyMode {
  sound,
  unsound,
  /// The null safety mode was not detected. Only supported for 'flutter test'.
  autodetect,
}

String _getCurrentHostPlatformArchName() {
  final HostPlatform hostPlatform = getCurrentHostPlatform();
  return getNameForHostPlatformArch(hostPlatform);
}

String getNameForTargetPlatformArch(TargetPlatform platform) {
  switch (platform) {
    case TargetPlatform.linux_x64:
    case TargetPlatform.darwin:
    case TargetPlatform.windows_x64:
      return 'x64';
    case TargetPlatform.linux_arm64:
      return 'arm64';
    case TargetPlatform.android:
    case TargetPlatform.android_arm:
    case TargetPlatform.android_arm64:
    case TargetPlatform.android_x64:
    case TargetPlatform.android_x86:
    case TargetPlatform.fuchsia_arm64:
    case TargetPlatform.fuchsia_x64:
    case TargetPlatform.ios:
    case TargetPlatform.tester:
    case TargetPlatform.web_javascript:
      throw UnsupportedError('Unexpected target platform $platform');
  }
}

String getNameForHostPlatformArch(HostPlatform platform) {
  switch (platform) {
    case HostPlatform.darwin_x64:
      return 'x64';
    case HostPlatform.darwin_arm64:
      return 'arm64';
    case HostPlatform.linux_x64:
      return 'x64';
    case HostPlatform.linux_arm64:
      return 'arm64';
    case HostPlatform.windows_x64:
      return 'x64';
  }
}

String? _uncapitalize(String? s) {
  if (s == null || s.isEmpty) {
    return s;
  }
  return s.substring(0, 1).toLowerCase() + s.substring(1);
}
