// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. 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:_fe_analyzer_shared/src/base/analyzer_public_api.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:meta/meta.dart';
import 'package:pub_semver/pub_semver.dart';

/// The same as [ExperimentStatus.knownFeatures], except when a call to
/// [overrideKnownFeatures] is in progress.
Map<String, ExperimentalFeature> _knownFeatures =
    ExperimentStatus.knownFeatures;

/// This flag is `true` while [overrideKnownFeaturesAsync] is executing.
bool _overrideKnownFeaturesAsyncExecuting = false;

/// Decodes the strings given in [flags] into a list of booleans representing
/// experiments that should be enabled.
///
/// Always succeeds, even if the input flags are invalid.  Expired and
/// unrecognized flags are ignored, conflicting flags are resolved in favor of
/// the flag appearing last.
EnabledDisabledFlags decodeExplicitFlags(List<String> flags) {
  var enabledFlags = List<bool>.filled(_knownFeatures.length, false);
  var disabledFlags = List<bool>.filled(_knownFeatures.length, false);
  for (var entry in _flagStringsToMap(flags).entries) {
    if (entry.value) {
      enabledFlags[entry.key] = true;
    } else {
      disabledFlags[entry.key] = true;
    }
  }
  return EnabledDisabledFlags(enabledFlags, disabledFlags);
}

/// Pretty-prints the given set of enable flags as a set of feature names.
String experimentStatusToString(List<bool> enableFlags) {
  var featuresInSet = <String>[];
  for (var feature in _knownFeatures.values) {
    if (enableFlags[feature.index]) {
      featuresInSet.add(feature.enableString);
    }
  }
  return 'FeatureSet{${featuresInSet.join(', ')}}';
}

/// Execute the callback, pretending that the given [knownFeatures] take the
/// place of [ExperimentStatus.knownFeatures].
///
/// It isn't safe to call this method with an asynchronous callback, because it
/// only changes the set of known features during the time that [callback] is
/// (synchronously) executing. Use [overrideKnownFeaturesAsync] instead.
@visibleForTesting
T overrideKnownFeatures<T>(
  Map<String, ExperimentalFeature> knownFeatures,
  T Function() callback,
) {
  var oldKnownFeatures = _knownFeatures;
  try {
    _knownFeatures = knownFeatures;
    return callback();
  } finally {
    _knownFeatures = oldKnownFeatures;
  }
}

/// Execute the callback, pretending that the given [knownFeatures] take the
/// place of [ExperimentStatus.knownFeatures].
///
/// This function cannot be invoked before its previous invocation completes.
@visibleForTesting
Future<T> overrideKnownFeaturesAsync<T>(
  Map<String, ExperimentalFeature> knownFeatures,
  Future<T> Function() callback,
) async {
  if (_overrideKnownFeaturesAsyncExecuting) {
    throw StateError('overrideKnownFeaturesAsync is not reentrant');
  }

  _overrideKnownFeaturesAsyncExecuting = true;
  var oldKnownFeatures = _knownFeatures;
  try {
    _knownFeatures = knownFeatures;
    return await callback();
  } finally {
    _knownFeatures = oldKnownFeatures;
    _overrideKnownFeaturesAsyncExecuting = false;
  }
}

/// Computes a new set of enable flags based on [version].
///
/// Features in [explicitEnabledFlags] are enabled in the [sdkLanguageVersion].
///
/// Features in [explicitDisabledFlags] are always disabled.
List<bool> restrictEnableFlagsToVersion({
  required Version sdkLanguageVersion,
  required List<bool> explicitEnabledFlags,
  required List<bool> explicitDisabledFlags,
  required Version version,
}) {
  var decodedFlags = List.filled(_knownFeatures.length, false);
  for (var feature in _knownFeatures.values) {
    if (explicitDisabledFlags[feature.index]) {
      decodedFlags[feature.index] = false;
      continue;
    }

    var releaseVersion = feature.releaseVersion;
    if (releaseVersion != null && version >= releaseVersion) {
      decodedFlags[feature.index] = true;
    }

    if (explicitEnabledFlags[feature.index]) {
      var experimentalReleaseVersion = feature.experimentalReleaseVersion;
      if (experimentalReleaseVersion == null) {
        // Specifically, the current sdk version (whatever it is) is always
        // used as the language version which opts code into the experiment
        // when the experiment flag is passed.
        if (version == sdkLanguageVersion) {
          decodedFlags[feature.index] = true;
        }
      } else {
        // An experiment flag may at any point be assigned an experimental
        // release version.  From that point forward, all tools will no
        // longer use the current sdk version to opt code in, but rather
        // will use the experimental release version as the opt in version.
        // Updated 2020-08-25: we decided that experimental features should
        // be available since `min(sdk, experimentalRelease)`.
        if (version >= experimentalReleaseVersion ||
            version >= sdkLanguageVersion) {
          decodedFlags[feature.index] = true;
        }
      }
    }
  }

  return decodedFlags;
}

/// Validates whether there are any disagreements between the strings given in
/// [flags1] and the strings given in [flags2].
///
/// The returned iterable yields any problems that were found.  Only reports
/// problems related to combining the flags; problems that would be found by
/// applying [validateFlags] to [flags1] or [flags2] individually are not
/// reported.
///
/// If no problems are found, it is safe to concatenate the flag lists.  If
/// problems are found, the only negative side effect is that some flags in
/// one list may be overridden by some flags in the other list.
///
// TODO(paulberry): if this method ever needs to be exposed via the analyzer
// public API, consider making a version that reports validation results using
// the AnalysisError type.
Iterable<ConflictingFlagLists> validateFlagCombination(
  List<String> flags1,
  List<String> flags2,
) sync* {
  var flag1Map = _flagStringsToMap(flags1);
  var flag2Map = _flagStringsToMap(flags2);
  for (var entry in flag2Map.entries) {
    if (flag1Map[entry.key] != null && flag1Map[entry.key] != entry.value) {
      yield ConflictingFlagLists(
        _featureIndexToFeature(entry.key),
        !entry.value,
      );
    }
  }
}

/// Validates whether the strings given in [flags] constitute a valid set of
/// experimental feature enable/disable flags.
///
/// The returned iterable yields any problems that were found.
///
// TODO(paulberry): if this method ever needs to be exposed via the analyzer
// public API, consider making a version that reports validation results using
// the AnalysisError type.
Iterable<ValidationResult> validateFlags(List<String> flags) sync* {
  var previousFlagIndex = <int, int>{};
  var previousFlagValue = <int, bool>{};
  for (int flagIndex = 0; flagIndex < flags.length; flagIndex++) {
    var flag = flags[flagIndex];
    ExperimentalFeature? feature;
    bool requestedValue;
    if (flag.startsWith('no-')) {
      feature = _knownFeatures[flag.substring(3)];
      requestedValue = false;
    } else {
      feature = _knownFeatures[flag];
      requestedValue = true;
    }
    if (feature == null) {
      yield UnrecognizedFlag(flagIndex, flag);
    } else if (feature.isExpired) {
      yield requestedValue == feature.isEnabledByDefault
          ? UnnecessaryUseOfExpiredFlag(flagIndex, feature)
          : IllegalUseOfExpiredFlag(flagIndex, feature);
    } else if (previousFlagIndex.containsKey(feature.index) &&
        previousFlagValue[feature.index] != requestedValue) {
      yield ConflictingFlags(
        flagIndex,
        previousFlagIndex[feature.index]!,
        feature,
        requestedValue,
      );
    } else {
      previousFlagIndex[feature.index] = flagIndex;
      previousFlagValue[feature.index] = requestedValue;
    }
  }
}

ExperimentalFeature _featureIndexToFeature(int index) {
  for (var feature in _knownFeatures.values) {
    if (feature.index == index) return feature;
  }
  throw ArgumentError('Unrecognized feature index');
}

Map<int, bool> _flagStringsToMap(List<String> flags) {
  var result = <int, bool>{};
  for (int flagIndex = 0; flagIndex < flags.length; flagIndex++) {
    var flag = flags[flagIndex];
    ExperimentalFeature? feature;
    bool requestedValue;
    if (flag.startsWith('no-')) {
      feature = _knownFeatures[flag.substring(3)];
      requestedValue = false;
    } else {
      feature = _knownFeatures[flag];
      requestedValue = true;
    }
    if (feature != null && !feature.isExpired) {
      result[feature.index] = requestedValue;
    }
  }
  return result;
}

/// Indication of a conflict between two lists of flags.
class ConflictingFlagLists {
  /// Info about which feature the user requested conflicting values for
  final ExperimentalFeature feature;

  /// True if the first list of flags requested to enable the experimental
  /// feature.
  final bool firstValue;

  ConflictingFlagLists(this.feature, this.firstValue);
}

/// Validation result indicating that the user requested conflicting values for
/// an experimental flag (e.g. both "foo" and "no-foo").
class ConflictingFlags extends ValidationResult {
  /// Info about which feature the user requested conflicting values for
  final ExperimentalFeature feature;

  /// The index of the first of the two conflicting strings.
  ///
  /// [stringIndex] is the index of the second of the two conflicting strings.
  final int previousStringIndex;

  /// True if the string at [stringIndex] requested to enable the experimental
  /// feature.
  ///
  /// The string at [previousStringIndex] requested the opposite.
  final bool requestedValue;

  ConflictingFlags(
    super.stringIndex,
    this.previousStringIndex,
    this.feature,
    this.requestedValue,
  ) : super._();

  @override
  String get flag => feature.stringForValue(requestedValue);

  @override
  bool get isError => true;

  @override
  String get message {
    var previousFlag = feature.stringForValue(!requestedValue);
    return 'Flag "$flag" conflicts with previous flag "$previousFlag"';
  }
}

class EnabledDisabledFlags {
  final List<bool> enabled;
  final List<bool> disabled;

  EnabledDisabledFlags(this.enabled, this.disabled);
}

/// Information about a single experimental flag that the user might use to
/// request that a feature be enabled (or disabled).
@AnalyzerPublicApi(message: 'Exposed by static fields in the Feature class.')
class ExperimentalFeature implements Feature {
  /// Index of the flag in the private data structure maintained by
  /// [ExperimentStatus].
  ///
  /// This index should not be relied upon to be stable over time.  For instance
  /// it should not be used to serialize the state of experiments to long term
  /// storage if there is any expectation of compatibility between analyzer
  /// versions.
  final int index;

  /// The string to enable the feature.
  final String enableString;

  /// Whether the feature is currently enabled by default.
  final bool isEnabledByDefault;

  /// Whether the flag is currently expired (meaning the enable/disable status
  /// can no longer be altered from the value in [isEnabledByDefault]).
  final bool isExpired;

  /// Documentation for the feature, if known.  `null` for expired flags.
  final String documentation;

  /// The first language version in which this feature can be enabled using
  /// the [enableString] experimental flag.
  final Version? experimentalReleaseVersion;

  @override
  final Version? releaseVersion;

  /// The channels on which this experiment is available.
  ///
  /// Valid channels are "stable", "beta", and "main". The "dev" channel in Dart
  /// is implied by main.
  final List<String> channels;

  ExperimentalFeature({
    required this.index,
    required this.enableString,
    required this.isEnabledByDefault,
    required this.isExpired,
    required this.documentation,
    required this.experimentalReleaseVersion,
    required this.releaseVersion,
    this.channels = const [],
  }) : assert(
         isEnabledByDefault ? releaseVersion != null : releaseVersion == null,
       );

  /// The string to disable the feature.
  String get disableString => 'no-$enableString';

  @override
  String? get experimentalFlag => isExpired ? null : enableString;

  @override
  FeatureStatus get status {
    if (isExpired) {
      if (isEnabledByDefault) {
        return FeatureStatus.current;
      } else {
        return FeatureStatus.abandoned;
      }
    } else {
      if (isEnabledByDefault) {
        return FeatureStatus.provisional;
      } else {
        return FeatureStatus.future;
      }
    }
  }

  /// Retrieves the string to enable or disable the feature, depending on
  /// [value].
  String stringForValue(bool value) => value ? enableString : disableString;

  @override
  String toString() => enableString;
}

/// Validation result indicating that the user requested enabling or disabling
/// of a feature associated with an expired flag, and the requested behavior
/// conflicts with the behavior that is now hardcoded into the toolchain.
class IllegalUseOfExpiredFlag extends ValidationResult {
  /// Information about the feature associated with the error.
  final ExperimentalFeature feature;

  IllegalUseOfExpiredFlag(super.flagIndex, this.feature) : super._();

  @override
  String get flag => feature.stringForValue(!feature.isEnabledByDefault);

  @override
  bool get isError => true;

  @override
  String get message {
    var state = feature.isEnabledByDefault ? 'enabled' : 'disabled';
    return 'Flag "$flag" was supplied, but the feature is already '
        'unconditionally $state.';
  }
}

/// Validation result indicating that the user requested enabling or disabling
/// of a feature associated with an expired flag, and the requested behavior
/// is consistent with the behavior that is now hardcoded into the toolchain.
/// (This is merely a warning, not an error).
class UnnecessaryUseOfExpiredFlag extends ValidationResult {
  /// Information about the feature associated with the warning.
  final ExperimentalFeature feature;

  UnnecessaryUseOfExpiredFlag(super.flagIndex, this.feature) : super._();

  @override
  String get flag => feature.stringForValue(feature.isEnabledByDefault);

  @override
  bool get isError => false;

  @override
  String get message => 'Flag "$flag" is no longer required.';
}

/// Validation result indicating that the user requested enabling or disabling
/// an unrecognized feature.
class UnrecognizedFlag extends ValidationResult {
  @override
  final String flag;

  UnrecognizedFlag(super.flagIndex, this.flag) : super._();

  @override
  bool get isError => true;

  @override
  String get message => 'Flag "$flag" not recognized.';
}

/// Representation of a single error or warning reported by [validateFlags].
abstract class ValidationResult {
  /// Indicates which of the supplied strings is associated with the error or
  /// warning.
  final int stringIndex;

  ValidationResult._(this.stringIndex);

  /// The supplied string associated with the error or warning.
  String get flag;

  /// Indicates whether the validation result is an error or a warning.
  bool get isError;

  /// Message describing the problem.
  String get message;

  @override
  String toString() => message;
}
