// Copyright (c) 2017, 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.

library vm.constants_native_effects;

import '../ast.dart';
import '../transformations/constants.dart';
import '../core_types.dart';

class VmConstantsBackend implements ConstantsBackend {
  final Map<String, String> defines;

  final Class immutableMapClass;
  final Class internalSymbolClass;
  final Field symbolNameField;

  VmConstantsBackend._(this.defines, this.immutableMapClass,
      this.internalSymbolClass, this.symbolNameField);

  /// If [defines] is not `null` it will be used for handling
  /// `const {bool,...}.fromEnvironment()` otherwise the current VM's values
  /// will be used.
  factory VmConstantsBackend(Map<String, String> defines, CoreTypes coreTypes) {
    final Library coreLibrary = coreTypes.coreLibrary;
    final Class immutableMapClass = coreLibrary.classes
        .firstWhere((Class klass) => klass.name == '_ImmutableMap');
    assert(immutableMapClass != null);

    final Class internalSymbolClass = coreTypes.internalSymbolClass;
    assert(internalSymbolClass != null);

    final Field symbolNameField =
        internalSymbolClass.fields.where((Field field) {
      return field.isInstanceMember && field.name.name == '_name';
    }).single;

    return new VmConstantsBackend._(
        defines, immutableMapClass, internalSymbolClass, symbolNameField);
  }

  Constant buildConstantForNative(
      String nativeName,
      List<DartType> typeArguments,
      List<Constant> positionalArguments,
      Map<String, Constant> namedArguments) {
    switch (nativeName) {
      case 'Bool_fromEnvironment':
        final String name = (positionalArguments[0] as StringConstant).value;
        final Constant constant = namedArguments['defaultValue'];
        final bool defaultValue = constant is BoolConstant
            ? constant.value
            : (constant is NullConstant ? null : false);
        bool value;
        if (defines != null) {
          value = defines[name] == 'true'
              ? true
              : (defines[name] == 'false' ? false : defaultValue);
        } else {
          value = new bool.fromEnvironment(name, defaultValue: defaultValue);
        }
        return new BoolConstant(value);
      case 'Integer_fromEnvironment':
        final String name = (positionalArguments[0] as StringConstant).value;
        final Constant constant = namedArguments['defaultValue'];
        final int defaultValue =
            constant is IntConstant ? constant.value : null;
        int value;
        if (defines != null) {
          final String defineValue = defines[name];
          value = defineValue != null
              ? (int.tryParse(defineValue) ?? defaultValue)
              : defaultValue;
        } else {
          value = new int.fromEnvironment(name, defaultValue: defaultValue);
        }
        return value != null ? new IntConstant(value) : new NullConstant();
      case 'String_fromEnvironment':
        final String name = (positionalArguments[0] as StringConstant).value;
        final Constant constant = namedArguments['defaultValue'];
        final String defaultValue =
            constant is StringConstant ? constant.value : null;
        String value;
        if (defines != null) {
          value = defines[name] ?? defaultValue;
        } else {
          value = new String.fromEnvironment(name, defaultValue: defaultValue);
        }
        return value == null ? new NullConstant() : new StringConstant(value);
    }
    throw 'No native effect registered for constant evaluation: $nativeName';
  }

  Constant buildSymbolConstant(StringConstant value) {
    return new InstanceConstant(
        internalSymbolClass.reference,
        const <DartType>[],
        <Reference, Constant>{symbolNameField.reference: value});
  }

  Constant lowerMapConstant(MapConstant constant) {
    // The _ImmutableMap class is implemented via one field pointing to a list
    // of key/value pairs -- see runtime/lib/immutable_map.dart!
    final List<Constant> kvListPairs =
        new List<Constant>(2 * constant.entries.length);
    for (int i = 0; i < constant.entries.length; i++) {
      final ConstantMapEntry entry = constant.entries[i];
      kvListPairs[2 * i] = entry.key;
      kvListPairs[2 * i + 1] = entry.value;
    }
    // Strong mode is a bit fishy here, since we merge the key and the value
    // type by putting both into the same list!
    final kvListConstant = new ListConstant(const DynamicType(), kvListPairs);
    assert(immutableMapClass.fields.length == 1);
    final Field kvPairListField = immutableMapClass.fields[0];
    return new InstanceConstant(immutableMapClass.reference, <DartType>[
      constant.keyType,
      constant.valueType,
    ], <Reference, Constant>{
      kvPairListField.reference: kvListConstant,
    });
  }

  Constant lowerListConstant(ListConstant constant) {
    // Currently we let vipunen deal with the [ListConstant]s.
    return constant;
  }
}
