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

part of 'serialization.dart';

/// Enum used for identifying [ir.TreeNode] subclasses in serialization.
enum _TreeNodeKind {
  cls,
  member,
  node,
  functionNode,
  typeParameter,
  functionDeclarationVariable,
  constant,
}

/// Enum used for identifying [ir.FunctionNode] context in serialization.
enum _FunctionNodeKind {
  procedure,
  constructor,
  functionExpression,
  functionDeclaration,
}

/// Enum used for identifying [ir.TypeParameter] context in serialization.
enum _TypeParameterKind { cls, functionNode }

class DartTypeNodeWriter
    extends ir.DartTypeVisitor1<void, List<ir.StructuralParameter>> {
  final DataSinkWriter _sink;

  DartTypeNodeWriter(this._sink);

  void visitTypes(
    List<ir.DartType> types,
    List<ir.StructuralParameter> functionTypeVariables,
  ) {
    _sink.writeInt(types.length);
    for (ir.DartType type in types) {
      _sink._writeDartTypeNode(type, functionTypeVariables);
    }
  }

  @override
  void visitAuxiliaryType(
    ir.AuxiliaryType node,
    List<ir.StructuralParameter> functionTypeVariables,
  ) {
    throw UnsupportedError(
      "Unsupported auxiliary type $node (${node.runtimeType}).",
    );
  }

  @override
  void visitInvalidType(
    ir.InvalidType node,
    List<ir.StructuralParameter> functionTypeVariables,
  ) {
    _sink.writeEnum(DartTypeNodeKind.invalidType);
  }

  @override
  void visitDynamicType(
    ir.DynamicType node,
    List<ir.StructuralParameter> functionTypeVariables,
  ) {
    _sink.writeEnum(DartTypeNodeKind.dynamicType);
  }

  @override
  void visitVoidType(
    ir.VoidType node,
    List<ir.StructuralParameter> functionTypeVariables,
  ) {
    _sink.writeEnum(DartTypeNodeKind.voidType);
  }

  @override
  void visitNeverType(
    ir.NeverType node,
    List<ir.StructuralParameter> functionTypeVariables,
  ) {
    _sink.writeEnum(DartTypeNodeKind.neverType);
    _sink.writeEnum(node.nullability);
  }

  @override
  void visitNullType(
    ir.NullType node,
    List<ir.StructuralParameter> functionTypeVariables,
  ) {
    _sink.writeEnum(DartTypeNodeKind.nullType);
  }

  @override
  void visitInterfaceType(
    ir.InterfaceType node,
    List<ir.StructuralParameter> functionTypeVariables,
  ) {
    _sink.writeEnum(DartTypeNodeKind.interfaceType);
    _sink.writeClassNode(node.classNode);
    _sink.writeEnum(node.nullability);
    visitTypes(node.typeArguments, functionTypeVariables);
  }

  @override
  void visitRecordType(
    ir.RecordType node,
    List<ir.StructuralParameter> functionTypeVariables,
  ) {
    _sink.writeEnum(DartTypeNodeKind.recordType);
    _sink.writeEnum(node.declaredNullability);
    visitTypes(node.positional, functionTypeVariables);
    _visitNamedTypes(node.named, functionTypeVariables);
  }

  @override
  void visitFutureOrType(
    ir.FutureOrType node,
    List<ir.StructuralParameter> functionTypeVariables,
  ) {
    _sink.writeEnum(DartTypeNodeKind.futureOrType);
    _sink.writeEnum(node.declaredNullability);
    _sink._writeDartTypeNode(node.typeArgument, functionTypeVariables);
  }

  @override
  void visitFunctionType(
    ir.FunctionType node,
    List<ir.StructuralParameter> functionTypeVariables,
  ) {
    _sink.writeEnum(DartTypeNodeKind.functionType);
    _sink.begin(functionTypeNodeTag);
    functionTypeVariables = List<ir.StructuralParameter>.from(
      functionTypeVariables,
    )..addAll(node.typeParameters);
    _sink.writeInt(node.typeParameters.length);
    for (ir.StructuralParameter parameter in node.typeParameters) {
      _sink.writeString(parameter.name!);
      _sink._writeDartTypeNode(parameter.bound, functionTypeVariables);
      _sink._writeDartTypeNode(parameter.defaultType, functionTypeVariables);
    }
    _sink._writeDartTypeNode(node.returnType, functionTypeVariables);
    _sink.writeEnum(node.nullability);
    _sink.writeInt(node.requiredParameterCount);
    visitTypes(node.positionalParameters, functionTypeVariables);
    _visitNamedTypes(node.namedParameters, functionTypeVariables);
    _sink.end(functionTypeNodeTag);
  }

  void _visitNamedTypes(
    List<ir.NamedType> named,
    List<ir.StructuralParameter> functionTypeVariables,
  ) {
    _sink.writeInt(named.length);
    for (ir.NamedType parameter in named) {
      _sink.writeString(parameter.name);
      _sink.writeBool(parameter.isRequired);
      _sink._writeDartTypeNode(parameter.type, functionTypeVariables);
    }
  }

  @override
  void visitTypeParameterType(
    ir.TypeParameterType node,
    List<ir.StructuralParameter> functionTypeVariables,
  ) {
    _sink.writeEnum(DartTypeNodeKind.typeParameterType);
    _sink.writeTypeParameterNode(node.parameter);
    _sink.writeEnum(node.declaredNullability);
    _sink._writeDartTypeNode(null, functionTypeVariables, allowNull: true);
  }

  @override
  void visitStructuralParameterType(
    ir.StructuralParameterType node,
    List<ir.StructuralParameter> functionTypeVariables,
  ) {
    int index = functionTypeVariables.indexOf(node.parameter);
    assert(index != -1);
    _sink.writeEnum(DartTypeNodeKind.functionTypeVariable);
    _sink.writeInt(index);
    _sink.writeEnum(node.declaredNullability);
  }

  @override
  void visitIntersectionType(
    ir.IntersectionType node,
    List<ir.StructuralParameter> functionTypeVariables,
  ) {
    _sink.writeEnum(DartTypeNodeKind.typeParameterType);
    _sink.writeTypeParameterNode(node.left.parameter);
    _sink.writeEnum(node.declaredNullability);
    _sink._writeDartTypeNode(
      node.right,
      functionTypeVariables,
      allowNull: false,
    );
  }

  @override
  void visitTypedefType(
    ir.TypedefType node,
    List<ir.StructuralParameter> functionTypeVariables,
  ) {
    _sink.writeEnum(DartTypeNodeKind.typedef);
    _sink.writeTypedefNode(node.typedefNode);
    _sink.writeEnum(node.nullability);
    visitTypes(node.typeArguments, functionTypeVariables);
  }

  @override
  void visitExtensionType(
    ir.ExtensionType node,
    List<ir.StructuralParameter> functionTypeVariables,
  ) {
    _sink.writeEnum(DartTypeNodeKind.extensionType);
    _sink.writeExtensionTypeDeclarationNode(node.extensionTypeDeclaration);
    _sink.writeEnum(node.nullability);
    visitTypes(node.typeArguments, functionTypeVariables);
  }
}
