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

import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/src/dart/analysis/experiments_impl.dart';
import 'package:meta/meta.dart';
import 'package:pub_semver/src/version.dart';

export 'package:analyzer/src/dart/analysis/experiments_impl.dart'
    show
        ConflictingFlags,
        ExperimentalFeature,
        IllegalUseOfExpiredFlag,
        UnnecessaryUseOfExpiredFlag,
        UnrecognizedFlag,
        validateFlags,
        ValidationResult;

part 'experiments.g.dart';

/// Gets access to the private list of boolean flags in an [ExperimentStatus]
/// object. For testing use only.
@visibleForTesting
List<bool> getExperimentalFlags_forTesting(ExperimentStatus status) =>
    status._flags;

/// Gets access to the private SDK language version in an [ExperimentStatus]
/// object. For testing use only.
@visibleForTesting
Version getSdkLanguageVersion_forTesting(ExperimentStatus status) =>
    status._sdkLanguageVersion;

/// A representation of the set of experiments that are active and whether they
/// are enabled.
class ExperimentStatus with _CurrentState implements FeatureSet {
  /// The current language version.
  static final Version currentVersion = Version.parse(_currentVersion);

  /// A map containing information about all known experimental flags.
  static final Map<String, ExperimentalFeature> knownFeatures = _knownFeatures;

  final Version _sdkLanguageVersion;
  final List<bool> _explicitEnabledFlags;
  final List<bool> _explicitDisabledFlags;
  final List<bool> _flags;

  factory ExperimentStatus() {
    return ExperimentStatus.latestLanguageVersion();
  }

  factory ExperimentStatus.fromStorage(Uint8List encoded) {
    var byteIndex = 0;

    int getByte() {
      return encoded[byteIndex++];
    }

    List<bool> getBoolList(int length) {
      var result = List<bool>.filled(length, false);
      var byteValue = 0;
      var bitIndex = 0;
      for (var i = 0; i < length; i++) {
        if (bitIndex == 0) {
          byteValue = getByte();
        }
        if ((byteValue & (1 << bitIndex)) != 0) {
          result[i] = true;
        }
        bitIndex = (bitIndex + 1) % 8;
      }
      return result;
    }

    var sdkLanguageVersion = Version(getByte(), getByte(), 0);
    var featureCount = getByte();
    return ExperimentStatus._(
      sdkLanguageVersion,
      getBoolList(featureCount),
      getBoolList(featureCount),
      getBoolList(featureCount),
    );
  }

  /// Decodes the strings given in [flags] into a representation of the set of
  /// 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.
  factory ExperimentStatus.fromStrings2({
    required Version sdkLanguageVersion,
    required List<String> flags,
    // TODO(scheglov) use restrictEnableFlagsToVersion
  }) {
    var explicitFlags = decodeExplicitFlags(flags);

    var decodedFlags = restrictEnableFlagsToVersion(
      sdkLanguageVersion: sdkLanguageVersion,
      explicitEnabledFlags: explicitFlags.enabled,
      explicitDisabledFlags: explicitFlags.disabled,
      version: sdkLanguageVersion,
    );

    return ExperimentStatus._(
      sdkLanguageVersion,
      explicitFlags.enabled,
      explicitFlags.disabled,
      decodedFlags,
    );
  }

  factory ExperimentStatus.latestLanguageVersion() {
    return ExperimentStatus.fromStrings2(
      sdkLanguageVersion: currentVersion,
      flags: [],
    );
  }

  ExperimentStatus._(
    this._sdkLanguageVersion,
    this._explicitEnabledFlags,
    this._explicitDisabledFlags,
    this._flags,
  );

  @override
  int get hashCode => Object.hashAll(_flags);

  @override
  bool operator ==(Object other) {
    if (other is ExperimentStatus) {
      if (_sdkLanguageVersion != other._sdkLanguageVersion) {
        return false;
      }
      if (!_equalListOfBool(
          _explicitEnabledFlags, other._explicitEnabledFlags)) {
        return false;
      }
      if (!_equalListOfBool(
          _explicitDisabledFlags, other._explicitDisabledFlags)) {
        return false;
      }
      if (!_equalListOfBool(_flags, other._flags)) {
        return false;
      }
      return true;
    }
    return false;
  }

  /// Queries whether the given [feature] is enabled or disabled.
  @override
  bool isEnabled(covariant ExperimentalFeature feature) =>
      _flags[feature.index];

  @override
  FeatureSet restrictToVersion(Version version) {
    return ExperimentStatus._(
      _sdkLanguageVersion,
      _explicitEnabledFlags,
      _explicitDisabledFlags,
      restrictEnableFlagsToVersion(
        sdkLanguageVersion: _sdkLanguageVersion,
        explicitEnabledFlags: _explicitEnabledFlags,
        explicitDisabledFlags: _explicitDisabledFlags,
        version: version,
      ),
    );
  }

  /// Encode into the format suitable for [ExperimentStatus.fromStorage].
  Uint8List toStorage() {
    var result = Uint8List(16);
    var resultIndex = 0;

    void addByte(int value) {
      assert(value >= 0 && value < 256);
      result[resultIndex++] = value;
    }

    addByte(_sdkLanguageVersion.major);
    addByte(_sdkLanguageVersion.minor);

    void addBoolList(List<bool> values) {
      var byteValue = 0;
      var bitIndex = 0;
      for (var value in values) {
        if (value) {
          byteValue |= 1 << bitIndex;
        }
        bitIndex++;
        if (bitIndex == 8) {
          addByte(byteValue);
          byteValue = 0;
          bitIndex = 0;
        }
      }
      if (bitIndex != 0) {
        addByte(byteValue);
      }
    }

    addByte(_flags.length);
    addBoolList(_explicitEnabledFlags);
    addBoolList(_explicitDisabledFlags);
    addBoolList(_flags);

    return result.sublist(0, resultIndex);
  }

  @override
  String toString() => experimentStatusToString(_flags);

  static bool _equalListOfBool(List<bool> first, List<bool> second) {
    if (first.length != second.length) return false;
    for (var i = 0; i < first.length; i++) {
      if (first[i] != second[i]) return false;
    }
    return true;
  }
}
