// Copyright (c) 2015, 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.

library analysis_server.src.plugin.server_plugin;

import 'package:analysis_server/plugin/analysis/analysis_domain.dart';
import 'package:analysis_server/plugin/analysis/analyzed_files.dart';
import 'package:analysis_server/plugin/analysis/navigation/navigation.dart';
import 'package:analysis_server/plugin/analysis/navigation/navigation_core.dart';
import 'package:analysis_server/plugin/analysis/occurrences/occurrences.dart';
import 'package:analysis_server/plugin/analysis/occurrences/occurrences_core.dart';
import 'package:analysis_server/plugin/edit/assist/assist.dart';
import 'package:analysis_server/plugin/edit/assist/assist_core.dart';
import 'package:analysis_server/plugin/edit/fix/fix.dart';
import 'package:analysis_server/plugin/edit/fix/fix_core.dart';
import 'package:analysis_server/plugin/index/index.dart';
import 'package:analysis_server/plugin/index/index_core.dart';
import 'package:analysis_server/plugin/protocol/protocol.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/domain_analysis.dart';
import 'package:analysis_server/src/domain_completion.dart';
import 'package:analysis_server/src/domain_execution.dart';
import 'package:analysis_server/src/domain_experimental.dart';
import 'package:analysis_server/src/domain_server.dart';
import 'package:analysis_server/src/domains/analysis/navigation_dart.dart';
import 'package:analysis_server/src/domains/analysis/occurrences_dart.dart';
import 'package:analysis_server/src/edit/edit_domain.dart';
import 'package:analysis_server/src/provisional/completion/completion_core.dart';
import 'package:analysis_server/src/search/search_domain.dart';
import 'package:analysis_server/src/services/correction/assist_internal.dart';
import 'package:analysis_server/src/services/correction/fix_internal.dart';
import 'package:analysis_server/src/services/index/index_contributor.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:plugin/plugin.dart';

/**
 * A function that will create a request handler that can be used by the given
 * [server].
 */
typedef RequestHandler RequestHandlerFactory(AnalysisServer server);

/**
 * A plugin that defines the extension points and extensions that are inherently
 * defined by the analysis server.
 */
class ServerPlugin implements Plugin {
  /**
   * The simple identifier of the extension point that allows plugins to
   * register file patterns that will cause files to be analyzed.
   */
  static const String ANALYZED_FILE_PATTERNS_EXTENSION_POINT =
      'analyzedFilePatterns';

  /**
   * The simple identifier of the extension point that allows plugins to
   * register assist contributors.
   */
  static const String ASSIST_CONTRIBUTOR_EXTENSION_POINT = 'assistContributor';

  /**
   * The simple identifier of the extension point that allows plugins to
   * register completion contributors.
   */
  static const String COMPLETION_CONTRIBUTOR_EXTENSION_POINT =
      'completionContributor';

  /**
   * The simple identifier of the extension point that allows plugins to
   * register domains.
   */
  static const String DOMAIN_EXTENSION_POINT = 'domain';

  /**
   * The simple identifier of the extension point that allows plugins to
   * register fix contributors.
   */
  static const String FIX_CONTRIBUTOR_EXTENSION_POINT = 'fixContributor';

  /**
   * The simple identifier of the extension point that allows plugins to
   * register index contributors.
   */
  static const String INDEX_CONTRIBUTOR_EXTENSION_POINT = 'indexContributor';

  /**
   * The simple identifier of the extension point that allows plugins to
   * register navigation contributors.
   */
  static const String NAVIGATION_CONTRIBUTOR_EXTENSION_POINT =
      'navigationContributor';

  /**
   * The simple identifier of the extension point that allows plugins to
   * register element occurrences.
   */
  static const String OCCURRENCES_CONTRIBUTOR_EXTENSION_POINT =
      'occurrencesContributor';

  /**
   * The simple identifier of the extension point that allows plugins to
   * register analysis result listeners.
   */
  static const String SET_ANALISYS_DOMAIN_EXTENSION_POINT = 'setAnalysisDomain';

  /**
   * The unique identifier of this plugin.
   */
  static const String UNIQUE_IDENTIFIER = 'analysis_server.core';

  /**
   * The extension point that allows plugins to register file patterns that will
   * cause files to be analyzed.
   */
  ExtensionPoint analyzedFilePatternsExtensionPoint;

  /**
   * The extension point that allows plugins to register assist contributors.
   */
  ExtensionPoint assistContributorExtensionPoint;

  /**
   * The extension point that allows plugins to register completion
   * contributors.
   */
  ExtensionPoint completionContributorExtensionPoint;

  /**
   * The extension point that allows plugins to register domains with the
   * server.
   */
  ExtensionPoint domainExtensionPoint;

  /**
   * The extension point that allows plugins to register fix contributors with
   * the server.
   */
  ExtensionPoint fixContributorExtensionPoint;

  /**
   * The extension point that allows plugins to register index contributors.
   */
  ExtensionPoint indexContributorExtensionPoint;

  /**
   * The extension point that allows plugins to register navigation
   * contributors.
   */
  ExtensionPoint navigationContributorExtensionPoint;

  /**
   * The extension point that allows plugins to register occurrences
   * contributors.
   */
  ExtensionPoint occurrencesContributorExtensionPoint;

  /**
   * The extension point that allows plugins to get access to the `analysis`
   * domain.
   */
  ExtensionPoint setAnalysisDomainExtensionPoint;

  /**
   * Initialize a newly created plugin.
   */
  ServerPlugin();

  /**
   * Return a list containing all of the file patterns that can cause files to
   * be analyzed.
   */
  List<String> get analyzedFilePatterns {
    List<String> patterns = <String>[];
    for (List<String> extension
        in analyzedFilePatternsExtensionPoint.extensions) {
      patterns.addAll(extension);
    }
    return patterns;
  }

  /**
   * Return a list containing all of the assist contributors that were
   * contributed.
   */
  List<AssistContributor> get assistContributors =>
      assistContributorExtensionPoint.extensions;

  /**
   * Return a list containing all of the completion contributors that were
   * contributed.
   */
  List<CompletionContributor> get completionContributors =>
      completionContributorExtensionPoint.extensions;

  /**
   * Return a list containing all of the fix contributors that were contributed.
   */
  List<FixContributor> get fixContributors =>
      fixContributorExtensionPoint.extensions;

  /**
   * Return a list containing all of the index contributors that were
   * contributed.
   */
  List<IndexContributor> get indexContributors =>
      indexContributorExtensionPoint.extensions;

  /**
   * Return a list containing all of the navigation contributors that were
   * contributed.
   */
  List<NavigationContributor> get navigationContributors =>
      navigationContributorExtensionPoint.extensions;

  /**
   * Return a list containing all of the occurrences contributors that were
   * contributed.
   */
  List<OccurrencesContributor> get occurrencesContributors =>
      occurrencesContributorExtensionPoint.extensions;

  /**
   * Return a list containing all of the receivers of the `analysis` domain
   * instance.
   */
  List<SetAnalysisDomain> get setAnalysisDomainFunctions =>
      setAnalysisDomainExtensionPoint.extensions;

  @override
  String get uniqueIdentifier => UNIQUE_IDENTIFIER;

  /**
   * Use the given [server] to create all of the domains ([RequestHandler]'s)
   * that have been registered and return the newly created domains.
   */
  List<RequestHandler> createDomains(AnalysisServer server) {
    if (domainExtensionPoint == null) {
      return <RequestHandler>[];
    }
    return domainExtensionPoint.extensions
        .map((RequestHandlerFactory factory) => factory(server))
        .toList();
  }

  @override
  void registerExtensionPoints(RegisterExtensionPoint registerExtensionPoint) {
    setAnalysisDomainExtensionPoint = registerExtensionPoint(
        SET_ANALISYS_DOMAIN_EXTENSION_POINT,
        _validateSetAnalysisDomainFunction);
    analyzedFilePatternsExtensionPoint = registerExtensionPoint(
        ANALYZED_FILE_PATTERNS_EXTENSION_POINT,
        _validateAnalyzedFilePatternsExtension);
    assistContributorExtensionPoint = registerExtensionPoint(
        ASSIST_CONTRIBUTOR_EXTENSION_POINT,
        _validateAssistContributorExtension);
    completionContributorExtensionPoint = registerExtensionPoint(
        COMPLETION_CONTRIBUTOR_EXTENSION_POINT,
        _validateCompletionContributorExtension);
    domainExtensionPoint = registerExtensionPoint(
        DOMAIN_EXTENSION_POINT, _validateDomainExtension);
    fixContributorExtensionPoint = registerExtensionPoint(
        FIX_CONTRIBUTOR_EXTENSION_POINT, _validateFixContributorExtension);
    indexContributorExtensionPoint = registerExtensionPoint(
        INDEX_CONTRIBUTOR_EXTENSION_POINT, _validateIndexContributorExtension);
    navigationContributorExtensionPoint = registerExtensionPoint(
        NAVIGATION_CONTRIBUTOR_EXTENSION_POINT,
        _validateNavigationContributorExtension);
    occurrencesContributorExtensionPoint = registerExtensionPoint(
        OCCURRENCES_CONTRIBUTOR_EXTENSION_POINT,
        _validateOccurrencesContributorExtension);
  }

  @override
  void registerExtensions(RegisterExtension registerExtension) {
    //
    // Register analyzed file patterns.
    //
    List<String> patterns = <String>[
      '{*:/,/}**/*.${AnalysisEngine.SUFFIX_DART}',
      '{*:/,/}**/*.${AnalysisEngine.SUFFIX_HTML}',
      '{*:/,/}**/*.${AnalysisEngine.SUFFIX_HTM}',
      '{*:/,/}**/${AnalysisEngine.ANALYSIS_OPTIONS_FILE}'
    ];
    registerExtension(ANALYZED_FILE_PATTERNS_EXTENSION_POINT_ID, patterns);
    //
    // Register assist contributors.
    //
    registerExtension(
        ASSIST_CONTRIBUTOR_EXTENSION_POINT_ID, new DefaultAssistContributor());
    //
    // Register completion contributors.
    //
    // TODO(brianwilkerson) Register the completion contributors.
//    registerExtension(COMPLETION_CONTRIBUTOR_EXTENSION_POINT_ID, ???);
    //
    // Register analysis contributors.
    //
    registerExtension(NAVIGATION_CONTRIBUTOR_EXTENSION_POINT_ID,
        new DartNavigationComputer());
    registerExtension(OCCURRENCES_CONTRIBUTOR_EXTENSION_POINT_ID,
        new DartOccurrencesComputer());
    //
    // Register domains.
    //
    String domainId = Plugin.join(UNIQUE_IDENTIFIER, DOMAIN_EXTENSION_POINT);
    registerExtension(
        domainId, (AnalysisServer server) => new ServerDomainHandler(server));
    registerExtension(
        domainId, (AnalysisServer server) => new AnalysisDomainHandler(server));
    registerExtension(
        domainId, (AnalysisServer server) => new EditDomainHandler(server));
    registerExtension(
        domainId, (AnalysisServer server) => new SearchDomainHandler(server));
    registerExtension(domainId,
        (AnalysisServer server) => new CompletionDomainHandler(server));
    registerExtension(domainId,
        (AnalysisServer server) => new ExecutionDomainHandler(server));
    registerExtension(domainId,
        (AnalysisServer server) => new ExperimentalDomainHandler(server));
    //
    // Register fix contributors.
    //
    registerExtension(
        FIX_CONTRIBUTOR_EXTENSION_POINT_ID, new DefaultFixContributor());
    //
    // Register index contributors.
    //
    registerExtension(
        INDEX_CONTRIBUTOR_EXTENSION_POINT_ID, new DartIndexContributor());
  }

  /**
   * Return `true` if the list being used as an [extension] contains any
   * elements that are not strings.
   */
  bool _containsNonString(List extension) {
    for (Object element in extension) {
      if (element is! String) {
        return true;
      }
    }
    return false;
  }

  /**
   * Validate the given extension by throwing an [ExtensionError] if it is not a
   * valid list of analyzed file patterns.
   */
  void _validateAnalyzedFilePatternsExtension(Object extension) {
    if (extension is! List || _containsNonString(extension)) {
      String id = analyzedFilePatternsExtensionPoint.uniqueIdentifier;
      throw new ExtensionError('Extensions to $id must be a List of Strings');
    }
  }

  /**
   * Validate the given extension by throwing an [ExtensionError] if it is not a
   * valid assist contributor.
   */
  void _validateAssistContributorExtension(Object extension) {
    if (extension is! AssistContributor) {
      String id = assistContributorExtensionPoint.uniqueIdentifier;
      throw new ExtensionError(
          'Extensions to $id must be an AssistContributor');
    }
  }

  /**
   * Validate the given extension by throwing an [ExtensionError] if it is not a
   * valid completion contributor.
   */
  void _validateCompletionContributorExtension(Object extension) {
    if (extension is! CompletionContributor) {
      String id = completionContributorExtensionPoint.uniqueIdentifier;
      throw new ExtensionError(
          'Extensions to $id must be an CompletionContributor');
    }
  }

  /**
   * Validate the given extension by throwing an [ExtensionError] if it is not a
   * valid domain.
   */
  void _validateDomainExtension(Object extension) {
    if (extension is! RequestHandlerFactory) {
      String id = domainExtensionPoint.uniqueIdentifier;
      throw new ExtensionError(
          'Extensions to $id must be a RequestHandlerFactory');
    }
  }

  /**
   * Validate the given extension by throwing an [ExtensionError] if it is not a
   * valid fix contributor.
   */
  void _validateFixContributorExtension(Object extension) {
    if (extension is! FixContributor) {
      String id = fixContributorExtensionPoint.uniqueIdentifier;
      throw new ExtensionError('Extensions to $id must be a FixContributor');
    }
  }

  /**
   * Validate the given extension by throwing an [ExtensionError] if it is not a
   * valid index contributor.
   */
  void _validateIndexContributorExtension(Object extension) {
    if (extension is! IndexContributor) {
      String id = indexContributorExtensionPoint.uniqueIdentifier;
      throw new ExtensionError('Extensions to $id must be an IndexContributor');
    }
  }

  /**
   * Validate the given extension by throwing an [ExtensionError] if it is not a
   * valid navigation contributor.
   */
  void _validateNavigationContributorExtension(Object extension) {
    if (extension is! NavigationContributor) {
      String id = navigationContributorExtensionPoint.uniqueIdentifier;
      throw new ExtensionError(
          'Extensions to $id must be an NavigationContributor');
    }
  }

  /**
   * Validate the given extension by throwing an [ExtensionError] if it is not a
   * valid occurrences contributor.
   */
  void _validateOccurrencesContributorExtension(Object extension) {
    if (extension is! OccurrencesContributor) {
      String id = occurrencesContributorExtensionPoint.uniqueIdentifier;
      throw new ExtensionError(
          'Extensions to $id must be an OccurrencesContributor');
    }
  }

  /**
   * Validate the given extension by throwing an [ExtensionError] if it is not a
   * valid analysis domain receiver.
   */
  void _validateSetAnalysisDomainFunction(Object extension) {
    if (extension is! SetAnalysisDomain) {
      String id = setAnalysisDomainExtensionPoint.uniqueIdentifier;
      throw new ExtensionError(
          'Extensions to $id must be a SetAnalysisDomain function');
    }
  }
}
