/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "core/editing/spellcheck/SpellCheckRequester.h"

#include "core/dom/Document.h"
#include "core/dom/Node.h"
#include "core/dom/TaskRunnerHelper.h"
#include "core/editing/EditingUtilities.h"
#include "core/editing/markers/DocumentMarkerController.h"
#include "core/editing/spellcheck/SpellChecker.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/html/TextControlElement.h"
#include "platform/text/TextCheckerClient.h"

namespace blink {

SpellCheckRequest::SpellCheckRequest(Range* checking_range,
                                     const String& text,
                                     int request_number)
    : requester_(nullptr),
      checking_range_(checking_range),
      root_editable_element_(
          blink::RootEditableElement(*checking_range_->startContainer())),
      request_data_(text),
      request_number_(request_number) {
  DCHECK(checking_range_);
  DCHECK(checking_range_->IsConnected());
  DCHECK(root_editable_element_);
}

SpellCheckRequest::~SpellCheckRequest() {}

DEFINE_TRACE(SpellCheckRequest) {
  visitor->Trace(requester_);
  visitor->Trace(checking_range_);
  visitor->Trace(root_editable_element_);
  TextCheckingRequest::Trace(visitor);
}

void SpellCheckRequest::Dispose() {
  if (checking_range_)
    checking_range_->Dispose();
}

// static
SpellCheckRequest* SpellCheckRequest::Create(
    const EphemeralRange& checking_range,
    int request_number) {
  if (checking_range.IsNull())
    return nullptr;
  if (!blink::RootEditableElement(
          *checking_range.StartPosition().ComputeContainerNode()))
    return nullptr;

  String text =
      PlainText(checking_range, TextIteratorBehavior::Builder()
                                    .SetEmitsObjectReplacementCharacter(true)
                                    .Build());
  if (text.IsEmpty())
    return nullptr;

  Range* checking_range_object = CreateRange(checking_range);

  return new SpellCheckRequest(checking_range_object, text, request_number);
}

const TextCheckingRequestData& SpellCheckRequest::Data() const {
  return request_data_;
}

bool SpellCheckRequest::IsValid() const {
  return checking_range_->IsConnected() &&
         root_editable_element_->isConnected();
}

void SpellCheckRequest::DidSucceed(const Vector<TextCheckingResult>& results) {
  if (!requester_)
    return;
  SpellCheckRequester* requester = requester_;
  requester_ = nullptr;
  requester->DidCheckSucceed(request_data_.Sequence(), results);
}

void SpellCheckRequest::DidCancel() {
  if (!requester_)
    return;
  SpellCheckRequester* requester = requester_;
  requester_ = nullptr;
  requester->DidCheckCancel(request_data_.Sequence());
}

void SpellCheckRequest::SetCheckerAndSequence(SpellCheckRequester* requester,
                                              int sequence) {
  DCHECK(!requester_);
  DCHECK_EQ(request_data_.Sequence(), kUnrequestedTextCheckingSequence);
  requester_ = requester;
  request_data_.SetSequence(sequence);
}

SpellCheckRequester::SpellCheckRequester(LocalFrame& frame)
    : frame_(&frame),
      last_request_sequence_(0),
      last_processed_sequence_(0),
      timer_to_process_queued_request_(
          TaskRunnerHelper::Get(TaskType::kUnspecedTimer, &frame),
          this,
          &SpellCheckRequester::TimerFiredToProcessQueuedRequest) {}

SpellCheckRequester::~SpellCheckRequester() {}

TextCheckerClient& SpellCheckRequester::Client() const {
  return GetFrame().GetSpellChecker().TextChecker();
}

void SpellCheckRequester::TimerFiredToProcessQueuedRequest(TimerBase*) {
  DCHECK(!request_queue_.IsEmpty());
  if (request_queue_.IsEmpty())
    return;

  InvokeRequest(request_queue_.TakeFirst());
}

void SpellCheckRequester::RequestCheckingFor(const EphemeralRange& range) {
  RequestCheckingFor(range, 0);
}

void SpellCheckRequester::RequestCheckingFor(const EphemeralRange& range,
                                             int request_num) {
  SpellCheckRequest* request = SpellCheckRequest::Create(range, request_num);
  if (!request)
    return;

  DCHECK_EQ(request->Data().Sequence(), kUnrequestedTextCheckingSequence);
  int sequence = ++last_request_sequence_;
  if (sequence == kUnrequestedTextCheckingSequence)
    sequence = ++last_request_sequence_;

  request->SetCheckerAndSequence(this, sequence);

  if (timer_to_process_queued_request_.IsActive() || processing_request_) {
    EnqueueRequest(request);
    return;
  }

  InvokeRequest(request);
}

void SpellCheckRequester::CancelCheck() {
  if (processing_request_)
    processing_request_->DidCancel();
}

void SpellCheckRequester::PrepareForLeakDetection() {
  timer_to_process_queued_request_.Stop();
  // Empty the queue of pending requests to prevent it being a leak source.
  // Pending spell checker requests are cancellable requests not representing
  // leaks, just async work items waiting to be processed.
  //
  // Rather than somehow wait for this async queue to drain before running
  // the leak detector, they're all cancelled to prevent flaky leaks being
  // reported.
  request_queue_.Clear();
  // WebSpellCheckClient stores a set of WebTextCheckingCompletion objects,
  // which may store references to already invoked requests. We should clear
  // these references to prevent them from being a leak source.
  Client().CancelAllPendingRequests();
}

void SpellCheckRequester::InvokeRequest(SpellCheckRequest* request) {
  DCHECK(!processing_request_);
  processing_request_ = request;
  Client().RequestCheckingOfString(processing_request_);
}

void SpellCheckRequester::ClearProcessingRequest() {
  if (!processing_request_)
    return;

  processing_request_->Dispose();
  processing_request_.Clear();
}

void SpellCheckRequester::EnqueueRequest(SpellCheckRequest* request) {
  DCHECK(request);
  bool continuation = false;
  if (!request_queue_.IsEmpty()) {
    SpellCheckRequest* last_request = request_queue_.back();
    // It's a continuation if the number of the last request got incremented in
    // the new one and both apply to the same editable.
    continuation =
        request->RootEditableElement() == last_request->RootEditableElement() &&
        request->RequestNumber() == last_request->RequestNumber() + 1;
  }

  // Spellcheck requests for chunks of text in the same element should not
  // overwrite each other.
  if (!continuation) {
    RequestQueue::const_iterator same_element_request = std::find_if(
        request_queue_.begin(), request_queue_.end(),
        [request](const SpellCheckRequest* queued_request) -> bool {
          return request->RootEditableElement() ==
                 queued_request->RootEditableElement();
        });
    if (same_element_request != request_queue_.end())
      request_queue_.erase(same_element_request);
  }

  request_queue_.push_back(request);
}

void SpellCheckRequester::DidCheck(int sequence,
                                   const Vector<TextCheckingResult>& results) {
  DCHECK(processing_request_);
  DCHECK_EQ(processing_request_->Data().Sequence(), sequence);
  if (processing_request_->Data().Sequence() != sequence) {
    request_queue_.Clear();
    return;
  }

  if (results.size())
    GetFrame().GetSpellChecker().MarkAndReplaceFor(processing_request_,
                                                   results);

  DCHECK_LT(last_processed_sequence_, sequence);
  last_processed_sequence_ = sequence;

  ClearProcessingRequest();
  if (!request_queue_.IsEmpty())
    timer_to_process_queued_request_.StartOneShot(0, BLINK_FROM_HERE);
}

void SpellCheckRequester::DidCheckSucceed(
    int sequence,
    const Vector<TextCheckingResult>& results) {
  // TODO(editing-dev): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  See http://crbug.com/590369 for more details.
  GetFrame().GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();

  TextCheckingRequestData request_data = processing_request_->Data();
  if (request_data.Sequence() == sequence) {
    DocumentMarker::MarkerTypes markers = DocumentMarker::MisspellingMarkers();
    if (processing_request_->IsValid()) {
      Range* checking_range = processing_request_->CheckingRange();
      GetFrame().GetDocument()->Markers().RemoveMarkersInRange(
          EphemeralRange(checking_range), markers);
    }
  }
  DidCheck(sequence, results);
}

void SpellCheckRequester::DidCheckCancel(int sequence) {
  Vector<TextCheckingResult> results;
  DidCheck(sequence, results);
}

DEFINE_TRACE(SpellCheckRequester) {
  visitor->Trace(frame_);
  visitor->Trace(processing_request_);
  visitor->Trace(request_queue_);
}

}  // namespace blink
