// Copyright (C) 2010 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.client.ui;

import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.SuggestOracle;

/**
 * Delegates to a slow SuggestOracle, such as a remote server API.
 *
 * <p>A response is only supplied to the UI if no requests were made after the oracle begin that
 * request.
 *
 * <p>When a request is made while the delegate is still processing a prior request all intermediate
 * requests are discarded and the most recent request is queued. The pending request's response is
 * discarded and the most recent request is started.
 */
public class RemoteSuggestOracle extends SuggestOracle {
  private final SuggestOracle oracle;
  private Query query;
  private String last;
  private Timer requestRetentionTimer;
  private boolean cancelOutstandingRequest;

  private boolean serveSuggestions;

  public RemoteSuggestOracle(SuggestOracle src) {
    oracle = src;
  }

  public String getLast() {
    return last;
  }

  @Override
  public void requestSuggestions(Request req, Callback cb) {
    if (!serveSuggestions) {
      return;
    }

    // Use a timer for key stroke retention, such that we don't query the
    // backend for each and every keystroke we receive.
    if (requestRetentionTimer != null) {
      requestRetentionTimer.cancel();
    }
    requestRetentionTimer =
        new Timer() {
          @Override
          public void run() {
            Query q = new Query(req, cb);
            if (query == null) {
              query = q;
              q.start();
            } else {
              query = q;
            }
          }
        };
    requestRetentionTimer.schedule(200);
  }

  @Override
  public void requestDefaultSuggestions(Request req, Callback cb) {
    requestSuggestions(req, cb);
  }

  @Override
  public boolean isDisplayStringHTML() {
    return oracle.isDisplayStringHTML();
  }

  public void cancelOutstandingRequest() {
    if (requestRetentionTimer != null) {
      requestRetentionTimer.cancel();
    }
    if (query != null) {
      cancelOutstandingRequest = true;
    }
  }

  public void setServeSuggestions(boolean serveSuggestions) {
    this.serveSuggestions = serveSuggestions;
  }

  private class Query implements Callback {
    final Request request;
    final Callback callback;

    Query(Request req, Callback cb) {
      request = req;
      callback = cb;
    }

    void start() {
      if (request.getQuery() == null) {
        request.setQuery("");
      }
      oracle.requestSuggestions(request, this);
    }

    @Override
    public void onSuggestionsReady(Request req, Response res) {
      if (cancelOutstandingRequest || !serveSuggestions) {
        // If cancelOutstandingRequest() was called, we ignore this response
        cancelOutstandingRequest = false;
        query = null;
      } else if (query == this) {
        // No new request was started while this query was running.
        // Propose this request's response as the suggestions.
        query = null;
        last = request.getQuery();
        callback.onSuggestionsReady(req, res);
      } else {
        // Another query came in while this one was running. Skip
        // this response and start the most recent query.
        query.start();
      }
    }
  }
}

@@ -2998,86 +2998,8 @@
 ) %7B%0A
-      if (request.getQuery() == null) %7B%0A        request.setQuery(%22%22);%0A      %7D%0A
     

Revert "Fix GWT UI AddFileBox to provide path suggestions continuously"