// Copyright (c) 2014, 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:collection';

import 'package:_fe_analyzer_shared/src/messages/codes.dart' show Message;
import 'package:analyzer/dart/ast/ast.dart'
    show AstNode, ConstructorDeclaration;
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/diagnostic/diagnostic.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:source_span/source_span.dart';

/// An object that listen for [AnalysisError]s being produced by the analysis
/// engine.
abstract class AnalysisErrorListener {
  /// An error listener that ignores errors that are reported to it.
  static final AnalysisErrorListener NULL_LISTENER = _NullErrorListener();

  /// This method is invoked when an [error] has been found by the analysis
  /// engine.
  void onError(AnalysisError error);
}

/// An [AnalysisErrorListener] that keeps track of whether any error has been
/// reported to it.
class BooleanErrorListener implements AnalysisErrorListener {
  /// A flag indicating whether an error has been reported to this listener.
  bool _errorReported = false;

  /// Return `true` if an error has been reported to this listener.
  bool get errorReported => _errorReported;

  @override
  void onError(AnalysisError error) {
    _errorReported = true;
  }
}

/// An object used to create analysis errors and report then to an error
/// listener.
class ErrorReporter {
  /// The error listener to which errors will be reported.
  final AnalysisErrorListener _errorListener;

  /// Is `true` if the library being analyzed is non-nullable by default.
  final bool isNonNullableByDefault;

  /// The source to be used when reporting errors.
  final Source _source;

  /// Initialize a newly created error reporter that will report errors to the
  /// given [_errorListener]. Errors will be reported against the
  /// [_defaultSource] unless another source is provided later.
  ErrorReporter(this._errorListener, this._source,
      {this.isNonNullableByDefault = false});

  Source get source => _source;

  /// Report the given [error].
  void reportError(AnalysisError error) {
    _errorListener.onError(error);
  }

  /// Report an error with the given [errorCode] and [arguments]. The [element]
  /// is used to compute the location of the error.
  void reportErrorForElement(ErrorCode errorCode, Element element,
      [List<Object>? arguments]) {
    reportErrorForOffset(errorCode, element.nonSynthetic.nameOffset,
        element.nameLength, arguments);
  }

  /// Report a diagnostic with the given [code] and [arguments]. The
  /// location of the diagnostic will be the name of the [constructor].
  void reportErrorForName(ErrorCode code, ConstructorDeclaration constructor,
      {List<Object>? arguments}) {
    // TODO(brianwilkerson) Consider extending this method to take any
    //  declaration and compute the correct range for the name of that
    //  declaration. This might make it easier to be consistent.
    if (constructor.name != null) {
      var offset = constructor.returnType.offset;
      reportErrorForOffset(
          code, offset, constructor.name!.end - offset, arguments);
    } else {
      reportErrorForNode(code, constructor.returnType, arguments);
    }
  }

  /// Report an error with the given [errorCode] and [arguments].
  /// The [node] is used to compute the location of the error.
  void reportErrorForNode(ErrorCode errorCode, AstNode node,
      [List<Object>? arguments, List<DiagnosticMessage>? messages]) {
    reportErrorForOffset(
        errorCode, node.offset, node.length, arguments, messages);
  }

  /// Report an error with the given [errorCode] and [arguments]. The location
  /// of the error is specified by the given [offset] and [length].
  void reportErrorForOffset(ErrorCode errorCode, int offset, int length,
      [List<Object>? arguments, List<DiagnosticMessage>? messages]) {
    _convertElements(arguments);
    messages ??= [];
    messages.addAll(_convertTypeNames(arguments));
    _errorListener.onError(
        AnalysisError(_source, offset, length, errorCode, arguments, messages));
  }

  /// Report an error with the given [errorCode] and [arguments]. The location
  /// of the error is specified by the given [span].
  void reportErrorForSpan(ErrorCode errorCode, SourceSpan span,
      [List<Object>? arguments]) {
    reportErrorForOffset(errorCode, span.start.offset, span.length, arguments);
  }

  /// Report an error with the given [errorCode] and [arguments]. The [token] is
  /// used to compute the location of the error.
  void reportErrorForToken(ErrorCode errorCode, Token token,
      [List<Object>? arguments, List<DiagnosticMessage>? messages]) {
    reportErrorForOffset(
        errorCode, token.offset, token.length, arguments, messages);
  }

  /// Report an error with the given [errorCode] and [message]. The location of
  /// the error is specified by the given [offset] and [length].
  ///
  /// Deprecated - the [Message] type assumes named arguments, and no analyzer
  /// errors use named arguments anymore.  Please use other methods of
  /// [ErrorReporter].
  @deprecated
  void reportErrorMessage(
      ErrorCode errorCode, int offset, int length, Message message) {
    _errorListener.onError(AnalysisError.withNamedArguments(
        _source, offset, length, errorCode, message.arguments));
  }

  /// Report an error with the given [errorCode] and [arguments]. The [node] is
  /// used to compute the location of the error. The arguments are expected to
  /// contain two or more types. Convert the types into strings by using the
  /// display names of the types, unless there are two or more types with the
  /// same names, in which case the extended display names of the types will be
  /// used in order to clarify the message.
  ///
  /// If there are not two or more types in the argument list, the method
  /// [reportErrorForNode] should be used instead.
  @Deprecated('Use reportErrorForNode(), it will convert types as well')
  void reportTypeErrorForNode(
      ErrorCode errorCode, AstNode node, List<Object> arguments) {
    reportErrorForOffset(errorCode, node.offset, node.length, arguments);
  }

  /// Convert all [Element]s in the [arguments] into their display strings.
  void _convertElements(List<Object>? arguments) {
    if (arguments == null) {
      return;
    }

    for (var i = 0; i < arguments.length; i++) {
      var argument = arguments[i];
      if (argument is Element) {
        arguments[i] = argument.getDisplayString(
          withNullability: isNonNullableByDefault,
        );
      } else if (!(argument is String ||
          argument is DartType ||
          argument is int ||
          argument is Uri)) {
        throw ArgumentError(
            'Tried to format an error using ${argument.runtimeType}');
      }
    }
  }

  /// Given an array of [arguments] that is expected to contain two or more
  /// types, convert the types into strings by using the display names of the
  /// types, unless there are two or more types with the same names, in which
  /// case the extended display names of the types will be used in order to
  /// clarify the message.
  List<DiagnosticMessage> _convertTypeNames(List<Object?>? arguments) {
    var messages = <DiagnosticMessage>[];
    if (arguments == null) {
      return messages;
    }

    Map<String, List<_TypeToConvert>> typeGroups = {};
    for (int i = 0; i < arguments.length; i++) {
      var argument = arguments[i];
      if (argument is DartType) {
        String displayName = argument.getDisplayString(
          withNullability: isNonNullableByDefault,
        );
        List<_TypeToConvert> types =
            typeGroups.putIfAbsent(displayName, () => <_TypeToConvert>[]);
        types.add(_TypeToConvert(i, argument, displayName));
      }
    }
    for (List<_TypeToConvert> typeGroup in typeGroups.values) {
      if (typeGroup.length == 1) {
        _TypeToConvert typeToConvert = typeGroup[0];
        arguments[typeToConvert.index] = typeToConvert.displayName;
      } else {
        Map<String, Set<Element>> nameToElementMap = {};
        for (_TypeToConvert typeToConvert in typeGroup) {
          for (Element element in typeToConvert.allElements()) {
            Set<Element> elements =
                nameToElementMap.putIfAbsent(element.name!, () => <Element>{});
            elements.add(element);
          }
        }
        for (_TypeToConvert typeToConvert in typeGroup) {
          // TODO(brianwilkerson) When clients do a better job of displaying
          // context messages, remove the extra text added to the buffer.
          StringBuffer? buffer;
          for (Element element in typeToConvert.allElements()) {
            String name = element.name!;
            if (nameToElementMap[name]!.length > 1) {
              if (buffer == null) {
                buffer = StringBuffer();
                buffer.write('where ');
              } else {
                buffer.write(', ');
              }
              buffer.write('$name is defined in ${element.source!.fullName}');
            }
            messages.add(DiagnosticMessageImpl(
                filePath: element.source!.fullName,
                length: element.nameLength,
                message: '$name is defined in ${element.source!.fullName}',
                offset: element.nameOffset,
                url: null));
          }

          if (buffer != null) {
            arguments[typeToConvert.index] =
                '${typeToConvert.displayName} ($buffer)';
          } else {
            arguments[typeToConvert.index] = typeToConvert.displayName;
          }
        }
      }
    }
    return messages;
  }
}

/// An error listener that will record the errors that are reported to it in a
/// way that is appropriate for caching those errors within an analysis context.
class RecordingErrorListener implements AnalysisErrorListener {
  Set<AnalysisError>? _errors;

  /// Return the errors collected by the listener.
  List<AnalysisError> get errors {
    if (_errors == null) {
      return const <AnalysisError>[];
    }
    return _errors!.toList();
  }

  /// Return the errors collected by the listener for the given [source].
  List<AnalysisError> getErrorsForSource(Source source) {
    if (_errors == null) {
      return const <AnalysisError>[];
    }
    return _errors!.where((error) => error.source == source).toList();
  }

  @override
  void onError(AnalysisError error) {
    (_errors ??= HashSet<AnalysisError>()).add(error);
  }
}

/// An [AnalysisErrorListener] that ignores error.
class _NullErrorListener implements AnalysisErrorListener {
  @override
  void onError(AnalysisError event) {
    // Ignore errors
  }
}

/// Used by `ErrorReporter._convertTypeNames` to keep track of a type that is
/// being converted.
class _TypeToConvert {
  final int index;
  final DartType type;
  final String displayName;

  List<Element>? _allElements;

  _TypeToConvert(this.index, this.type, this.displayName);

  List<Element> allElements() {
    if (_allElements == null) {
      Set<Element> elements = <Element>{};

      void addElementsFrom(DartType type) {
        if (type is FunctionType) {
          addElementsFrom(type.returnType);
          for (ParameterElement parameter in type.parameters) {
            addElementsFrom(parameter.type);
          }
        } else if (type is InterfaceType) {
          if (elements.add(type.element)) {
            for (DartType typeArgument in type.typeArguments) {
              addElementsFrom(typeArgument);
            }
          }
        }
      }

      addElementsFrom(type);
      _allElements = elements.where((element) {
        var name = element.name;
        return name != null && name.isNotEmpty;
      }).toList();
    }
    return _allElements!;
  }
}
