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

import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary2/reference.dart';

class LinkingBundleContext {
  /// The `dynamic` class is declared in `dart:core`, but is not a class.
  /// Also, it is static, so we cannot set `reference` for it.
  /// So, we have to push it in a separate way.
  final Reference dynamicReference;

  /// References used in all libraries being linked.
  /// Element references in nodes are indexes in this list.
  final List<Reference> references = [null];

  /// Data about [references].
  final LinkedNodeReferencesBuilder referencesBuilder =
      LinkedNodeReferencesBuilder(
    parent: [0],
    name: [''],
  );

  final Map<TypeParameterElement, int> _typeParameters = Map.identity();
  int _nextSyntheticTypeParameterId = 0x10000;

  LinkingBundleContext(this.dynamicReference);

  /// We need indexes for references during linking, but once we are done,
  /// we must clear indexes to make references ready for linking a next bundle.
  void clearIndexes() {
    for (var reference in references) {
      if (reference != null) {
        reference.index = null;
      }
    }
  }

  int idOfTypeParameter(TypeParameterElement element) {
    return _typeParameters[element];
  }

  int indexOfElement(Element element) {
    if (element == null) return 0;
    assert(element is! Member);

    if (identical(element, DynamicElementImpl.instance)) {
      return indexOfReference(dynamicReference);
    }

    var reference = (element as ElementImpl).reference;
    return indexOfReference(reference);
  }

  int indexOfReference(Reference reference) {
    if (reference == null) return 0;
    if (reference.parent == null) return 0;
    if (reference.index != null) return reference.index;

    var parentIndex = indexOfReference(reference.parent);
    referencesBuilder.parent.add(parentIndex);
    referencesBuilder.name.add(reference.name);

    reference.index = references.length;
    references.add(reference);
    return reference.index;
  }

  LinkedNodeTypeBuilder writeType(DartType type) {
    if (type == null) return null;

    if (type.isBottom) {
      return LinkedNodeTypeBuilder(
        kind: LinkedNodeTypeKind.bottom,
        nullabilitySuffix: _nullabilitySuffix(type),
      );
    } else if (type.isDynamic) {
      return LinkedNodeTypeBuilder(
        kind: LinkedNodeTypeKind.dynamic_,
      );
    } else if (type is FunctionType) {
      return _writeFunctionType(type);
    } else if (type is InterfaceType) {
      return LinkedNodeTypeBuilder(
        kind: LinkedNodeTypeKind.interface,
        interfaceClass: indexOfElement(type.element),
        interfaceTypeArguments: type.typeArguments.map(writeType).toList(),
        nullabilitySuffix: _nullabilitySuffix(type),
      );
    } else if (type is TypeParameterType) {
      TypeParameterElementImpl element = type.element;
      var id = _typeParameters[element];
      if (id != null) {
        return LinkedNodeTypeBuilder(
          kind: LinkedNodeTypeKind.typeParameter,
          nullabilitySuffix: _nullabilitySuffix(type),
          typeParameterId: id,
        );
      } else {
        var index = indexOfElement(element);
        return LinkedNodeTypeBuilder(
          kind: LinkedNodeTypeKind.typeParameter,
          nullabilitySuffix: _nullabilitySuffix(type),
          typeParameterElement: index,
        );
      }
    } else if (type is VoidType) {
      return LinkedNodeTypeBuilder(
        kind: LinkedNodeTypeKind.void_,
      );
    } else {
      throw UnimplementedError('(${type.runtimeType}) $type');
    }
  }

  LinkedNodeFormalParameterKind _formalParameterKind(ParameterElement p) {
    if (p.isRequiredPositional) {
      return LinkedNodeFormalParameterKind.requiredPositional;
    } else if (p.isRequiredNamed) {
      return LinkedNodeFormalParameterKind.requiredNamed;
    } else if (p.isOptionalPositional) {
      return LinkedNodeFormalParameterKind.optionalPositional;
    } else if (p.isOptionalNamed) {
      return LinkedNodeFormalParameterKind.optionalNamed;
    } else {
      throw StateError('Unexpected parameter kind: $p');
    }
  }

  FunctionType _toSyntheticFunctionType(FunctionType type) {
    var typeParameters = type.typeFormals;

    if (typeParameters.isEmpty) return type;

    var onlySyntheticTypeParameters = typeParameters.every((e) {
      return e is TypeParameterElementImpl && e.linkedNode == null;
    });
    if (onlySyntheticTypeParameters) return type;

    var parameters = getFreshTypeParameters(typeParameters);
    return parameters.applyToFunctionType(type);
  }

  LinkedNodeTypeBuilder _writeFunctionType(FunctionType type) {
    type = _toSyntheticFunctionType(type);

    var typeParameterBuilders = <LinkedNodeTypeTypeParameterBuilder>[];

    var typeParameters = type.typeFormals;
    for (var i = 0; i < typeParameters.length; ++i) {
      var typeParameter = typeParameters[i];
      _typeParameters[typeParameter] = _nextSyntheticTypeParameterId++;
      typeParameterBuilders.add(
        LinkedNodeTypeTypeParameterBuilder(name: typeParameter.name),
      );
    }

    for (var i = 0; i < typeParameters.length; ++i) {
      var typeParameter = typeParameters[i];
      typeParameterBuilders[i].bound = writeType(typeParameter.bound);
    }

    Element typedefElement;
    List<DartType> typedefTypeArguments = const <DartType>[];
    if (type.element is GenericTypeAliasElement) {
      typedefElement = type.element;
      typedefTypeArguments = type.typeArguments;
    }
    // TODO(scheglov) Cleanup to always use GenericTypeAliasElement.
    if (type.element is GenericFunctionTypeElement &&
        type.element.enclosingElement is GenericTypeAliasElement) {
      typedefElement = type.element.enclosingElement;
      typedefTypeArguments = type.typeArguments;
    }

    var result = LinkedNodeTypeBuilder(
      kind: LinkedNodeTypeKind.function,
      functionFormalParameters: type.parameters
          .map((p) => LinkedNodeTypeFormalParameterBuilder(
                kind: _formalParameterKind(p),
                name: p.name,
                type: writeType(p.type),
              ))
          .toList(),
      functionReturnType: writeType(type.returnType),
      functionTypeParameters: typeParameterBuilders,
      functionTypedef: indexOfElement(typedefElement),
      functionTypedefTypeArguments:
          typedefTypeArguments.map(writeType).toList(),
      nullabilitySuffix: _nullabilitySuffix(type),
    );

    for (var typeParameter in typeParameters) {
      _typeParameters.remove(typeParameter);
      --_nextSyntheticTypeParameterId;
    }

    return result;
  }

  static EntityRefNullabilitySuffix _nullabilitySuffix(DartType type) {
    var nullabilitySuffix = (type as TypeImpl).nullabilitySuffix;
    switch (nullabilitySuffix) {
      case NullabilitySuffix.question:
        return EntityRefNullabilitySuffix.question;
      case NullabilitySuffix.star:
        return EntityRefNullabilitySuffix.starOrIrrelevant;
      case NullabilitySuffix.none:
        return EntityRefNullabilitySuffix.none;
      default:
        throw StateError('$nullabilitySuffix');
    }
  }
}
