// Copyright (c) 2016, 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 fasta.kernel_enum_builder;

import 'package:kernel/ast.dart' show
    Arguments,
    AsyncMarker,
    Class,
    Constructor,
    ConstructorInvocation,
    DirectPropertyGet,
    Expression,
    Field,
    FieldInitializer,
    IntLiteral,
    InterfaceType,
    ListLiteral,
    MapEntry,
    MapLiteral,
    MethodInvocation,
    Name,
    ProcedureKind,
    ReturnStatement,
    StaticGet,
    StringLiteral,
    ThisExpression,
    VariableGet;

import '../errors.dart' show
    inputError;

import '../modifier.dart' show
    constMask,
    finalMask,
    staticMask;

import "../source/source_class_builder.dart" show
    SourceClassBuilder;

import 'kernel_builder.dart' show
    Builder,
    EnumBuilder,
    FormalParameterBuilder,
    KernelConstructorBuilder,
    KernelFieldBuilder,
    KernelFormalParameterBuilder,
    KernelLibraryBuilder,
    KernelNamedTypeBuilder,
    KernelProcedureBuilder,
    KernelTypeBuilder,
    LibraryBuilder,
    MemberBuilder,
    MetadataBuilder;

class KernelEnumBuilder extends SourceClassBuilder
    implements EnumBuilder<KernelTypeBuilder, InterfaceType> {
  final List<String> constants;

  final MapLiteral toStringMap;

  final KernelTypeBuilder intType;

  final KernelTypeBuilder stringType;

  KernelEnumBuilder.internal(List<MetadataBuilder> metadata, String name,
      Map<String, Builder> members, Class cls, this.constants, this.toStringMap,
      this.intType, this.stringType, LibraryBuilder parent, int charOffset)
      : super(metadata, 0, name, null, null, null, members, parent, null,
          charOffset, cls);

  factory KernelEnumBuilder(List<MetadataBuilder> metadata, String name,
      List<String> constants, KernelLibraryBuilder parent, int charOffset) {
    constants ??= const <String>[];
    // TODO(ahe): These types shouldn't be looked up in scope, they come
    // directly from dart:core.
    KernelTypeBuilder intType = parent.addType(
        new KernelNamedTypeBuilder("int", null, charOffset, parent.fileUri));
    KernelTypeBuilder stringType = parent.addType(
        new KernelNamedTypeBuilder("String", null, charOffset, parent.fileUri));
    Class cls = new Class(name: name);
    Map<String, Builder> members = <String, Builder>{};
    KernelNamedTypeBuilder selfType = new KernelNamedTypeBuilder(
        name, null, charOffset, parent.fileUri);
    KernelTypeBuilder listType = parent.addType(
        new KernelNamedTypeBuilder(
            "List", <KernelTypeBuilder>[selfType], charOffset, parent.fileUri));

    /// From Dart Programming Language Specification 4th Edition/December 2015:
    ///     metadata class E {
    ///       final int index;
    ///       const E(this.index);
    ///       static const E id0 = const E(0);
    ///       ...
    ///       static const E idn-1 = const E(n - 1);
    ///       static const List<E> values = const <E>[id0, ..., idn-1];
    ///       String toString() => { 0: ‘E.id0’, . . ., n-1: ‘E.idn-1’}[index]
    ///     }
    members["index"] = new KernelFieldBuilder(null, intType, "index", finalMask,
        parent, charOffset);
    KernelConstructorBuilder constructorBuilder = new KernelConstructorBuilder(
        null, constMask, null, "", null, <FormalParameterBuilder>[
            new KernelFormalParameterBuilder(null, 0, intType, "index", true,
                parent, charOffset)], parent, charOffset);
    members[""] = constructorBuilder;
    int index = 0;
    List<MapEntry> toStringEntries = <MapEntry>[];
    KernelFieldBuilder valuesBuilder = new KernelFieldBuilder(null, listType,
        "values", constMask | staticMask, parent, charOffset);
    members["values"] = valuesBuilder;
    KernelProcedureBuilder toStringBuilder = new KernelProcedureBuilder(null, 0,
        stringType, "toString", null, null, AsyncMarker.Sync,
        ProcedureKind.Method, parent, charOffset);
    members["toString"] = toStringBuilder;
    String className = name;
    for (String name in constants) {
      if (members.containsKey(name)) {
        inputError(null, null, "Duplicated name: $name");
        continue;
      }
      KernelFieldBuilder fieldBuilder =
          new KernelFieldBuilder(null, selfType, name, constMask | staticMask,
              parent, charOffset); // TODO(ahe): Get charOffset from [name].
      members[name] = fieldBuilder;
      toStringEntries.add(new MapEntry(
              new IntLiteral(index), new StringLiteral("$className.$name")));
      index++;
    }
    MapLiteral toStringMap = new MapLiteral(toStringEntries, isConst: true);
    KernelEnumBuilder enumBuilder = new KernelEnumBuilder.internal(metadata,
        name, members, cls, constants, toStringMap, intType, stringType,
        parent, charOffset);
    // TODO(sigmund): dynamic should be `covariant MemberBuilder`.
    members.forEach((String name, dynamic b) {
      MemberBuilder builder = b;
      builder.parent = enumBuilder;
    });
    selfType.builder = enumBuilder;
    return enumBuilder;
  }

  KernelTypeBuilder get mixedInType => null;

  InterfaceType buildType(List<KernelTypeBuilder> arguments) {
    return cls.rawType;
  }

  Class build(KernelLibraryBuilder libraryBuilder) {
    if (constants.isEmpty) {
      libraryBuilder.addCompileTimeError(
          -1, "An enum declaration can't be empty.");
    }
    toStringMap.keyType = intType.build();
    toStringMap.valueType = stringType.build();
    KernelFieldBuilder indexFieldBuilder = members["index"];
    Field indexField = indexFieldBuilder.build(libraryBuilder.library);
    KernelProcedureBuilder toStringBuilder = members["toString"];
    toStringBuilder.body = new ReturnStatement(
        new MethodInvocation(toStringMap, new Name("[]"),
            new Arguments(<Expression>[
                    new DirectPropertyGet(new ThisExpression(), indexField)])));
    List<Expression> values = <Expression>[];
    for (String name in constants) {
      KernelFieldBuilder builder = members[name];
      values.add(new StaticGet(builder.build(libraryBuilder.library)));
    }
    KernelFieldBuilder valuesBuilder = members["values"];
    valuesBuilder.build(libraryBuilder.library);
    valuesBuilder.initializer =
        new ListLiteral(values, typeArgument: cls.rawType, isConst: true);
    KernelConstructorBuilder constructorBuilder = members[""];
    Constructor constructor = constructorBuilder.build(libraryBuilder.library);
    constructor.initializers.insert(0, new FieldInitializer(indexField,
            new VariableGet(constructor.function.positionalParameters.single))
        ..parent = constructor);
    int index = 0;
    for (String constant in constants) {
      KernelFieldBuilder field = members[constant];
      field.build(libraryBuilder.library);
      Arguments arguments =
          new Arguments(<Expression>[new IntLiteral(index++)]);
      field.initializer =
          new ConstructorInvocation(constructor, arguments, isConst: true);
    }
    return super.build(libraryBuilder);
  }

  Builder findConstructorOrFactory(String name) => null;
}
