// 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.

library operation.queue;

import 'dart:collection';

import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/operation/operation.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';

/**
 * A queue of operations in an [AnalysisServer].
 */
class ServerOperationQueue {
  final List<Queue<ServerOperation>> _queues = <Queue<ServerOperation>>[];

  ServerOperationQueue() {
    for (int i = 0; i < ServerOperationPriority.COUNT; i++) {
      var queue = new DoubleLinkedQueue<ServerOperation>();
      _queues.add(queue);
    }
  }

  /**
   * Returns `true` if there are no queued [ServerOperation]s.
   */
  bool get isEmpty {
    return _queues.every((queue) => queue.isEmpty);
  }

  /**
   * Adds the given operation to this queue. The exact position in the queue
   * depends on the priority of the given operation relative to the priorities
   * of the other operations in the queue.
   */
  void add(ServerOperation operation) {
    int queueIndex = operation.priority.ordinal;
    Queue<ServerOperation> queue = _queues[queueIndex];
    queue.addLast(operation);
  }

  /**
   * Removes all elements in the queue.
   */
  void clear() {
    for (Queue<ServerOperation> queue in _queues) {
      queue.clear();
    }
  }

  /**
   * The given [context] has been removed, so all pending operations that refer
   * to it should be removed from the queue.
   */
  void contextRemoved(AnalysisContext context) {
    for (Queue<ServerOperation> queue in _queues) {
      queue.removeWhere((operation) => operation.context == context);
    }
  }

  /**
   * Return the next operation to perform, or `null` if the queue is empty.
   * This method does not change the queue.
   */
  ServerOperation peek() {
    for (Queue<ServerOperation> queue in _queues) {
      if (!queue.isEmpty) {
        return queue.first;
      }
    }
    return null;
  }

  /**
   * Reschedules queued operations according their current priorities.
   */
  void reschedule() {
    // prepare all operations
    List<ServerOperation> operations = <ServerOperation>[];
    for (Queue<ServerOperation> queue in _queues) {
      operations.addAll(queue);
      queue.clear();
    }
    // add all operations
    operations.forEach(add);
  }

  /**
   * The given [source] if about to changed.
   */
  void sourceAboutToChange(Source source) {
    for (Queue<ServerOperation> queue in _queues) {
      queue.removeWhere((operation) {
        if (operation is SourceSensitiveOperation) {
          return operation.shouldBeDiscardedOnSourceChange(source);
        }
        return false;
      });
    }
  }

  /**
   * Returns the next operation to perform or `null` if empty.
   */
  ServerOperation take() {
    for (Queue<ServerOperation> queue in _queues) {
      if (!queue.isEmpty) {
        return queue.removeFirst();
      }
    }
    return null;
  }

  /**
   * Returns an operation that satisfies the given [test] or `null`.
   */
  ServerOperation takeIf(bool test(ServerOperation operation)) {
    for (Queue<ServerOperation> queue in _queues) {
      for (var operation in queue) {
        if (test(operation)) {
          queue.remove(operation);
          return operation;
        }
      }
    }
    return null;
  }
}
