// Copyright (c) 2020, 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:convert';

import 'package:meta/meta.dart';

/// Parse the given [jsonText] into the [AllowedExperiments].
///
/// Throw [FormatException] is any format issues are found.
AllowedExperiments parseAllowedExperiments(String jsonText) {
  return new _AllowedExperimentsParser(jsonText).parse();
}

/// The set of experiments enabled for SDK and packages.
class AllowedExperiments {
  /// The set of experiments that are enabled for all SDK libraries other than
  /// for those which are specified in [sdkLibraryExperiments].
  final List<String> sdkDefaultExperiments;

  /// Mapping from individual SDK libraries, e.g. 'core', to the set of
  /// experiments that are enabled for this library.
  final Map<String, List<String>> sdkLibraryExperiments;

  /// Mapping from package names, e.g. 'path', to the set of experiments that
  /// are enabled for all files of this package.
  final Map<String, List<String>> packageExperiments;

  AllowedExperiments({
    @required this.sdkDefaultExperiments,
    @required this.sdkLibraryExperiments,
    @required this.packageExperiments,
  });

  /// Return the set of enabled experiments for the package with the [name],
  /// e.g. "path", possibly `null`.
  List<String> forPackage(String name) {
    return packageExperiments[name];
  }

  /// Return the set of enabled experiments for the library with the [name],
  /// e.g. "core".
  List<String> forSdkLibrary(String name) {
    return sdkLibraryExperiments[name] ?? sdkDefaultExperiments;
  }
}

class _AllowedExperimentsParser {
  final String _jsonText;
  final List<String> _parsePath = [];
  final Map<String, List<String>> _experimentSets = {};

  _AllowedExperimentsParser(this._jsonText);

  AllowedExperiments parse() {
    Object rootObject = json.decode(_jsonText);
    Map<String, Object> map = _mustBeMap(rootObject);

    _ensureVersion(map);

    _withParsePath('experimentSets', () {
      Map<String, Object> experimentSetMap =
          _requiredMap(map, 'experimentSets');
      for (MapEntry<String, Object> entry in experimentSetMap.entries) {
        String setName = entry.key;
        _withParsePath(setName, () {
          _experimentSets[setName] = _mustBeListOfStrings(entry.value);
        });
      }
    });

    List<String> sdkDefaultExperimentSet = <String>[];
    Map<String, List<String>> sdkLibraryExperiments = <String, List<String>>{};
    _withParsePath('sdk', () {
      Map<String, Object> sdkMap = _requiredMap(map, 'sdk');

      _withParsePath('default', () {
        sdkDefaultExperimentSet = _experimentList(
          _requiredMap(sdkMap, 'default'),
        );
      });

      _withParsePath('libraries', () {
        Map<String, Object> sdkLibraryExperimentsMap =
            _optionalMap(sdkMap, 'libraries');
        if (sdkLibraryExperimentsMap != null) {
          for (MapEntry<String, Object> entry
              in sdkLibraryExperimentsMap.entries) {
            String libraryName = entry.key;
            _withParsePath(libraryName, () {
              Map<String, Object> libraryMap = _mustBeMap(entry.value);
              List<String> experimentList = _experimentList(libraryMap);
              sdkLibraryExperiments[libraryName] = experimentList;
            });
          }
        }
      });
    });

    Map<String, List<String>> packageExperiments = <String, List<String>>{};
    _withParsePath('packages', () {
      Map<String, Object> packageExperimentsMap = _optionalMap(map, 'packages');
      if (packageExperimentsMap != null) {
        for (MapEntry<String, Object> entry in packageExperimentsMap.entries) {
          String packageName = entry.key;
          _withParsePath(packageName, () {
            Map<String, Object> libraryMap = _mustBeMap(entry.value);
            List<String> experimentList = _experimentList(libraryMap);
            packageExperiments[packageName] = experimentList;
          });
        }
      }
    });

    return new AllowedExperiments(
      sdkDefaultExperiments: sdkDefaultExperimentSet,
      sdkLibraryExperiments: sdkLibraryExperiments,
      packageExperiments: packageExperiments,
    );
  }

  void _ensureVersion(Map<String, Object> map) {
    Object versionObject = map['version'];
    if (versionObject is! int || versionObject != 1) {
      throw new FormatException(
        "Expected field 'version' with value '1'; "
        "actually ${versionObject.runtimeType}: $versionObject",
        _jsonText,
      );
    }
  }

  List<String> _experimentList(Map<String, Object> map) {
    String experimentSetName = _requiredString(map, 'experimentSet');
    List<String> result = _experimentSets[experimentSetName];
    if (result != null) {
      return result;
    }

    throw new FormatException(
      "No experiment set '$experimentSetName in $_experimentSets",
      _jsonText,
    );
  }

  List<String> _mustBeListOfStrings(Object object) {
    if (object is List<Object> && object.every((e) => e is String)) {
      return List.castFrom(object);
    }

    String path = _parsePath.join(' / ');
    throw new FormatException(
      "Expected list of strings at $path, "
      "actually ${object.runtimeType}: $object",
      _jsonText,
    );
  }

  Map<String, Object> _mustBeMap(Object object) {
    if (object is Map<String, Object>) {
      return object;
    }

    String path = _parsePath.isNotEmpty ? _parsePath.join(' / ') : 'root';
    throw new FormatException(
      "Expected map at $path, "
      "actually ${object.runtimeType}: $object",
      _jsonText,
    );
  }

  Map<String, Object> _optionalMap(Map<String, Object> map, String name) {
    Object result = map[name];
    if (result == null || result is Map<String, Object>) {
      return result;
    }

    String path = _parsePath.join(' / ');
    throw new FormatException(
      "Expected map at $path, actually ${result.runtimeType}: $result",
      _jsonText,
    );
  }

  Map<String, Object> _requiredMap(Map<String, Object> map, String name) {
    Object result = map[name];
    if (result is Map<String, Object>) {
      return result;
    }

    String path = _parsePath.join(' / ');
    throw new FormatException(
      "Expected map at $path, actually ${result.runtimeType}: $result",
      _jsonText,
    );
  }

  String _requiredString(Map<String, Object> map, String name) {
    Object result = map[name];
    if (result is String) {
      return result;
    }

    String path = _parsePath.join(' / ');
    throw new FormatException(
      "Expected string at $path, actually ${result.runtimeType}: $result",
      _jsonText,
    );
  }

  void _withParsePath(String name, void Function() f) {
    _parsePath.add(name);
    try {
      f();
    } finally {
      _parsePath.removeLast();
    }
  }
}
