// 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 value != null ? new BoolConstant(value) : new NullConstant();
      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 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;
  }
}
