// 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:analysis_server/src/protocol_server.dart' as protocol;
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:analyzer/src/services/available_declarations.dart';

/// Compute which suggestion sets should be included into completion inside
/// the given [resolvedUnit] of a file.  Depending on the file path, it might
/// include different sets, e.g. inside the `lib/` directory of a `Pub` package
/// only regular dependencies can be referenced, but `test/` can reference
/// both regular and "dev" dependencies.
void computeIncludedSetList(
  DeclarationsTracker tracker,
  ResolvedUnitResult resolvedUnit,
  List<protocol.IncludedSuggestionSet> includedSetList,
  Set<String> includedElementNames,
) {
  var analysisContext = resolvedUnit.session.analysisContext;
  var context = tracker.getContext(analysisContext);
  if (context == null) return;

  var librariesObject = context.getLibraries(resolvedUnit.path);

  var importedUriSet = resolvedUnit.libraryElement.importedLibraries
      .map((importedLibrary) => importedLibrary.source.uri)
      .toSet();

  void includeLibrary(
    Library library,
    int importedRelevance,
    int deprecatedRelevance,
    int otherwiseRelevance,
  ) {
    int relevance;
    if (importedUriSet.contains(library.uri)) {
      return;
    }
    if (library.isDeprecated) {
      relevance = deprecatedRelevance;
    } else {
      relevance = otherwiseRelevance;
    }

    includedSetList.add(
      protocol.IncludedSuggestionSet(
        library.id,
        relevance,
        displayUri: _getRelativeFileUri(resolvedUnit, library.uri),
      ),
    );

    for (var declaration in library.declarations) {
      includedElementNames.add(declaration.name);
    }
  }

  for (var library in librariesObject.context) {
    includeLibrary(library, 8, 2, 5);
  }

  for (var library in librariesObject.dependencies) {
    includeLibrary(library, 7, 1, 4);
  }

  for (var library in librariesObject.sdk) {
    includeLibrary(library, 6, 0, 3);
  }
}

protocol.CompletionAvailableSuggestionsParams
    createCompletionAvailableSuggestions(
  List<Library> changed,
  List<int> removed,
) =>
        protocol.CompletionAvailableSuggestionsParams(
          changedLibraries: changed.map((library) {
            return _protocolAvailableSuggestionSet(library);
          }).toList(),
          removedLibraries: removed,
        );

/// Convert the [LibraryChange] into the corresponding protocol notification.
protocol.Notification createCompletionAvailableSuggestionsNotification(
  List<Library> changed,
  List<int> removed,
) =>
    createCompletionAvailableSuggestions(changed, removed).toNotification();

/// Compute existing imports and elements that they provide.
protocol.Notification createExistingImportsNotification(
  ResolvedUnitResult resolvedUnit,
) {
  var uniqueStrings = _UniqueImportedStrings();
  var uniqueElements = _UniqueImportedElements();
  var existingImports = <protocol.ExistingImport>[];

  var importElementList = resolvedUnit.libraryElement.imports;
  for (var import in importElementList) {
    var importedLibrary = import.importedLibrary;
    if (importedLibrary == null) continue;

    var importedUriStr = '${importedLibrary.librarySource.uri}';

    var existingImportElements = <int>[];
    for (var element in import.namespace.definedNames.values) {
      if (element.librarySource != null) {
        var index = uniqueElements.indexOf(uniqueStrings, element);
        existingImportElements.add(index);
      }
    }

    existingImports.add(protocol.ExistingImport(
      uniqueStrings.indexOf(importedUriStr),
      existingImportElements,
    ));
  }

  return protocol.CompletionExistingImportsParams(
    resolvedUnit.libraryElement.source.fullName,
    protocol.ExistingImports(
      protocol.ImportedElementSet(
        uniqueStrings.values,
        uniqueElements.uriList,
        uniqueElements.nameList,
      ),
      existingImports,
    ),
  ).toNotification();
}

/// TODO(dantup): We need to expose this because the Declarations code currently
/// returns declarations with DeclarationKinds but the DartCompletionManager
/// gives us a list of "included ElementKinds". Maybe it would be better to expose
/// includedDeclarationKinds and then just map that list to ElementKinds once in
/// domain_completion for the original protocol?
protocol.ElementKind protocolElementKind(DeclarationKind kind) {
  switch (kind) {
    case DeclarationKind.CLASS:
      return protocol.ElementKind.CLASS;
    case DeclarationKind.CLASS_TYPE_ALIAS:
      return protocol.ElementKind.CLASS_TYPE_ALIAS;
    case DeclarationKind.CONSTRUCTOR:
      return protocol.ElementKind.CONSTRUCTOR;
    case DeclarationKind.ENUM:
      return protocol.ElementKind.ENUM;
    case DeclarationKind.ENUM_CONSTANT:
      return protocol.ElementKind.ENUM_CONSTANT;
    case DeclarationKind.EXTENSION:
      return protocol.ElementKind.EXTENSION;
    case DeclarationKind.FIELD:
      return protocol.ElementKind.FIELD;
    case DeclarationKind.FUNCTION:
      return protocol.ElementKind.FUNCTION;
    case DeclarationKind.FUNCTION_TYPE_ALIAS:
      return protocol.ElementKind.FUNCTION_TYPE_ALIAS;
    case DeclarationKind.GETTER:
      return protocol.ElementKind.GETTER;
    case DeclarationKind.METHOD:
      return protocol.ElementKind.METHOD;
    case DeclarationKind.MIXIN:
      return protocol.ElementKind.MIXIN;
    case DeclarationKind.SETTER:
      return protocol.ElementKind.SETTER;
    case DeclarationKind.VARIABLE:
      return protocol.ElementKind.TOP_LEVEL_VARIABLE;
  }
}

/// Computes the best URI to import [what] into the [unit] library.
String? _getRelativeFileUri(ResolvedUnitResult unit, Uri what) {
  if (what.scheme == 'file') {
    var pathContext = unit.session.resourceProvider.pathContext;

    var libraryPath = unit.libraryElement.source.fullName;
    var libraryFolder = pathContext.dirname(libraryPath);

    var whatPath = pathContext.fromUri(what);
    var relativePath = pathContext.relative(whatPath, from: libraryFolder);
    return pathContext.split(relativePath).join('/');
  }
  return null;
}

protocol.AvailableSuggestion? _protocolAvailableSuggestion(
    Declaration declaration) {
  var label = declaration.name;
  var parent = declaration.parent;
  if (parent != null) {
    if (declaration.kind == DeclarationKind.CONSTRUCTOR) {
      label = parent.name;
      if (declaration.name.isNotEmpty) {
        label += '.${declaration.name}';
      }
    } else if (declaration.kind == DeclarationKind.ENUM_CONSTANT) {
      label = '${parent.name}.${declaration.name}';
    } else if (declaration.kind == DeclarationKind.GETTER &&
        declaration.isStatic) {
      label = '${parent.name}.${declaration.name}';
    } else if (declaration.kind == DeclarationKind.FIELD &&
        declaration.isStatic) {
      label = '${parent.name}.${declaration.name}';
    } else {
      return null;
    }
  }

  String declaringLibraryUri;
  if (parent == null) {
    declaringLibraryUri = '${declaration.locationLibraryUri}';
  } else {
    declaringLibraryUri = '${parent.locationLibraryUri}';
  }

  var relevanceTags = declaration.relevanceTags.toList()..add(declaration.name);

  return protocol.AvailableSuggestion(
    label,
    declaringLibraryUri,
    _protocolElement(declaration),
    defaultArgumentListString: declaration.defaultArgumentListString,
    defaultArgumentListTextRanges: declaration.defaultArgumentListTextRanges,
    parameterNames: declaration.parameterNames,
    parameterTypes: declaration.parameterTypes,
    requiredParameterCount: declaration.requiredParameterCount,
    relevanceTags: relevanceTags,
  );
}

protocol.AvailableSuggestionSet _protocolAvailableSuggestionSet(
    Library library) {
  var items = <protocol.AvailableSuggestion>[];

  void addItem(Declaration declaration) {
    var suggestion = _protocolAvailableSuggestion(declaration);
    if (suggestion != null) {
      items.add(suggestion);
    }
    declaration.children.forEach(addItem);
  }

  for (var declaration in library.declarations) {
    addItem(declaration);
  }

  return protocol.AvailableSuggestionSet(library.id, library.uriStr, items);
}

protocol.Element _protocolElement(Declaration declaration) {
  return protocol.Element(
    protocolElementKind(declaration.kind),
    declaration.name,
    _protocolElementFlags(declaration),
    location: protocol.Location(
      declaration.locationPath,
      declaration.locationOffset,
      0, // length
      declaration.locationStartLine,
      declaration.locationStartColumn,
      declaration.locationStartLine, // endLine
      declaration.locationStartColumn, // endColumn
    ),
    parameters: declaration.parameters,
    returnType: declaration.returnType,
    typeParameters: declaration.typeParameters,
  );
}

int _protocolElementFlags(Declaration declaration) {
  return protocol.Element.makeFlags(
    isAbstract: declaration.isAbstract,
    isConst: declaration.isConst,
    isDeprecated: declaration.isDeprecated,
    isFinal: declaration.isFinal,
    isStatic: declaration.isStatic,
  );
}

class CompletionLibrariesWorker implements SchedulerWorker {
  final DeclarationsTracker tracker;

  CompletionLibrariesWorker(this.tracker);

  @override
  AnalysisDriverPriority get workPriority {
    if (tracker.hasWork) {
      return AnalysisDriverPriority.priority;
    } else {
      return AnalysisDriverPriority.nothing;
    }
  }

  @override
  Future<void> performWork() async {
    tracker.doWork();
  }
}

class DeclarationsTrackerData {
  final DeclarationsTracker _tracker;

  /// The set of libraries reported by [_tracker] so far.
  ///
  /// We create [_tracker] at the server start, but the completion domain
  /// should send available declarations only when the corresponding
  /// subscription is done. OTOH, we don't want the changes stream grow
  /// infinitely as the same libraries are changed multiple times. So, we drain
  /// the changes stream in this map, and send it at subscription.
  final Map<int, Library> _idToLibrary = {};

  /// When the completion domain subscribes for changes, we start redirecting
  /// changes to this listener.
  void Function(LibraryChange)? _listener;

  DeclarationsTrackerData(this._tracker) {
    _tracker.changes.listen((change) {
      var listener = _listener;
      if (listener != null) {
        listener(change);
      } else {
        for (var library in change.changed) {
          _idToLibrary[library.id] = library;
        }
        for (var id in change.removed) {
          _idToLibrary.remove(id);
        }
      }
    });
  }

  /// Start listening for available libraries, and return the libraries that
  /// were accumulated so far.
  List<Library> startListening(void Function(LibraryChange) listener) {
    if (_listener != null) {
      throw StateError('Already listening.');
    }
    _listener = listener;

    var accumulatedLibraries = _idToLibrary.values.toList();
    _idToLibrary.clear();
    return accumulatedLibraries;
  }

  void stopListening() {
    if (_listener == null) {
      throw StateError('Not listening.');
    }
    _listener = null;
  }
}

class _ImportedElement {
  final int uri;
  final int name;

  @override
  final int hashCode;

  _ImportedElement(this.uri, this.name)
      : hashCode = JenkinsSmiHash.hash2(uri, name);

  @override
  bool operator ==(other) {
    return other is _ImportedElement && other.uri == uri && other.name == name;
  }
}

class _UniqueImportedElements {
  final map = <_ImportedElement, int>{};

  List<int> get nameList => map.keys.map((e) => e.name).toList();

  List<int> get uriList => map.keys.map((e) => e.uri).toList();

  int indexOf(_UniqueImportedStrings strings, Element element) {
    var uriStr = '${element.librarySource!.uri}';
    var wrapper = _ImportedElement(
      strings.indexOf(uriStr),
      strings.indexOf(element.name!),
    );
    var index = map[wrapper];
    if (index == null) {
      index = map.length;
      map[wrapper] = index;
    }
    return index;
  }
}

class _UniqueImportedStrings {
  final map = <String, int>{};

  List<String> get values => map.keys.toList();

  int indexOf(String str) {
    var index = map[str];
    if (index == null) {
      index = map.length;
      map[str] = index;
    }
    return index;
  }
}
