/**
 * This file contains code to generate experimental flags
 * based on the information in tools/experimental_features.yaml.
 */
import 'dart:io';

import 'package:analysis_tool/tools.dart';
import 'package:front_end/src/fasta/scanner/characters.dart' show $MINUS, $_;
import 'package:front_end/src/testing/package_root.dart' as pkgRoot;
import 'package:path/path.dart';
import 'package:yaml/yaml.dart' show YamlMap, loadYaml;

main() async {
  await GeneratedContent.generateAll(
      normalize(join(pkgRoot.packageRoot, 'analyzer')), allTargets);
}

List<GeneratedContent> get allTargets {
  Map<dynamic, dynamic> experimentsYaml = loadYaml(new File(join(
          normalize(join(pkgRoot.packageRoot, '../tools')),
          'experimental_features.yaml'))
      .readAsStringSync());

  return <GeneratedContent>[
    new GeneratedFile('lib/src/dart/analysis/experiments.g.dart',
        (String pkgPath) async {
      var generator = new _ExperimentsGenerator(experimentsYaml);
      generator.generateFormatCode();
      return generator.out.toString();
    }),
  ];
}

String keyToIdentifier(String key) {
  var identifier = StringBuffer();
  for (int index = 0; index < key.length; ++index) {
    var code = key.codeUnitAt(index);
    if (code == $MINUS) {
      code = $_;
    }
    identifier.writeCharCode(code);
  }
  return identifier.toString();
}

class _ExperimentsGenerator {
  final Map experimentsYaml;

  List<String> keysSorted;

  final out = new StringBuffer('''
//
// THIS FILE IS GENERATED. DO NOT EDIT.
//
// Instead modify 'tools/experimental_features.yaml' and run
// 'dart pkg/analyzer/tool/experiments/generate.dart' to update.

part of 'experiments.dart';
''');

  _ExperimentsGenerator(this.experimentsYaml);

  void generateFormatCode() {
    keysSorted = experimentsYaml.keys.cast<String>().toList()..sort();
    generateSection_KnownFeatures();
    generateSection_BuildExperimentalFlagsArray();
    generateSection_EnableString();
    generateSection_ExperimentalFeature();
    generateSection_IsEnabledByDefault();
    generateSection_IsExpired();
    generateSection_CurrentState();
  }

  void generateSection_BuildExperimentalFlagsArray() {
    out.write('''

List<bool> _buildExperimentalFlagsArray() => <bool>[
''');
    for (var key in keysSorted) {
      var id = keyToIdentifier(key);
      var entry = experimentsYaml[key] as YamlMap;
      bool shipped = entry['enabledIn'] != null;
      bool expired = entry['expired'];
      if (shipped || expired == true) {
        out.writeln('true, // $key');
      } else {
        out.writeln('IsEnabledByDefault.$id,');
      }
    }
    // TODO(danrubel): Remove bogus entries
    out.write('''
      false, // bogus-disabled
      true, // bogus-enabled
    ];
''');
  }

  void generateSection_CurrentState() {
    // TODO(danrubel): Remove bogus entries
    out.write('''

mixin _CurrentState {
  /// Current state for the flag "bogus-disabled"
  bool get bogus_disabled => isEnabled(ExperimentalFeatures.bogus_disabled);

  /// Current state for the flag "bogus-enabled"
  bool get bogus_enabled => isEnabled(ExperimentalFeatures.bogus_enabled);
''');
    for (var key in keysSorted) {
      var id = keyToIdentifier(key);
      out.write('''
  /// Current state for the flag "$key"
  bool get $id => isEnabled(ExperimentalFeatures.$id);
    ''');
    }
    out.write('''

  bool isEnabled(covariant ExperimentalFeature feature);
}''');
  }

  void generateSection_EnableString() {
    out.write('''

/// Constant strings for enabling each of the currently known experimental
/// flags.
class EnableString {
''');
    for (var key in keysSorted) {
      out.write('''
      /// String to enable the experiment "$key"
      static const String ${keyToIdentifier(key)} = '$key';
    ''');
    }
    // TODO(danrubel): Remove bogus entries
    out.write('''

      /// String to enable the experiment "bogus-disabled"
      static const String bogus_disabled = 'bogus-disabled';

      /// String to enable the experiment "bogus-enabled"
      static const String bogus_enabled = 'bogus-enabled';
    }''');
  }

  void generateSection_ExperimentalFeature() {
    out.write('''

class ExperimentalFeatures {
''');
    int index = 0;
    for (var key in keysSorted) {
      var id = keyToIdentifier(key);
      var help = (experimentsYaml[key] as YamlMap)['help'] ?? '';
      var enabledIn = (experimentsYaml[key] as YamlMap)['enabledIn'];
      out.write('''

      static const $id = const ExperimentalFeature(
      $index,
      EnableString.$id,
      IsEnabledByDefault.$id,
      IsExpired.$id,
      '$help'
    ''');
      if (enabledIn != null) {
        if (enabledIn is double) {
          enabledIn = '$enabledIn.0';
        }
        out.write(",firstSupportedVersion: '$enabledIn'");
      }
      out.writeln(');');
      ++index;
    }
    // TODO(danrubel): Remove bogus entries
    out.write('''

      static const bogus_disabled = const ExperimentalFeature(
        $index,
        EnableString.bogus_disabled,
        IsEnabledByDefault.bogus_disabled,
        IsExpired.bogus_disabled,
        null);

      static const bogus_enabled = const ExperimentalFeature(
        ${index + 1},
        EnableString.bogus_enabled,
        IsEnabledByDefault.bogus_enabled,
        IsExpired.bogus_enabled,
        null,
        firstSupportedVersion: '1.0.0');
    }''');
  }

  void generateSection_IsEnabledByDefault() {
    out.write('''

/// Constant bools indicating whether each experimental flag is currently
/// enabled by default.
class IsEnabledByDefault {
''');
    for (var key in keysSorted) {
      var entry = experimentsYaml[key] as YamlMap;
      bool shipped = entry['enabledIn'] != null;
      out.write('''
      /// Default state of the experiment "$key"
      static const bool ${keyToIdentifier(key)} = $shipped;
    ''');
    }
    // TODO(danrubel): Remove bogus entries
    out.write('''

      /// Default state of the experiment "bogus-disabled"
      static const bool bogus_disabled = false;

      /// Default state of the experiment "bogus-enabled"
      static const bool bogus_enabled = true;
    }''');
  }

  void generateSection_IsExpired() {
    out.write('''

/// Constant bools indicating whether each experimental flag is currently
/// expired (meaning its enable/disable status can no longer be altered from the
/// value in [IsEnabledByDefault]).
class IsExpired {
''');
    for (var key in keysSorted) {
      var entry = experimentsYaml[key] as YamlMap;
      bool shipped = entry['enabledIn'] != null;
      bool expired = entry['expired'];
      out.write('''
      /// Expiration status of the experiment "$key"
      static const bool ${keyToIdentifier(key)} = ${expired == true};
    ''');
      if (shipped && expired == false) {
        throw 'Cannot mark shipped feature as "expired: false"';
      }
    }
    // TODO(danrubel): Remove bogus entries
    out.write('''

      /// Expiration status of the experiment "bogus-disabled"
      static const bool bogus_disabled = true;

      /// Expiration status of the experiment "bogus-enabled"
      static const bool bogus_enabled = true;
    }''');
  }

  void generateSection_KnownFeatures() {
    out.write('''

/// A map containing information about all known experimental flags.
const _knownFeatures = <String, ExperimentalFeature>{
''');
    for (var key in keysSorted) {
      var id = keyToIdentifier(key);
      out.write('''
  EnableString.$id: ExperimentalFeatures.$id,
    ''');
    }
    // TODO(danrubel): Remove bogus entries
    out.write('''

  EnableString.bogus_disabled: ExperimentalFeatures.bogus_disabled,
  EnableString.bogus_enabled: ExperimentalFeatures.bogus_enabled,
};
''');
  }
}
