// 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>>
    with
        ir.DartTypeVisitor1ExperimentExclusionMixin<
          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);
  }
}
