// Copyright (C) 2012 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.changes;

import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwtorm.client.KeyUtil;

import java.util.Set;

/** List of changes available from {@code /changes/}. */
public class ChangeList extends JsArray<ChangeInfo> {
  private static final String URI = "/changes/";

  /** Run multiple queries in a single remote invocation. */
  public static void queryMultiple(
      final AsyncCallback<JsArray<ChangeList>> callback,
      Set<ListChangesOption> options,
      String... queries) {
    if (queries.length == 0) {
      return;
    }
    RestApi call = new RestApi(URI);
    for (String q : queries) {
      call.addParameterRaw("q", KeyUtil.encode(q));
    }
    addOptions(call, options);
    if (queries.length == 1) {
      // Server unwraps a single query, so wrap it back in an array for the
      // callback.
      call.get(new AsyncCallback<ChangeList>() {
        @Override
        public void onSuccess(ChangeList result) {
          JsArray<ChangeList> wrapped = JsArray.createArray(1).cast();
          wrapped.set(0, result);
          callback.onSuccess(wrapped);
        }

        @Override
        public void onFailure(Throwable caught) {
          callback.onFailure(caught);
        }
      });
    } else {
      call.get(callback);
    }
  }

  public static void query(String query,
      Set<ListChangesOption> options,
      AsyncCallback<ChangeList> callback) {
    query(query, options, callback, 0, 0);
  }

  public static void query(String query,
      Set<ListChangesOption> options,
      AsyncCallback<ChangeList> callback,
      int start, int limit) {
    RestApi call = newQuery(query);
    if (limit > 0) {
      call.addParameter("n", limit);
    }
    addOptions(call, options);
    if (start != 0) {
      call.addParameter("S", start);
    }
    call.get(callback);
  }

  public static void addOptions(RestApi call, Set<ListChangesOption> s) {
    call.addParameterRaw("O", Integer.toHexString(ListChangesOption.toBits(s)));
  }

  private static RestApi newQuery(String query) {
    RestApi call = new RestApi(URI);
    // The server default is ?q=status:open so don't repeat it.
    if (!"status:open".equals(query) && !"is:open".equals(query)) {
      call.addParameterRaw("q", KeyUtil.encode(query));
    }
    return call;
  }

  protected ChangeList() {
  }
}
