// Copyright (c) 2017, 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' as analyzer;
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/diagnostic/diagnostic.dart' as analyzer;
import 'package:analyzer/error/error.dart' as analyzer;
import 'package:analyzer/exception/exception.dart' as analyzer;
import 'package:analyzer/source/error_processor.dart' as analyzer;
import 'package:analyzer/src/generated/engine.dart' as analyzer;
import 'package:analyzer/src/generated/source.dart' as analyzer;
import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;

/// An object used to convert between objects defined by the 'analyzer' package
/// and those defined by the plugin protocol.
///
/// Clients may not extend, implement or mix-in this class.
class AnalyzerConverter {
  /// Convert the analysis [error] from the 'analyzer' package to an analysis
  /// error defined by the plugin API. If a [lineInfo] is provided then the
  /// error's location will have a start line and start column. If a [severity]
  /// is provided, then it will override the severity defined by the error.
  plugin.AnalysisError convertAnalysisError(analyzer.AnalysisError error,
      {analyzer.LineInfo? lineInfo, analyzer.ErrorSeverity? severity}) {
    var errorCode = error.errorCode;
    severity ??= errorCode.errorSeverity;
    var offset = error.offset;
    var startLine = -1;
    var startColumn = -1;
    var endLine = -1;
    var endColumn = -1;
    if (lineInfo != null) {
      var startLocation = lineInfo.getLocation(offset);
      startLine = startLocation.lineNumber;
      startColumn = startLocation.columnNumber;
      var endLocation = lineInfo.getLocation(offset + error.length);
      endLine = endLocation.lineNumber;
      endColumn = endLocation.columnNumber;
    }
    List<plugin.DiagnosticMessage>? contextMessages;
    if (error.contextMessages.isNotEmpty) {
      contextMessages = error.contextMessages
          .map((message) =>
              convertDiagnosticMessage(message, lineInfo: lineInfo))
          .toList();
    }
    return plugin.AnalysisError(
        convertErrorSeverity(severity),
        convertErrorType(errorCode.type),
        plugin.Location(
            error.source.fullName, offset, error.length, startLine, startColumn,
            endLine: endLine, endColumn: endColumn),
        error.message,
        errorCode.name.toLowerCase(),
        contextMessages: contextMessages,
        correction: error.correction,
        hasFix: true);
  }

  /// Convert the list of analysis [errors] from the 'analyzer' package to a
  /// list of analysis errors defined by the plugin API. If a [lineInfo] is
  /// provided then the resulting errors locations will have a start line and
  /// start column. If an analysis [options] is provided then the severities of
  /// the errors will be altered based on those options.
  List<plugin.AnalysisError> convertAnalysisErrors(
      List<analyzer.AnalysisError> errors,
      {analyzer.LineInfo? lineInfo,
      analyzer.AnalysisOptions? options}) {
    var serverErrors = <plugin.AnalysisError>[];
    for (var error in errors) {
      var processor = analyzer.ErrorProcessor.getProcessor(options, error);
      if (processor != null) {
        var severity = processor.severity;
        // Errors with null severity are filtered out.
        if (severity != null) {
          // Specified severities override.
          serverErrors.add(convertAnalysisError(error,
              lineInfo: lineInfo, severity: severity));
        }
      } else {
        serverErrors.add(convertAnalysisError(error, lineInfo: lineInfo));
      }
    }
    return serverErrors;
  }

  /// Convert the diagnostic [message] from the 'analyzer' package to an
  /// analysis error defined by the plugin API. If a [lineInfo] is provided then
  /// the error's location will have a start line and start column.
  plugin.DiagnosticMessage convertDiagnosticMessage(
      analyzer.DiagnosticMessage message,
      {analyzer.LineInfo? lineInfo}) {
    var file = message.filePath;
    var offset = message.offset;
    var length = message.length;
    var startLine = -1;
    var startColumn = -1;
    var endLine = -1;
    var endColumn = -1;
    if (lineInfo != null) {
      var lineLocation = lineInfo.getLocation(offset);
      startLine = lineLocation.lineNumber;
      startColumn = lineLocation.columnNumber;
      var endLocation = lineInfo.getLocation(offset + length);
      endLine = endLocation.lineNumber;
      endColumn = endLocation.columnNumber;
    }
    return plugin.DiagnosticMessage(
        message.messageText(includeUrl: true),
        plugin.Location(file, offset, length, startLine, startColumn,
            endLine: endLine, endColumn: endColumn));
  }

  /// Convert the given [element] from the 'analyzer' package to an element
  /// defined by the plugin API.
  plugin.Element convertElement(analyzer.Element element) {
    var kind = _convertElementToElementKind(element);
    return plugin.Element(
      kind,
      element.displayName,
      plugin.Element.makeFlags(
        isPrivate: element.isPrivate,
        isDeprecated: element.hasDeprecated,
        isAbstract: _isAbstract(element),
        isConst: _isConst(element),
        isFinal: _isFinal(element),
        isStatic: _isStatic(element),
      ),
      location: locationFromElement(element),
      typeParameters: _getTypeParametersString(element),
      aliasedType: _getAliasedTypeString(element),
      parameters: _getParametersString(element),
      returnType: _getReturnTypeString(element),
    );
  }

  /// Convert the element [kind] from the 'analyzer' package to an element kind
  /// defined by the plugin API.
  ///
  /// This method does not take into account that an instance of [ClassElement]
  /// can be an enum and an instance of [FieldElement] can be an enum constant.
  /// Use [_convertElementToElementKind] where possible.
  plugin.ElementKind convertElementKind(analyzer.ElementKind kind) {
    if (kind == analyzer.ElementKind.CLASS) {
      return plugin.ElementKind.CLASS;
    } else if (kind == analyzer.ElementKind.COMPILATION_UNIT) {
      return plugin.ElementKind.COMPILATION_UNIT;
    } else if (kind == analyzer.ElementKind.CONSTRUCTOR) {
      return plugin.ElementKind.CONSTRUCTOR;
    } else if (kind == analyzer.ElementKind.FIELD) {
      return plugin.ElementKind.FIELD;
    } else if (kind == analyzer.ElementKind.FUNCTION) {
      return plugin.ElementKind.FUNCTION;
    } else if (kind == analyzer.ElementKind.FUNCTION_TYPE_ALIAS) {
      return plugin.ElementKind.FUNCTION_TYPE_ALIAS;
    } else if (kind == analyzer.ElementKind.GENERIC_FUNCTION_TYPE) {
      return plugin.ElementKind.FUNCTION_TYPE_ALIAS;
    } else if (kind == analyzer.ElementKind.GETTER) {
      return plugin.ElementKind.GETTER;
    } else if (kind == analyzer.ElementKind.LABEL) {
      return plugin.ElementKind.LABEL;
    } else if (kind == analyzer.ElementKind.LIBRARY) {
      return plugin.ElementKind.LIBRARY;
    } else if (kind == analyzer.ElementKind.LOCAL_VARIABLE) {
      return plugin.ElementKind.LOCAL_VARIABLE;
    } else if (kind == analyzer.ElementKind.METHOD) {
      return plugin.ElementKind.METHOD;
    } else if (kind == analyzer.ElementKind.PARAMETER) {
      return plugin.ElementKind.PARAMETER;
    } else if (kind == analyzer.ElementKind.PREFIX) {
      return plugin.ElementKind.PREFIX;
    } else if (kind == analyzer.ElementKind.SETTER) {
      return plugin.ElementKind.SETTER;
    } else if (kind == analyzer.ElementKind.TOP_LEVEL_VARIABLE) {
      return plugin.ElementKind.TOP_LEVEL_VARIABLE;
    } else if (kind == analyzer.ElementKind.TYPE_ALIAS) {
      return plugin.ElementKind.TYPE_ALIAS;
    } else if (kind == analyzer.ElementKind.TYPE_PARAMETER) {
      return plugin.ElementKind.TYPE_PARAMETER;
    }
    return plugin.ElementKind.UNKNOWN;
  }

  /// Convert the error [severity] from the 'analyzer' package to an analysis
  /// error severity defined by the plugin API.
  plugin.AnalysisErrorSeverity convertErrorSeverity(
          analyzer.ErrorSeverity severity) =>
      plugin.AnalysisErrorSeverity(severity.name);

  ///Convert the error [type] from the 'analyzer' package to an analysis error
  /// type defined by the plugin API.
  plugin.AnalysisErrorType convertErrorType(analyzer.ErrorType type) =>
      plugin.AnalysisErrorType(type.name);

  /// Create a location based on an the given [element].
  plugin.Location? locationFromElement(analyzer.Element? element,
      {int? offset, int? length}) {
    if (element == null || element.source == null) {
      return null;
    }
    offset ??= element.nameOffset;
    length ??= element.nameLength;
    if (element is analyzer.CompilationUnitElement ||
        (element is analyzer.LibraryElement && offset < 0)) {
      offset = 0;
      length = 0;
    }
    var unitElement = _getUnitElement(element);
    var range = analyzer.SourceRange(offset, length);
    return _locationForArgs(unitElement, range);
  }

  /// Convert the element kind of the [element] from the 'analyzer' package to
  /// an element kind defined by the plugin API.
  plugin.ElementKind _convertElementToElementKind(analyzer.Element element) {
    if (element is analyzer.ClassElement && element.isEnum) {
      return plugin.ElementKind.ENUM;
    } else if (element is analyzer.FieldElement &&
        element.isEnumConstant &&
        // MyEnum.values and MyEnum.one.index return isEnumConstant = true
        // so these additional checks are necessary.
        // TODO(danrubel) MyEnum.values is constant, but is a list
        // so should it return isEnumConstant = true?
        // MyEnum.one.index is final but *not* constant
        // so should it return isEnumConstant = true?
        // Or should we return ElementKind.ENUM_CONSTANT here
        // in either or both of these cases?
        element.type.element == element.enclosingElement) {
      return plugin.ElementKind.ENUM_CONSTANT;
    }
    return convertElementKind(element.kind);
  }

  String? _getAliasedTypeString(analyzer.Element element) {
    if (element is analyzer.TypeAliasElement) {
      var aliasedType = element.aliasedType;
      return aliasedType.getDisplayString(withNullability: false);
    }
    return null;
  }

  /// Return a textual representation of the parameters of the given [element],
  /// or `null` if the element does not have any parameters.
  String? _getParametersString(analyzer.Element element) {
    // TODO(scheglov) expose the corresponding feature from ExecutableElement
    List<analyzer.ParameterElement> parameters;
    if (element is analyzer.ExecutableElement) {
      // valid getters don't have parameters
      if (element.kind == analyzer.ElementKind.GETTER &&
          element.parameters.isEmpty) {
        return null;
      }
      parameters = element.parameters;
    } else if (element is analyzer.TypeAliasElement) {
      var aliasedElement = element.aliasedElement;
      if (aliasedElement is analyzer.GenericFunctionTypeElement) {
        parameters = aliasedElement.parameters;
      } else {
        return null;
      }
    } else {
      return null;
    }
    var buffer = StringBuffer();
    var closeOptionalString = '';
    buffer.write('(');
    for (var i = 0; i < parameters.length; i++) {
      var parameter = parameters[i];
      if (i > 0) {
        buffer.write(', ');
      }
      if (closeOptionalString.isEmpty) {
        if (parameter.isNamed) {
          buffer.write('{');
          closeOptionalString = '}';
        } else if (parameter.isOptionalPositional) {
          buffer.write('[');
          closeOptionalString = ']';
        }
      }
      parameter.appendToWithoutDelimiters(buffer, withNullability: false);
    }
    buffer.write(closeOptionalString);
    buffer.write(')');
    return buffer.toString();
  }

  /// Return a textual representation of the return type of the given [element],
  /// or `null` if the element does not have a return type.
  String? _getReturnTypeString(analyzer.Element element) {
    if (element is analyzer.ExecutableElement) {
      if (element.kind == analyzer.ElementKind.SETTER) {
        return null;
      }
      return element.returnType.getDisplayString(withNullability: false);
    } else if (element is analyzer.VariableElement) {
      return element.type.getDisplayString(withNullability: false);
    } else if (element is analyzer.TypeAliasElement) {
      var aliasedType = element.aliasedType;
      if (aliasedType is FunctionType) {
        var returnType = aliasedType.returnType;
        return returnType.getDisplayString(withNullability: false);
      }
    }
    return null;
  }

  /// Return a textual representation of the type parameters of the given
  /// [element], or `null` if the element does not have type parameters.
  String? _getTypeParametersString(analyzer.Element element) {
    if (element is analyzer.TypeParameterizedElement) {
      var typeParameters = element.typeParameters;
      if (typeParameters.isEmpty) {
        return null;
      }
      return '<${typeParameters.join(', ')}>';
    }
    return null;
  }

  /// Return the compilation unit containing the given [element].
  analyzer.CompilationUnitElement? _getUnitElement(analyzer.Element element) {
    analyzer.Element? currentElement = element;
    if (currentElement is analyzer.CompilationUnitElement) {
      return currentElement;
    }
    if (currentElement.enclosingElement is analyzer.LibraryElement) {
      currentElement = currentElement.enclosingElement;
    }
    if (currentElement is analyzer.LibraryElement) {
      return currentElement.definingCompilationUnit;
    }
    for (;
        currentElement != null;
        currentElement = currentElement.enclosingElement) {
      if (currentElement is analyzer.CompilationUnitElement) {
        return currentElement;
      }
    }
    return null;
  }

  bool _isAbstract(analyzer.Element element) {
    // TODO(scheglov) add isAbstract to Element API
    if (element is analyzer.ClassElement) {
      return element.isAbstract;
    } else if (element is analyzer.MethodElement) {
      return element.isAbstract;
    } else if (element is analyzer.PropertyAccessorElement) {
      return element.isAbstract;
    }
    return false;
  }

  bool _isConst(analyzer.Element element) {
    // TODO(scheglov) add isConst to Element API
    if (element is analyzer.ConstructorElement) {
      return element.isConst;
    } else if (element is analyzer.VariableElement) {
      return element.isConst;
    }
    return false;
  }

  bool _isFinal(analyzer.Element element) {
    // TODO(scheglov) add isFinal to Element API
    if (element is analyzer.VariableElement) {
      return element.isFinal;
    }
    return false;
  }

  bool _isStatic(analyzer.Element element) {
    // TODO(scheglov) add isStatic to Element API
    if (element is analyzer.ExecutableElement) {
      return element.isStatic;
    } else if (element is analyzer.PropertyInducingElement) {
      return element.isStatic;
    }
    return false;
  }

  /// Create and return a location within the given [unitElement] at the given
  /// [range].
  plugin.Location? _locationForArgs(
      analyzer.CompilationUnitElement? unitElement,
      analyzer.SourceRange range) {
    var startLine = 0;
    var startColumn = 0;
    var endLine = 0;
    var endColumn = 0;

    if (unitElement == null) {
      return null;
    }
    try {
      var lineInfo = unitElement.lineInfo;
      if (lineInfo != null) {
        var offsetLocation = lineInfo.getLocation(range.offset);
        startLine = offsetLocation.lineNumber;
        startColumn = offsetLocation.columnNumber;
        var endLocation = lineInfo.getLocation(range.offset + range.length);
        endLine = endLocation.lineNumber;
        endColumn = endLocation.columnNumber;
      }
    } on analyzer.AnalysisException {
      // Ignore exceptions
    }
    return plugin.Location(unitElement.source.fullName, range.offset,
        range.length, startLine, startColumn,
        endLine: endLine, endColumn: endColumn);
  }
}
