// Copyright (c) 2015, 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 dart2js.serialization.types;

import '../dart_types.dart';
import '../elements/elements.dart';
import 'keys.dart';
import 'serialization.dart';

/// Visitor that serializes a [DartType] by encoding it into an [ObjectEncoder].
///
/// This class is called from the [Serializer] when a [DartType] needs
/// serialization. The [ObjectEncoder] ensures that any [Element], and other
/// [DartType] that the serialized [DartType] depends upon are also serialized.
class TypeSerializer extends DartTypeVisitor<dynamic, ObjectEncoder> {
  const TypeSerializer();

  void visitType(DartType type, ObjectEncoder encoder) {
    throw new UnsupportedError('Unsupported type: $type');
  }

  void visitVoidType(VoidType type, ObjectEncoder encoder) {}

  void visitTypeVariableType(TypeVariableType type, ObjectEncoder encoder) {
    encoder.setElement(Key.ELEMENT, type.element);
    encoder.setBool(
        Key.IS_METHOD_TYPE_VARIABLE_TYPE, type is MethodTypeVariableType);
  }

  void visitFunctionType(FunctionType type, ObjectEncoder encoder) {
    // TODO(johnniwinther): Support encoding of `type.element`.
    encoder.setType(Key.RETURN_TYPE, type.returnType);
    encoder.setTypes(Key.PARAMETER_TYPES, type.parameterTypes);
    encoder.setTypes(Key.OPTIONAL_PARAMETER_TYPES, type.optionalParameterTypes);
    encoder.setStrings(Key.NAMED_PARAMETERS, type.namedParameters);
    encoder.setTypes(Key.NAMED_PARAMETER_TYPES, type.namedParameterTypes);
  }

  void visitMalformedType(MalformedType type, ObjectEncoder encoder) {
    encoder.setElement(Key.ELEMENT, type.element);
  }

  void visitInterfaceType(InterfaceType type, ObjectEncoder encoder) {
    encoder.setElement(Key.ELEMENT, type.element);
    encoder.setTypes(Key.TYPE_ARGUMENTS, type.typeArguments);
  }

  void visitTypedefType(TypedefType type, ObjectEncoder encoder) {
    encoder.setElement(Key.ELEMENT, type.element);
    encoder.setTypes(Key.TYPE_ARGUMENTS, type.typeArguments);
  }

  void visitDynamicType(DynamicType type, ObjectEncoder encoder) {}
}

/// Utility class for deserializing [DartType]s.
///
/// This is used by the [Deserializer].
class TypeDeserializer {
  /// Deserializes a [DartType] from an [ObjectDecoder].
  ///
  /// The class is called from the [Deserializer] when a [DartType] needs
  /// deserialization. The [ObjectDecoder] ensures that any [Element], other
  /// [DartType] that the deserialized [DartType] depends upon are available.
  static DartType deserialize(ObjectDecoder decoder) {
    TypeKind typeKind = decoder.getEnum(Key.KIND, TypeKind.values);
    switch (typeKind) {
      case TypeKind.INTERFACE:
        return new InterfaceType(decoder.getElement(Key.ELEMENT),
            decoder.getTypes(Key.TYPE_ARGUMENTS, isOptional: true));
      case TypeKind.FUNCTION:
        // TODO(johnniwinther): Support decoding of `type.element`.
        return new FunctionType.synthesized(
            decoder.getType(Key.RETURN_TYPE),
            decoder.getTypes(Key.PARAMETER_TYPES, isOptional: true),
            decoder.getTypes(Key.OPTIONAL_PARAMETER_TYPES, isOptional: true),
            decoder.getStrings(Key.NAMED_PARAMETERS, isOptional: true),
            decoder.getTypes(Key.NAMED_PARAMETER_TYPES, isOptional: true));
      case TypeKind.TYPE_VARIABLE:
        TypeVariableElement element = decoder.getElement(Key.ELEMENT);
        if (decoder.getBool(Key.IS_METHOD_TYPE_VARIABLE_TYPE)) {
          return new MethodTypeVariableType(element);
        }
        return new TypeVariableType(element);
      case TypeKind.TYPEDEF:
        return new TypedefType(decoder.getElement(Key.ELEMENT),
            decoder.getTypes(Key.TYPE_ARGUMENTS, isOptional: true));
      case TypeKind.STATEMENT:
        throw new UnsupportedError("Unexpected type kind '${typeKind}.");
      case TypeKind.MALFORMED_TYPE:
        // TODO(johnniwinther): Do we need the 'userProvidedBadType' or maybe
        // just a toString of it?
        return new MalformedType(decoder.getElement(Key.ELEMENT), null);
      case TypeKind.DYNAMIC:
        return const DynamicType();
      case TypeKind.VOID:
        return const VoidType();
    }
  }
}
