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

import 'package:analysis_server/protocol/protocol_generated.dart' as server;
import 'package:analysis_server/src/channel/channel.dart';
import 'package:analysis_server/src/plugin/result_collector.dart';
import 'package:analysis_server/src/plugin/result_converter.dart';
import 'package:analysis_server/src/plugin/result_merger.dart';
import 'package:analyzer/file_system/file_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;

/**
 * The object used to coordinate the results of notifications from the analysis
 * server and multiple plugins.
 */
class NotificationManager {
  /**
   * The identifier used to identify results from the server.
   */
  static const String serverId = 'server';

  /**
   * The channel used to send notifications to the client.
   */
  final ServerCommunicationChannel channel;

  /**
   * The resource provider used to get the path context.
   */
  final ResourceProvider provider;

  /**
   * A list of the paths of files and directories that are included for analysis.
   */
  List<String> includedPaths = <String>[];

  /**
   * A list of the paths of files and directories that are excluded from
   * analysis.
   */
  List<String> excludedPaths = <String>[];

  /**
   * The current set of subscriptions to which the client has subscribed.
   */
  Map<server.AnalysisService, Set<String>> currentSubscriptions =
      <server.AnalysisService, Set<String>>{};

  /**
   * The collector being used to collect the analysis errors from the plugins.
   */
  ResultCollector<List<AnalysisError>> errors;

  /**
   * The collector being used to collect the folding regions from the plugins.
   */
  ResultCollector<List<FoldingRegion>> folding;

  /**
   * The collector being used to collect the highlight regions from the plugins.
   */
  ResultCollector<List<HighlightRegion>> highlights;

  /**
   * The collector being used to collect the navigation parameters from the
   * plugins.
   */
  ResultCollector<server.AnalysisNavigationParams> navigation;

  /**
   * The collector being used to collect the occurrences from the plugins.
   */
  ResultCollector<List<Occurrences>> occurrences;

  /**
   * The collector being used to collect the outlines from the plugins.
   */
  ResultCollector<List<Outline>> outlines;

  /**
   * The object used to convert results.
   */
  final ResultConverter converter = new ResultConverter();

  /**
   * The object used to merge results.
   */
  final ResultMerger merger = new ResultMerger();

  /**
   * Initialize a newly created notification manager.
   */
  NotificationManager(this.channel, this.provider) {
    errors = new ResultCollector<List<AnalysisError>>(serverId,
        predicate: _isIncluded);
    folding = new ResultCollector<List<FoldingRegion>>(serverId);
    highlights = new ResultCollector<List<HighlightRegion>>(serverId);
    navigation = new ResultCollector<server.AnalysisNavigationParams>(serverId);
    occurrences = new ResultCollector<List<Occurrences>>(serverId);
    outlines = new ResultCollector<List<Outline>>(serverId);
  }

  /**
   * Handle the given [notification] from the plugin with the given [pluginId].
   */
  void handlePluginNotification(
      String pluginId, plugin.Notification notification) {
    String event = notification.event;
    switch (event) {
      case plugin.ANALYSIS_NOTIFICATION_ERRORS:
        plugin.AnalysisErrorsParams params =
            new plugin.AnalysisErrorsParams.fromNotification(notification);
        recordAnalysisErrors(pluginId, params.file, params.errors);
        break;
      case plugin.ANALYSIS_NOTIFICATION_FOLDING:
        plugin.AnalysisFoldingParams params =
            new plugin.AnalysisFoldingParams.fromNotification(notification);
        recordFoldingRegions(pluginId, params.file, params.regions);
        break;
      case plugin.ANALYSIS_NOTIFICATION_HIGHLIGHTS:
        plugin.AnalysisHighlightsParams params =
            new plugin.AnalysisHighlightsParams.fromNotification(notification);
        recordHighlightRegions(pluginId, params.file, params.regions);
        break;
      case plugin.ANALYSIS_NOTIFICATION_NAVIGATION:
        plugin.AnalysisNavigationParams params =
            new plugin.AnalysisNavigationParams.fromNotification(notification);
        recordNavigationParams(pluginId, params.file,
            converter.convertAnalysisNavigationParams(params));
        break;
      case plugin.ANALYSIS_NOTIFICATION_OCCURRENCES:
        plugin.AnalysisOccurrencesParams params =
            new plugin.AnalysisOccurrencesParams.fromNotification(notification);
        recordOccurrences(pluginId, params.file, params.occurrences);
        break;
      case plugin.ANALYSIS_NOTIFICATION_OUTLINE:
        plugin.AnalysisOutlineParams params =
            new plugin.AnalysisOutlineParams.fromNotification(notification);
        recordOutlines(pluginId, params.file, params.outline);
        break;
      case plugin.PLUGIN_NOTIFICATION_ERROR:
        plugin.PluginErrorParams params =
            new plugin.PluginErrorParams.fromNotification(notification);
        // TODO(brianwilkerson) There is no indication for the client as to the
        // fact that the error came from a plugin, let alone which plugin it
        // came from. We should consider whether we really want to send them to
        // the client.
        channel.sendNotification(new server.ServerErrorParams(
                params.isFatal, params.message, params.stackTrace)
            .toNotification());
        break;
    }
  }

  /**
   * Record error information from the plugin with the given [pluginId] for the
   * file with the given [filePath].
   */
  void recordAnalysisErrors(
      String pluginId, String filePath, List<AnalysisError> errorData) {
    if (errors.isCollectingFor(filePath)) {
      errors.putResults(filePath, pluginId, errorData);
      List<List<AnalysisError>> unmergedErrors = errors.getResults(filePath);
      List<AnalysisError> mergedErrors =
          merger.mergeAnalysisErrors(unmergedErrors);
      channel.sendNotification(
          new server.AnalysisErrorsParams(filePath, mergedErrors)
              .toNotification());
    }
  }

  /**
   * Record folding information from the plugin with the given [pluginId] for
   * the file with the given [filePath].
   */
  void recordFoldingRegions(
      String pluginId, String filePath, List<FoldingRegion> foldingData) {
    if (folding.isCollectingFor(filePath)) {
      folding.putResults(filePath, pluginId, foldingData);
      List<List<FoldingRegion>> unmergedFolding = folding.getResults(filePath);
      List<FoldingRegion> mergedFolding =
          merger.mergeFoldingRegions(unmergedFolding);
      channel.sendNotification(
          new server.AnalysisFoldingParams(filePath, mergedFolding)
              .toNotification());
    }
  }

  /**
   * Record highlight information from the plugin with the given [pluginId] for
   * the file with the given [filePath].
   */
  void recordHighlightRegions(
      String pluginId, String filePath, List<HighlightRegion> highlightData) {
    if (highlights.isCollectingFor(filePath)) {
      highlights.putResults(filePath, pluginId, highlightData);
      List<List<HighlightRegion>> unmergedHighlights =
          highlights.getResults(filePath);
      List<HighlightRegion> mergedHighlights =
          merger.mergeHighlightRegions(unmergedHighlights);
      channel.sendNotification(
          new server.AnalysisHighlightsParams(filePath, mergedHighlights)
              .toNotification());
    }
  }

  /**
   * Record navigation information from the plugin with the given [pluginId] for
   * the file with the given [filePath].
   */
  void recordNavigationParams(String pluginId, String filePath,
      server.AnalysisNavigationParams navigationData) {
    if (navigation.isCollectingFor(filePath)) {
      navigation.putResults(filePath, pluginId, navigationData);
      List<server.AnalysisNavigationParams> unmergedNavigations =
          navigation.getResults(filePath);
      server.AnalysisNavigationParams mergedNavigations =
          merger.mergeNavigation(unmergedNavigations);
      channel.sendNotification(mergedNavigations.toNotification());
    }
  }

  /**
   * Record occurrences information from the plugin with the given [pluginId]
   * for the file with the given [filePath].
   */
  void recordOccurrences(
      String pluginId, String filePath, List<Occurrences> occurrencesData) {
    if (occurrences.isCollectingFor(filePath)) {
      occurrences.putResults(filePath, pluginId, occurrencesData);
      List<List<Occurrences>> unmergedOccurrences =
          occurrences.getResults(filePath);
      List<Occurrences> mergedOccurrences =
          merger.mergeOccurrences(unmergedOccurrences);
      channel.sendNotification(
          new server.AnalysisOccurrencesParams(filePath, mergedOccurrences)
              .toNotification());
    }
  }

  /**
   * Record outline information from the plugin with the given [pluginId] for
   * the file with the given [filePath].
   */
  void recordOutlines(
      String pluginId, String filePath, List<Outline> outlineData) {
    if (outlines.isCollectingFor(filePath)) {
      outlines.putResults(filePath, pluginId, outlineData);
      List<List<Outline>> unmergedOutlines = outlines.getResults(filePath);
      List<Outline> mergedOutlines = merger.mergeOutline(unmergedOutlines);
      channel.sendNotification(new server.AnalysisOutlineParams(
              filePath, server.FileKind.LIBRARY, mergedOutlines[0])
          .toNotification());
    }
  }

  /**
   * Set the lists of [included] and [excluded] files.
   */
  void setAnalysisRoots(List<String> included, List<String> excluded) {
    includedPaths = included;
    excludedPaths = excluded;
  }

  /**
   * Set the current subscriptions to the given set of [newSubscriptions].
   */
  void setSubscriptions(
      Map<server.AnalysisService, Set<String>> newSubscriptions) {
    /**
     * Return the collector associated with the given service, or `null` if the
     * service is not handled by this manager.
     */
    ResultCollector collectorFor(server.AnalysisService service) {
      switch (service) {
        case server.AnalysisService.FOLDING:
          return folding;
        case server.AnalysisService.HIGHLIGHTS:
          return highlights;
        case server.AnalysisService.NAVIGATION:
          return navigation;
        case server.AnalysisService.OCCURRENCES:
          return occurrences;
        case server.AnalysisService.OUTLINE:
          return outlines;
      }
      return null;
    }

    Set<server.AnalysisService> services =
        new HashSet<server.AnalysisService>();
    services.addAll(currentSubscriptions.keys);
    services.addAll(newSubscriptions.keys);
    services.forEach((server.AnalysisService service) {
      ResultCollector collector = collectorFor(service);
      if (collector != null) {
        Set<String> currentPaths = currentSubscriptions[service];
        Set<String> newPaths = newSubscriptions[service];
        if (currentPaths == null) {
          if (newPaths == null) {
            // This should not happen.
            return;
          }
          // All of the [newPaths] need to be added.
          newPaths.forEach((String filePath) {
            collector.startCollectingFor(filePath);
          });
        } else if (newPaths == null) {
          // All of the [currentPaths] need to be removed.
          currentPaths.forEach((String filePath) {
            collector.stopCollectingFor(filePath);
          });
        } else {
          // Compute the difference of the two sets.
          newPaths.forEach((String filePath) {
            if (!currentPaths.contains(filePath)) {
              collector.startCollectingFor(filePath);
            }
          });
          currentPaths.forEach((String filePath) {
            if (!newPaths.contains(filePath)) {
              collector.stopCollectingFor(filePath);
            }
          });
        }
      }
    });
    currentSubscriptions = newSubscriptions;
  }

  /**
   * Return `true` if errors should be collected for the file with the given
   * [path] (because it is being analyzed).
   */
  bool _isIncluded(String path) {
    bool isIncluded() {
      for (String includedPath in includedPaths) {
        if (provider.pathContext.isWithin(includedPath, path) ||
            provider.pathContext.equals(includedPath, path)) {
          return true;
        }
      }
      return false;
    }

    bool isExcluded() {
      for (String excludedPath in excludedPaths) {
        if (provider.pathContext.isWithin(excludedPath, path)) {
          return true;
        }
      }
      return false;
    }

    // TODO(brianwilkerson) Return false if error notifications are globally
    // disabled.
    return isIncluded() && !isExcluded();
  }
}
