// 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 'dart:async';

import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
import 'package:analysis_server/src/lsp/mapping.dart';
import 'package:analysis_server/src/search/type_hierarchy.dart';

class ImplementationHandler
    extends MessageHandler<TextDocumentPositionParams, List<Location>> {
  ImplementationHandler(LspAnalysisServer server) : super(server);
  Method get handlesMessage => Method.textDocument_implementation;

  @override
  LspJsonHandler<TextDocumentPositionParams> get jsonHandler =>
      TextDocumentPositionParams.jsonHandler;

  @override
  Future<ErrorOr<List<Location>>> handle(
      TextDocumentPositionParams params, CancellationToken token) async {
    if (!isDartDocument(params.textDocument)) {
      return success(const []);
    }

    final pos = params.position;
    final path = pathOfDoc(params.textDocument);
    final unit = await path.mapResult(requireResolvedUnit);
    final offset = await unit.mapResult((unit) => toOffset(unit.lineInfo, pos));
    return offset
        .mapResult((offset) => _getImplementations(path.result, offset, token));
  }

  Future<ErrorOr<List<Location>>> _getImplementations(
      String file, int offset, CancelableToken token) async {
    final element = await server.getElementAtOffset(file, offset);
    final computer = new TypeHierarchyComputer(server.searchEngine, element);
    if (token.isCancellationRequested) {
      return cancelled();
    }
    final items = await computer.compute();

    if (items == null || items.isEmpty) {
      return success([]);
    }

    Iterable<TypeHierarchyItem> getDescendants(TypeHierarchyItem item) => item
        .subclasses
        ?.map((i) => items[i])
        ?.followedBy(item.subclasses.expand((i) => getDescendants(items[i])));

    // [TypeHierarchyComputer] returns the whole tree, but we specifically only
    // want implementations (sub-classes). Find the referenced element and then
    // recursively add its children.
    var currentItem = items.firstWhere(
      (item) {
        final location =
            item.memberElement?.location ?? item.classElement?.location;
        return location.offset <= offset &&
            location.offset + location.length >= offset;
      },
      // If we didn't find an item spanning our offset, we must've been at a
      // call site so start everything from the root item.
      orElse: () => items.first,
    );

    final isClass = currentItem.memberElement == null;

    final locations = getDescendants(currentItem).where((item) {
      // Filter based on type, so when searching for members we don't include
      // any intermediate classes that don't have implementations for the
      // method.
      return isClass ? item.classElement != null : item.memberElement != null;
    }).map((item) {
      final elementLocation =
          item.memberElement?.location ?? item.classElement?.location;
      final lineInfo = server.getLineInfo(elementLocation.file);
      return Location(
        Uri.file(elementLocation.file).toString(),
        toRange(lineInfo, elementLocation.offset, elementLocation.length),
      );
    }).toList();

    return success(locations);
  }
}
