// Copyright (c) 2014, 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/protocol/protocol_constants.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/generated/source.dart';

/// Instances of the class [ExecutionDomainHandler] implement a [RequestHandler]
/// that handles requests in the `execution` domain.
class ExecutionDomainHandler implements RequestHandler {
  /// The analysis server that is using this handler to process requests.
  final AnalysisServer server;

  /// The next execution context identifier to be returned.
  int nextContextId = 0;

  /// A table mapping execution context id's to the root of the context.
  final Map<String, String> contextMap = HashMap<String, String>();

  /// Initialize a newly created handler to handle requests for the given
  /// [server].
  ExecutionDomainHandler(this.server);

  /// Implement the `execution.createContext` request.
  Response createContext(Request request) {
    var file = ExecutionCreateContextParams.fromRequest(request).contextRoot;
    var contextId = (nextContextId++).toString();
    contextMap[contextId] = file;
    return ExecutionCreateContextResult(contextId).toResponse(request.id);
  }

  /// Implement the `execution.deleteContext` request.
  Response deleteContext(Request request) {
    var contextId = ExecutionDeleteContextParams.fromRequest(request).id;
    contextMap.remove(contextId);
    return ExecutionDeleteContextResult().toResponse(request.id);
  }

  /// Implement the 'execution.getSuggestions' request.
  void getSuggestions(Request request) async {
//    var params = new ExecutionGetSuggestionsParams.fromRequest(request);
//    var computer = new RuntimeCompletionComputer(
//        server.resourceProvider,
//        server.fileContentOverlay,
//        server.getAnalysisDriver(params.contextFile),
//        params.code,
//        params.offset,
//        params.contextFile,
//        params.contextOffset,
//        params.variables,
//        params.expressions);
//    RuntimeCompletionResult completionResult = await computer.compute();
//
//    // Send the response.
//    var result = new ExecutionGetSuggestionsResult(
//        suggestions: completionResult.suggestions,
//        expressions: completionResult.expressions);
    // TODO(brianwilkerson) Re-enable this functionality after implementing a
    // way of computing suggestions that is compatible with AnalysisSession.
    var result = ExecutionGetSuggestionsResult(
        suggestions: <CompletionSuggestion>[],
        expressions: <RuntimeCompletionExpression>[]);
    server.sendResponse(result.toResponse(request.id));
  }

  @override
  Response? handleRequest(Request request) {
    try {
      var requestName = request.method;
      if (requestName == EXECUTION_REQUEST_CREATE_CONTEXT) {
        return createContext(request);
      } else if (requestName == EXECUTION_REQUEST_DELETE_CONTEXT) {
        return deleteContext(request);
      } else if (requestName == EXECUTION_REQUEST_GET_SUGGESTIONS) {
        getSuggestions(request);
        return Response.DELAYED_RESPONSE;
      } else if (requestName == EXECUTION_REQUEST_MAP_URI) {
        return mapUri(request);
      } else if (requestName == EXECUTION_REQUEST_SET_SUBSCRIPTIONS) {
        return setSubscriptions(request);
      }
    } on RequestFailure catch (exception) {
      return exception.response;
    }
    return null;
  }

  /// Implement the 'execution.mapUri' request.
  Response mapUri(Request request) {
    var params = ExecutionMapUriParams.fromRequest(request);
    var contextId = params.id;
    var path = contextMap[contextId];
    if (path == null) {
      return Response.invalidParameter(request, 'id',
          'There is no execution context with an id of $contextId');
    }

    var driver = server.getAnalysisDriver(path);
    if (driver == null) {
      return Response.invalidExecutionContext(request, contextId);
    }
    var sourceFactory = driver.sourceFactory;

    var file = params.file;
    var uri = params.uri;
    if (file != null) {
      if (uri != null) {
        return Response.invalidParameter(request, 'file',
            'Either file or uri must be provided, but not both');
      }
      var resource = server.resourceProvider.getResource(file);
      if (!resource.exists) {
        return Response.invalidParameter(request, 'file', 'Must exist');
      } else if (resource is! File) {
        return Response.invalidParameter(
            request, 'file', 'Must not refer to a directory');
      }

      var source = driver.fsState.getFileForPath(file).source;
      if (source.uriKind != UriKind.FILE_URI) {
        uri = source.uri.toString();
      } else {
        uri = sourceFactory.restoreUri(source).toString();
      }
      return ExecutionMapUriResult(uri: uri).toResponse(request.id);
    } else if (uri != null) {
      var source = sourceFactory.forUri(uri);
      if (source == null) {
        return Response.invalidParameter(request, 'uri', 'Invalid URI');
      }
      file = source.fullName;
      return ExecutionMapUriResult(file: file).toResponse(request.id);
    }
    return Response.invalidParameter(
        request, 'file', 'Either file or uri must be provided');
  }

  /// Implement the 'execution.setSubscriptions' request.
  Response setSubscriptions(Request request) {
    // Under the analysis driver, setSubscriptions() becomes a no-op.
    return ExecutionSetSubscriptionsResult().toResponse(request.id);
  }
}
