// Copyright (c) 2020, 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:analysis_server/src/services/correction/dart/abstract_producer.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
import 'package:analysis_server/src/services/correction/namespace.dart';
import 'package:analysis_server/src/services/linter/lint_names.dart';
import 'package:analysis_server/src/utilities/extensions/element.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:analyzer_plugin/src/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/src/utilities/library.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';

class ImportLibrary extends MultiCorrectionProducer {
  final _ImportKind _importKind;

  ImportLibrary(this._importKind);

  @override
  Stream<CorrectionProducer> get producers async* {
    final node = this.node;
    if (_importKind == _ImportKind.dartAsync) {
      yield* _importLibrary(DartFixKind.IMPORT_ASYNC, Uri.parse('dart:async'));
    } else if (_importKind == _ImportKind.forExtension) {
      if (node is SimpleIdentifier) {
        var extensionName = node.name;
        yield* _importLibraryForElement(
            extensionName,
            const [ElementKind.EXTENSION],
            const [TopLevelDeclarationKind.extension]);
      }
    } else if (_importKind == _ImportKind.forExtensionMember) {
      /// Return producers that will import extensions that apply to the
      /// [targetType] and that define a member with the given [memberName].
      Stream<CorrectionProducer> importMatchingExtensions(
          String memberName, DartType? targetType) async* {
        if (targetType == null) {
          return;
        }
        var definingLibraries =
            extensionCache.membersByName[memberName]?.toList();
        if (definingLibraries != null) {
          for (var definingLibrary in definingLibraries) {
            var libraryPath = definingLibrary.libraryPath;
            var uri = sessionHelper.session.uriConverter.pathToUri(libraryPath);
            if (uri != null) {
              yield* _importExtensionInLibrary(uri, targetType, memberName);
            }
          }
        }
      }

      if (node is SimpleIdentifier) {
        var memberName = node.name;
        if (memberName.startsWith('_')) {
          return;
        }
        yield* importMatchingExtensions(memberName, _targetType(node));
      } else if (node is BinaryExpression) {
        var memberName = node.operator.lexeme;
        yield* importMatchingExtensions(
            memberName, node.leftOperand.staticType);
      }
    } else if (_importKind == _ImportKind.forFunction) {
      if (node is SimpleIdentifier) {
        var parent = node.parent;
        if (parent is MethodInvocation) {
          if (parent.realTarget != null || parent.methodName != node) {
            return;
          }
        }

        var name = node.name;
        yield* _importLibraryForElement(name, const [
          ElementKind.FUNCTION,
          ElementKind.TOP_LEVEL_VARIABLE
        ], const [
          TopLevelDeclarationKind.function,
          TopLevelDeclarationKind.variable
        ]);
      }
    } else if (_importKind == _ImportKind.forTopLevelVariable) {
      var targetNode = node;
      if (targetNode is Annotation) {
        var name = targetNode.name;
        if (name.staticElement == null) {
          if (targetNode.arguments != null) {
            return;
          }
          targetNode = name;
        }
      }
      if (targetNode is SimpleIdentifier) {
        var name = targetNode.name;
        yield* _importLibraryForElement(
            name,
            const [ElementKind.TOP_LEVEL_VARIABLE],
            const [TopLevelDeclarationKind.variable]);
      }
    } else if (_importKind == _ImportKind.forType) {
      var targetNode = node;
      if (targetNode is Annotation) {
        var name = targetNode.name;
        if (name.staticElement == null) {
          if (targetNode.arguments == null) {
            return;
          }
          targetNode = name;
        }
      }
      if (mightBeTypeIdentifier(targetNode)) {
        var typeName = (targetNode is SimpleIdentifier)
            ? targetNode.name
            : (targetNode as PrefixedIdentifier).prefix.name;
        yield* _importLibraryForElement(typeName, const [
          ElementKind.CLASS,
          ElementKind.FUNCTION_TYPE_ALIAS,
          ElementKind.TYPE_ALIAS
        ], const [
          TopLevelDeclarationKind.type
        ]);
      } else if (mightBeImplicitConstructor(targetNode)) {
        var typeName = (targetNode as SimpleIdentifier).name;
        yield* _importLibraryForElement(typeName, const [ElementKind.CLASS],
            const [TopLevelDeclarationKind.type]);
      }
    }
  }

  @override
  bool mightBeTypeIdentifier(AstNode node) {
    if (super.mightBeTypeIdentifier(node)) {
      return true;
    }
    if (node is PrefixedIdentifier) {
      var parent = node.parent;
      if (parent is NamedType) {
        return true;
      }
    }
    return false;
  }

  Stream<CorrectionProducer> _importExtensionInLibrary(
      Uri uri, DartType targetType, String memberName) async* {
    // Look to see whether the library at the [uri] is already imported. If it
    // is, then we can check the extension elements without needing to perform
    // additional analysis.
    var foundImport = false;
    for (var imp in libraryElement.imports) {
      // prepare element
      var importedLibrary = imp.importedLibrary;
      if (importedLibrary == null || importedLibrary.source.uri != uri) {
        continue;
      }
      foundImport = true;
      for (var extension in importedLibrary.matchingExtensionsWithMember(
          libraryElement, targetType, memberName)) {
        // If the import has a combinator that needs to be updated, then offer
        // to update it.
        var combinators = imp.combinators;
        if (combinators.length == 1) {
          var combinator = combinators[0];
          if (combinator is HideElementCombinator) {
            // TODO(brianwilkerson) Support removing the extension name from a
            //  hide combinator.
          } else if (combinator is ShowElementCombinator) {
            yield _ImportLibraryShow(
                uri.toString(), combinator, extension.name!);
          }
        }
      }
    }

    // If the library at the [uri] is not already imported, we return a
    // correction producer that will either add an import or not based on the
    // result of analyzing the library.
    if (!foundImport) {
      yield _ImportLibraryContainingExtension(uri, targetType, memberName);
    }
  }

  /// Returns a list of one or two import corrections.
  ///
  /// If [includeRelativeFix] is `false`, only one correction, with an absolute
  /// import path, is returned. Otherwise, a correction with an absolute import
  /// path and a correction with a relative path are returned. If the
  /// `prefer_relative_imports` lint rule is enabled, the relative path is
  /// returned first.
  Stream<CorrectionProducer> _importLibrary(
    FixKind fixKind,
    Uri library, {
    bool includeRelativeFix = false,
  }) {
    if (!includeRelativeFix) {
      return Stream.fromIterable([
        _ImportAbsoluteLibrary(fixKind, library),
      ]);
    }
    if (isLintEnabled(LintNames.prefer_relative_imports)) {
      return Stream.fromIterable([
        _ImportRelativeLibrary(fixKind, library),
        _ImportAbsoluteLibrary(fixKind, library),
      ]);
    } else {
      return Stream.fromIterable([
        _ImportAbsoluteLibrary(fixKind, library),
        _ImportRelativeLibrary(fixKind, library),
      ]);
    }
  }

  Stream<CorrectionProducer> _importLibraryForElement(
      String name,
      List<ElementKind> elementKinds,
      List<TopLevelDeclarationKind> kinds2) async* {
    // ignore if private
    if (name.startsWith('_')) {
      return;
    }
    // may be there is an existing import,
    // but it is with prefix and we don't use this prefix
    var alreadyImportedWithPrefix = <String>{};
    for (var imp in libraryElement.imports) {
      // prepare element
      var libraryElement = imp.importedLibrary;
      if (libraryElement == null) {
        continue;
      }
      var element = getExportedElement(libraryElement, name);
      if (element == null) {
        continue;
      }
      if (element is PropertyAccessorElement) {
        element = element.variable;
      }
      if (!elementKinds.contains(element.kind)) {
        continue;
      }
      // may be apply prefix
      var prefix = imp.prefix;
      if (prefix != null) {
        yield _ImportLibraryPrefix(libraryElement, prefix);
        continue;
      }
      // may be update "show" directive
      var combinators = imp.combinators;
      if (combinators.length == 1) {
        var combinator = combinators[0];
        if (combinator is HideElementCombinator) {
          // TODO(brianwilkerson) Support removing the element name from a
          //  hide combinator.
        } else if (combinator is ShowElementCombinator) {
          // prepare library name - unit name or 'dart:name' for SDK library
          var libraryName =
              libraryElement.definingCompilationUnit.source.uri.toString();
          if (libraryElement.isInSdk) {
            libraryName = libraryElement.source.shortName;
          }
          // don't add this library again
          alreadyImportedWithPrefix.add(libraryElement.source.fullName);
          yield _ImportLibraryShow(libraryName, combinator, name);
        }
      }
    }
    // Find new top-level declarations.
    var declarations = getTopLevelDeclarations(name);
    for (var declaration in declarations) {
      // Check the kind.
      if (!kinds2.contains(declaration.kind)) {
        continue;
      }
      // Check the source.
      if (alreadyImportedWithPrefix.contains(declaration.path)) {
        continue;
      }
      // Check that the import doesn't end with '.template.dart'
      if (declaration.uri.path.endsWith('.template.dart')) {
        continue;
      }
      // Compute the fix kind.
      FixKind fixKind;
      if (declaration.uri.isScheme('dart')) {
        fixKind = DartFixKind.IMPORT_LIBRARY_SDK;
      } else if (_isLibSrcPath(declaration.path)) {
        // Bad: non-API.
        fixKind = DartFixKind.IMPORT_LIBRARY_PROJECT3;
      } else if (declaration.isExported) {
        // Ugly: exports.
        fixKind = DartFixKind.IMPORT_LIBRARY_PROJECT2;
      } else {
        // Good: direct declaration.
        fixKind = DartFixKind.IMPORT_LIBRARY_PROJECT1;
      }
      // If both files are in the same package's lib folder, also include a
      // relative import.
      var includeRelativeUri = canBeRelativeImport(
          declaration.uri, libraryElement.librarySource.uri);
      // Add the fix(es).
      yield* _importLibrary(fixKind, declaration.uri,
          includeRelativeFix: includeRelativeUri);
    }
  }

  bool _isLibSrcPath(String path) {
    var parts = resourceProvider.pathContext.split(path);
    for (var i = 0; i < parts.length - 2; i++) {
      if (parts[i] == 'lib' && parts[i + 1] == 'src') {
        return true;
      }
    }
    return false;
  }

  /// If the [node] might represent an access to a member of a type, return the
  /// type of the object being accessed, otherwise return `null`.
  DartType? _targetType(SimpleIdentifier node) {
    var parent = node.parent;
    if (parent is MethodInvocation && parent.methodName == node) {
      var target = parent.realTarget;
      if (target != null) {
        return target.staticType;
      }
    } else if (parent is PropertyAccess && parent.propertyName == node) {
      return parent.realTarget.staticType;
    } else if (parent is PrefixedIdentifier && parent.identifier == node) {
      return parent.prefix.staticType;
    }
    // If there is no explicit target, then return the type of an implicit
    // `this`.
    DartType? enclosingThisType(AstNode node) {
      var parent = node.parent;
      if (parent is ClassOrMixinDeclaration) {
        return parent.declaredElement?.thisType;
      } else if (parent is ExtensionDeclaration) {
        return parent.extendedType.type;
      }
    }

    while (parent != null) {
      if (parent is MethodDeclaration) {
        if (!parent.isStatic) {
          return enclosingThisType(parent);
        }
        return null;
      } else if (parent is FieldDeclaration) {
        if (!parent.isStatic) {
          return enclosingThisType(parent);
        }
        return null;
      }
      parent = parent.parent;
    }
  }

  /// Return an instance of this class that will add an import of `dart:async`.
  /// Used as a tear-off in `FixProcessor`.
  static ImportLibrary dartAsync() => ImportLibrary(_ImportKind.dartAsync);

  /// Return an instance of this class that will add an import for an extension.
  /// Used as a tear-off in `FixProcessor`.
  static ImportLibrary forExtension() =>
      ImportLibrary(_ImportKind.forExtension);

  static ImportLibrary forExtensionMember() =>
      ImportLibrary(_ImportKind.forExtensionMember);

  /// Return an instance of this class that will add an import for a top-level
  /// function. Used as a tear-off in `FixProcessor`.
  static ImportLibrary forFunction() => ImportLibrary(_ImportKind.forFunction);

  /// Return an instance of this class that will add an import for a top-level
  /// variable. Used as a tear-off in `FixProcessor`.
  static ImportLibrary forTopLevelVariable() =>
      ImportLibrary(_ImportKind.forTopLevelVariable);

  /// Return an instance of this class that will add an import for a type (class
  /// or mixin). Used as a tear-off in `FixProcessor`.
  static ImportLibrary forType() => ImportLibrary(_ImportKind.forType);
}

/// A correction processor that can add an import using an absolute URI.
class _ImportAbsoluteLibrary extends CorrectionProducer {
  final FixKind _fixKind;

  final Uri _library;

  String _uriText = '';

  _ImportAbsoluteLibrary(this._fixKind, this._library);

  @override
  List<Object> get fixArguments => [_uriText];

  @override
  FixKind get fixKind => _fixKind;

  @override
  Future<void> compute(ChangeBuilder builder) async {
    await builder.addDartFileEdit(file, (builder) {
      if (builder is DartFileEditBuilderImpl) {
        _uriText = builder.importLibraryWithAbsoluteUri(_library);
      }
    });
  }
}

enum _ImportKind {
  dartAsync,
  forExtension,
  forExtensionMember,
  forFunction,
  forTopLevelVariable,
  forType
}

/// A correction processor that can add an import of a library containing an
/// extension, but which does so only if the extension applies to a given type.
class _ImportLibraryContainingExtension extends CorrectionProducer {
  /// The URI of the library defining the extension.
  Uri uri;

  /// The type of the target that the extension must apply to.
  DartType targetType;

  /// The name of the member that the extension must declare.
  String memberName;

  /// The URI that is being proposed for the import directive.
  String _uriText = '';

  _ImportLibraryContainingExtension(this.uri, this.targetType, this.memberName);

  @override
  List<Object> get fixArguments => [_uriText];

  @override
  FixKind get fixKind => DartFixKind.IMPORT_LIBRARY_PROJECT1;

  @override
  Future<void> compute(ChangeBuilder builder) async {
    var result = await sessionHelper.session.getLibraryByUri(uri.toString());
    if (result is LibraryElementResult) {
      var library = result.element;
      if (library
          .matchingExtensionsWithMember(libraryElement, targetType, memberName)
          .isNotEmpty) {
        await builder.addDartFileEdit(file, (builder) {
          _uriText = builder.importLibrary(uri);
        });
      }
    }
  }
}

/// A correction processor that can add a prefix to an identifier defined in a
/// library that is already imported but that is imported with a prefix.
class _ImportLibraryPrefix extends CorrectionProducer {
  final LibraryElement _importedLibrary;
  final PrefixElement _importPrefix;

  String _libraryName = '';

  String _prefixName = '';

  _ImportLibraryPrefix(this._importedLibrary, this._importPrefix);

  @override
  List<Object> get fixArguments => [_libraryName, _prefixName];

  @override
  FixKind get fixKind => DartFixKind.IMPORT_LIBRARY_PREFIX;

  @override
  Future<void> compute(ChangeBuilder builder) async {
    _libraryName = _importedLibrary.displayName;
    _prefixName = _importPrefix.displayName;
    await builder.addDartFileEdit(file, (builder) {
      builder.addSimpleReplacement(range.startLength(node, 0), '$_prefixName.');
    });
  }
}

/// A correction processor that can add a name to the show combinator of an
/// existing import.
class _ImportLibraryShow extends CorrectionProducer {
  final String _libraryName;

  final ShowElementCombinator _showCombinator;

  final String _addedName;

  _ImportLibraryShow(this._libraryName, this._showCombinator, this._addedName);

  @override
  List<Object> get fixArguments => [_libraryName];

  @override
  FixKind get fixKind => DartFixKind.IMPORT_LIBRARY_SHOW;

  @override
  Future<void> compute(ChangeBuilder builder) async {
    Set<String> showNames = SplayTreeSet<String>();
    showNames.addAll(_showCombinator.shownNames);
    showNames.add(_addedName);
    var newShowCode = 'show ${showNames.join(', ')}';
    var offset = _showCombinator.offset;
    var length = _showCombinator.end - offset;
    var libraryFile = resolvedResult.libraryElement.source.fullName;
    await builder.addDartFileEdit(libraryFile, (builder) {
      builder.addSimpleReplacement(SourceRange(offset, length), newShowCode);
    });
  }
}

/// A correction processor that can add an import using a relative URI.
class _ImportRelativeLibrary extends CorrectionProducer {
  final FixKind _fixKind;

  final Uri _library;

  String _uriText = '';

  _ImportRelativeLibrary(this._fixKind, this._library);

  @override
  List<Object> get fixArguments => [_uriText];

  @override
  FixKind get fixKind => _fixKind;

  @override
  Future<void> compute(ChangeBuilder builder) async {
    await builder.addDartFileEdit(file, (builder) {
      if (builder is DartFileEditBuilderImpl) {
        _uriText = builder.importLibraryWithRelativeUri(_library);
      }
    });
  }
}
