// 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.

import 'dart:convert' show json;

import 'package:kernel/ast.dart';

import '../denylisted_classes.dart' show denylistedCoreClasses;

import '../fasta_codes.dart'
    show Message, templateTypeOrigin, templateTypeOriginWithFileUri;

import '../problems.dart' show unsupported;

/// A pretty-printer for Kernel types and constants with the ability to label
/// raw types with numeric markers in Dart comments (e.g. `/*1*/`) to
/// distinguish different types with the same name. This is used in diagnostic
/// messages to indicate the origins of types occurring in the message.
class TypeLabeler implements DartTypeVisitor<void>, ConstantVisitor<void> {
  final List<LabeledNode> names = <LabeledNode>[];
  final Map<String, List<LabeledNode>> nameMap = <String, List<LabeledNode>>{};
  final bool printNullability;

  List<Object> result = const [];

  TypeLabeler(this.printNullability);

  /// Pretty-print a type.
  /// When all types and constants appearing in the same message have been
  /// pretty-printed, the returned list can be converted to its string
  /// representation (with labels on duplicated names) by the `join()` method.
  List<Object> labelType(DartType type) {
    // TODO(askesc): Remove null check when we are completely null clean here.
    // ignore: unnecessary_null_comparison
    if (type == null) return ["null-type"];
    result = [];
    type.accept(this);
    return result;
  }

  /// Pretty-print a constant.
  /// When all types and constants appearing in the same message have been
  /// pretty-printed, the returned list can be converted to its string
  /// representation (with labels on duplicated names) by the `join()` method.
  List<Object> labelConstant(Constant constant) {
    // TODO(askesc): Remove null check when we are completely null clean here.
    // ignore: unnecessary_null_comparison
    if (constant == null) return ["null-constant"];
    result = [];
    constant.accept(this);
    return result;
  }

  /// Get a textual description of the origins of the raw types appearing in
  /// types and constants that have been pretty-printed using this labeler.
  String get originMessages {
    StringBuffer messages = new StringBuffer();
    for (LabeledNode name in names) {
      messages.write(name.originMessage);
    }
    return messages.toString();
  }

  // We don't have access to coreTypes here, so we have our own Object check.
  static bool isObject(DartType type) {
    if (type is InterfaceType && type.classNode.name == 'Object') {
      Uri importUri = type.classNode.enclosingLibrary.importUri;
      return importUri.scheme == 'dart' && importUri.path == 'core';
    }
    return false;
  }

  LabeledNode nameForEntity(
      TreeNode node, String nodeName, Uri importUri, Uri fileUri) {
    List<LabeledNode>? labelsForName = nameMap[nodeName];
    if (labelsForName == null) {
      // First encountered entity with this name
      LabeledNode name =
          new LabeledNode(node, nodeName, importUri, fileUri, this);
      names.add(name);
      nameMap[nodeName] = [name];
      return name;
    } else {
      for (LabeledNode entityForName in labelsForName) {
        if (entityForName.node == node) {
          // Previously encountered entity
          return entityForName;
        }
      }
      // New entity with name that was previously encountered
      LabeledNode name =
          new LabeledNode(node, nodeName, importUri, fileUri, this);
      names.add(name);
      labelsForName.add(name);
      return name;
    }
  }

  void addNullability(Nullability nullability) {
    if (printNullability) {
      if (nullability == Nullability.nullable) {
        result.add("?");
      }
    }
  }

  void defaultDartType(DartType type) {}

  void visitTypedefType(TypedefType node) {
    Typedef typedefNode = node.typedefNode;
    result.add(nameForEntity(
        typedefNode,
        typedefNode.name,
        typedefNode.enclosingLibrary.importUri,
        typedefNode.enclosingLibrary.fileUri));
    if (node.typeArguments.isNotEmpty) {
      result.add("<");
      bool first = true;
      for (DartType typeArg in node.typeArguments) {
        if (!first) result.add(", ");
        typeArg.accept(this);
        first = false;
      }
      result.add(">");
    }
    addNullability(node.nullability);
  }

  void visitInvalidType(InvalidType node) {
    // TODO(askesc): Throw internal error if InvalidType appears in diagnostics.
    result.add("invalid-type");
  }

  void visitNeverType(NeverType node) {
    result.add("Never");
    addNullability(node.declaredNullability);
  }

  void visitNullType(NullType node) {
    result.add("Null");
  }

  void visitDynamicType(DynamicType node) {
    result.add("dynamic");
  }

  void visitVoidType(VoidType node) {
    result.add("void");
  }

  void visitTypeParameterType(TypeParameterType node) {
    TreeNode? parent = node.parameter;
    while (parent is! Library && parent != null) {
      parent = parent.parent;
    }
    // Note that this can be null if, for instance, the erroneous code is not
    // actually in the tree - then we don't know where it comes from!
    Library? enclosingLibrary = parent as Library?;

    result.add(nameForEntity(
        node.parameter,
        node.parameter.name ?? '',
        enclosingLibrary == null ? unknownUri : enclosingLibrary.importUri,
        enclosingLibrary == null ? unknownUri : enclosingLibrary.fileUri));
    addNullability(node.declaredNullability);
  }

  void visitFunctionType(FunctionType node) {
    node.returnType.accept(this);
    result.add(" Function");
    if (node.typeParameters.isNotEmpty) {
      result.add("<");
      bool first = true;
      for (TypeParameter param in node.typeParameters) {
        if (!first) result.add(", ");
        result.add(param.name ?? '');
        if (isObject(param.bound) && param.defaultType is DynamicType) {
          // Bound was not specified, and therefore should not be printed.
        } else {
          result.add(" extends ");
          param.bound.accept(this);
        }
        first = false;
      }
      result.add(">");
    }
    result.add("(");
    bool first = true;
    for (int i = 0; i < node.requiredParameterCount; i++) {
      if (!first) result.add(", ");
      node.positionalParameters[i].accept(this);
      first = false;
    }
    if (node.positionalParameters.length > node.requiredParameterCount) {
      if (node.requiredParameterCount > 0) result.add(", ");
      result.add("[");
      first = true;
      for (int i = node.requiredParameterCount;
          i < node.positionalParameters.length;
          i++) {
        if (!first) result.add(", ");
        node.positionalParameters[i].accept(this);
        first = false;
      }
      result.add("]");
    }
    if (node.namedParameters.isNotEmpty) {
      if (node.positionalParameters.isNotEmpty) result.add(", ");
      result.add("{");
      first = true;
      for (int i = 0; i < node.namedParameters.length; i++) {
        if (!first) result.add(", ");
        node.namedParameters[i].type.accept(this);
        result.add(" ${node.namedParameters[i].name}");
        first = false;
      }
      result.add("}");
    }
    result.add(")");
    addNullability(node.nullability);
  }

  void visitInterfaceType(InterfaceType node) {
    Class classNode = node.classNode;
    // TODO(johnniwinther): Ensure enclosing libraries on classes earlier
    // in the compiler to ensure types in error messages have context.
    Library? enclosingLibrary = classNode.parent as Library?;
    result.add(nameForEntity(
        classNode,
        classNode.name,
        enclosingLibrary?.importUri ?? unknownUri,
        enclosingLibrary?.fileUri ?? unknownUri));
    if (node.typeArguments.isNotEmpty) {
      result.add("<");
      bool first = true;
      for (DartType typeArg in node.typeArguments) {
        if (!first) result.add(", ");
        typeArg.accept(this);
        first = false;
      }
      result.add(">");
    }
    addNullability(node.nullability);
  }

  void visitFutureOrType(FutureOrType node) {
    result.add("FutureOr<");
    node.typeArgument.accept(this);
    result.add(">");
    addNullability(node.declaredNullability);
  }

  void visitExtensionType(ExtensionType node) {
    // TODO(johnniwinther): Ensure enclosing libraries on extensions earlier
    // in the compiler to ensure types in error messages have context.
    Library? enclosingLibrary = node.extension.parent as Library?;
    result.add(nameForEntity(
        node.extension,
        node.extension.name,
        enclosingLibrary?.importUri ?? unknownUri,
        enclosingLibrary?.fileUri ?? unknownUri));
    if (node.typeArguments.isNotEmpty) {
      result.add("<");
      bool first = true;
      for (DartType typeArg in node.typeArguments) {
        if (!first) result.add(", ");
        typeArg.accept(this);
        first = false;
      }
      result.add(">");
    }
    addNullability(node.declaredNullability);
  }

  void defaultConstant(Constant node) {}

  void visitNullConstant(NullConstant node) {
    result.add('${node.value}');
  }

  void visitBoolConstant(BoolConstant node) {
    result.add('${node.value}');
  }

  void visitIntConstant(IntConstant node) {
    result.add('${node.value}');
  }

  void visitDoubleConstant(DoubleConstant node) {
    result.add('${node.value}');
  }

  void visitSymbolConstant(SymbolConstant node) {
    String text = node.libraryReference != null
        ? '#${node.libraryReference!.asLibrary.importUri}::${node.name}'
        : '#${node.name}';
    result.add(text);
  }

  void visitStringConstant(StringConstant node) {
    result.add(json.encode(node.value));
  }

  void visitInstanceConstant(InstanceConstant node) {
    new InterfaceType(node.classNode, Nullability.legacy, node.typeArguments)
        .accept(this);
    result.add(" {");
    bool first = true;
    for (Field field in node.classNode.fields) {
      if (field.isStatic) continue;
      if (!first) result.add(", ");
      result.add("${field.name}: ");
      node.fieldValues[field.getterReference]!.accept(this);
      first = false;
    }
    result.add("}");
  }

  void visitListConstant(ListConstant node) {
    result.add("<");
    node.typeArgument.accept(this);
    result.add(">[");
    bool first = true;
    for (Constant constant in node.entries) {
      if (!first) result.add(", ");
      constant.accept(this);
      first = false;
    }
    result.add("]");
  }

  void visitSetConstant(SetConstant node) {
    result.add("<");
    node.typeArgument.accept(this);
    result.add(">{");
    bool first = true;
    for (Constant constant in node.entries) {
      if (!first) result.add(", ");
      constant.accept(this);
      first = false;
    }
    result.add("}");
  }

  void visitMapConstant(MapConstant node) {
    result.add("<");
    node.keyType.accept(this);
    result.add(", ");
    node.valueType.accept(this);
    result.add(">{");
    bool first = true;
    for (ConstantMapEntry entry in node.entries) {
      if (!first) result.add(", ");
      entry.key.accept(this);
      result.add(": ");
      entry.value.accept(this);
      first = false;
    }
    result.add("}");
  }

  void visitStaticTearOffConstant(StaticTearOffConstant node) {
    Procedure procedure = node.target;
    Class? classNode = procedure.enclosingClass;
    if (classNode != null) {
      result.add(nameForEntity(
          classNode,
          classNode.name,
          classNode.enclosingLibrary.importUri,
          classNode.enclosingLibrary.fileUri));
      result.add(".");
    }
    result.add(procedure.name.text);
  }

  void visitConstructorTearOffConstant(ConstructorTearOffConstant node) {
    Member constructor = node.target;
    Class classNode = constructor.enclosingClass!;
    result.add(nameForEntity(
        classNode,
        classNode.name,
        classNode.enclosingLibrary.importUri,
        classNode.enclosingLibrary.fileUri));
    result.add(".");
    result.add(constructor.name.text);
  }

  void visitRedirectingFactoryTearOffConstant(
      RedirectingFactoryTearOffConstant node) {
    Member constructor = node.target;
    Class classNode = constructor.enclosingClass!;
    result.add(nameForEntity(
        classNode,
        classNode.name,
        classNode.enclosingLibrary.importUri,
        classNode.enclosingLibrary.fileUri));
    result.add(".");
    result.add(constructor.name.text);
  }

  void visitInstantiationConstant(InstantiationConstant node) {
    node.tearOffConstant.accept(this);
    if (node.types.isNotEmpty) {
      result.add("<");
      bool first = true;
      for (DartType typeArg in node.types) {
        if (!first) result.add(", ");
        typeArg.accept(this);
        first = false;
      }
      result.add(">");
    }
  }

  void visitTypedefTearOffConstant(TypedefTearOffConstant node) {
    node.tearOffConstant.accept(this);
    if (node.parameters.isNotEmpty) {
      result.add("<");
      bool first = true;
      for (TypeParameter param in node.parameters) {
        if (!first) result.add(", ");
        result.add(param.name ?? '');
        if (isObject(param.bound) && param.defaultType is DynamicType) {
          // Bound was not specified, and therefore should not be printed.
        } else {
          result.add(" extends ");
          param.bound.accept(this);
        }
        first = false;
      }
      result.add(">");
    }
    if (node.types.isNotEmpty) {
      result.add("<");
      bool first = true;
      for (DartType typeArg in node.types) {
        if (!first) result.add(", ");
        typeArg.accept(this);
        first = false;
      }
      result.add(">");
    }
  }

  void visitTypeLiteralConstant(TypeLiteralConstant node) {
    node.type.accept(this);
  }

  void visitUnevaluatedConstant(UnevaluatedConstant node) {
    unsupported('printing unevaluated constants', -1, null);
  }
}

final Uri unknownUri = Uri.parse("unknown");

class LabeledNode {
  final TreeNode node;
  final TypeLabeler typeLabeler;
  final String name;
  final Uri importUri;
  final Uri fileUri;

  LabeledNode(
      this.node, this.name, this.importUri, this.fileUri, this.typeLabeler);

  String toString() {
    List<LabeledNode> entityForName = typeLabeler.nameMap[name]!;
    if (entityForName.length == 1) {
      return name;
    }
    return "$name/*${entityForName.indexOf(this) + 1}*/";
  }

  String get originMessage {
    if (importUri.scheme == 'dart' && importUri.path == 'core') {
      if (node is Class && denylistedCoreClasses.contains(name)) {
        // Denylisted core class. Only print if ambiguous.
        List<LabeledNode> entityForName = typeLabeler.nameMap[name]!;
        if (entityForName.length == 1) {
          return "";
        }
      }
    }
    if (importUri == unknownUri || node is! Class) {
      // We don't know where it comes from and/or it's not a class.
      // Only print if ambiguous.
      List<LabeledNode> entityForName = typeLabeler.nameMap[name]!;
      if (entityForName.length == 1) {
        return "";
      }
    }
    Message message = (importUri == fileUri || importUri.scheme == 'dart')
        ? templateTypeOrigin.withArguments(toString(), importUri)
        : templateTypeOriginWithFileUri.withArguments(
            toString(), importUri, fileUri);
    return "\n - " + message.message;
  }
}
