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

import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_constants.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/domain_abstract.dart';
import 'package:analysis_server/src/plugin/plugin_manager.dart';
import 'package:analysis_server/src/plugin/result_merger.dart';
import 'package:analysis_server/src/services/kythe/kythe_visitors.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/generated/type_system.dart';
import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/protocol/protocol_constants.dart' as plugin;
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;

/**
 * Instances of the class [KytheDomainHandler] implement a [RequestHandler]
 * that handles requests in the `kythe` domain.
 */
class KytheDomainHandler extends AbstractRequestHandler {
  /**
   * Initialize a newly created handler to handle requests for the given [server].
   */
  KytheDomainHandler(AnalysisServer server) : super(server);

  /**
   * Implement the `kythe.getKytheEntries` request.
   */
  Future<void> getKytheEntries(Request request) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    String file = new KytheGetKytheEntriesParams.fromRequest(request).file;
    AnalysisDriver driver = server.getAnalysisDriver(file);
    if (driver == null) {
      server.sendResponse(new Response.getKytheEntriesInvalidFile(request));
    } else {
      //
      // Allow plugins to start computing entries.
      //
      plugin.KytheGetKytheEntriesParams requestParams =
          new plugin.KytheGetKytheEntriesParams(file);
      Map<PluginInfo, Future<plugin.Response>> pluginFutures = server
          .pluginManager
          .broadcastRequest(requestParams, contextRoot: driver.contextRoot);
      //
      // Compute entries generated by server.
      //
      List<KytheGetKytheEntriesResult> allResults =
          <KytheGetKytheEntriesResult>[];
      ResolvedUnitResult result = await server.getResolvedUnit(file);
      if (result?.state == ResultState.VALID) {
        TypeSystem typeSystem = await result.libraryElement.session.typeSystem;
        List<KytheEntry> entries = <KytheEntry>[];
        // TODO(brianwilkerson) Figure out how to get the list of files.
        List<String> files = <String>[];
        result.unit.accept(new KytheDartVisitor(
            server.resourceProvider,
            entries,
            file,
            new InheritanceManager2(typeSystem),
            result.content));
        allResults.add(new KytheGetKytheEntriesResult(entries, files));
      }
      //
      // Add the entries produced by plugins to the server-generated entries.
      //
      if (pluginFutures != null) {
        List<plugin.Response> responses = await waitForResponses(pluginFutures,
            requestParameters: requestParams);
        for (plugin.Response response in responses) {
          plugin.KytheGetKytheEntriesResult result =
              new plugin.KytheGetKytheEntriesResult.fromResponse(response);
          allResults.add(
              new KytheGetKytheEntriesResult(result.entries, result.files));
        }
      }
      //
      // Return the result.
      //
      ResultMerger merger = new ResultMerger();
      KytheGetKytheEntriesResult mergedResults =
          merger.mergeKytheEntries(allResults);
      if (mergedResults == null) {
        server.sendResponse(
            new KytheGetKytheEntriesResult(<KytheEntry>[], <String>[])
                .toResponse(request.id));
      } else {
        server.sendResponse(new KytheGetKytheEntriesResult(
                mergedResults.entries, mergedResults.files)
            .toResponse(request.id));
      }
    }
  }

  @override
  Response handleRequest(Request request) {
    try {
      String requestName = request.method;
      if (requestName == KYTHE_REQUEST_GET_KYTHE_ENTRIES) {
        getKytheEntries(request);
        return Response.DELAYED_RESPONSE;
      }
    } on RequestFailure catch (exception) {
      return exception.response;
    }
    return null;
  }
}
