// 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.Gerrit;
import com.google.gerrit.client.info.AccountInfo;
import com.google.gerrit.client.info.ChangeInfo;
import com.google.gerrit.client.info.ChangeInfo.CommitInfo;
import com.google.gerrit.client.info.ChangeInfo.EditInfo;
import com.google.gerrit.client.info.ChangeInfo.IncludedInInfo;
import com.google.gerrit.client.rpc.CallbackGroup.Callback;
import com.google.gerrit.client.rpc.NativeString;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.user.client.rpc.AsyncCallback;

/** A collection of static methods which work on the Gerrit REST API for specific changes. */
public class ChangeApi {
  /** Abandon the change, ending its review. */
  public static void abandon(int id, String msg, AsyncCallback<ChangeInfo> cb) {
    MessageInput input = MessageInput.create();
    input.message(emptyToNull(msg));
    call(id, "abandon").post(input, cb);
  }

  /**
   * Create a new change.
   *
   * <p>The new change is created as DRAFT unless the draft workflow is disabled by
   * `change.allowDrafts = false` in the configuration, in which case the new change is created as
   * NEW.
   */
  public static void createChange(
      String project,
      String branch,
      String topic,
      String subject,
      String base,
      AsyncCallback<ChangeInfo> cb) {
    CreateChangeInput input = CreateChangeInput.create();
    input.project(emptyToNull(project));
    input.branch(emptyToNull(branch));
    input.topic(emptyToNull(topic));
    input.subject(emptyToNull(subject));
    input.baseChange(emptyToNull(base));

    if (Gerrit.info().change().allowDrafts()) {
      input.status(Change.Status.DRAFT.toString());
    }

    new RestApi("/changes/").post(input, cb);
  }

  /** Restore a previously abandoned change to be open again. */
  public static void restore(int id, String msg, AsyncCallback<ChangeInfo> cb) {
    MessageInput input = MessageInput.create();
    input.message(emptyToNull(msg));
    call(id, "restore").post(input, cb);
  }

  /** Create a new change that reverts the delta caused by this change. */
  public static void revert(int id, String msg, AsyncCallback<ChangeInfo> cb) {
    MessageInput input = MessageInput.create();
    input.message(emptyToNull(msg));
    call(id, "revert").post(input, cb);
  }

  /** Update the topic of a change. */
  public static void topic(int id, String topic, AsyncCallback<String> cb) {
    RestApi call = call(id, "topic");
    topic = emptyToNull(topic);
    if (topic != null) {
      TopicInput input = TopicInput.create();
      input.topic(topic);
      call.put(input, NativeString.unwrap(cb));
    } else {
      call.delete(NativeString.unwrap(cb));
    }
  }

  public static void detail(int id, AsyncCallback<ChangeInfo> cb) {
    detail(id).get(cb);
  }

  public static RestApi detail(int id) {
    return call(id, "detail");
  }

  public static RestApi blame(PatchSet.Id id, String path, boolean base) {
    return revision(id).view("files").id(path).view("blame").addParameter("base", base);
  }

  public static RestApi actions(int id, String revision) {
    if (revision == null || revision.equals("")) {
      revision = "current";
    }
    return call(id, revision, "actions");
  }

  public static void deleteAssignee(int id, AsyncCallback<AccountInfo> cb) {
    change(id).view("assignee").delete(cb);
  }

  public static void setAssignee(int id, String user, AsyncCallback<AccountInfo> cb) {
    AssigneeInput input = AssigneeInput.create();
    input.assignee(user);
    change(id).view("assignee").put(input, cb);
  }

  public static RestApi comments(int id) {
    return call(id, "comments");
  }

  public static RestApi drafts(int id) {
    return call(id, "drafts");
  }

  public static void edit(int id, AsyncCallback<EditInfo> cb) {
    edit(id).get(cb);
  }

  public static void editWithFiles(int id, AsyncCallback<EditInfo> cb) {
    edit(id).addParameterTrue("list").get(cb);
  }

  public static RestApi edit(int id) {
    return change(id).view("edit");
  }

  public static RestApi editWithCommands(int id) {
    return edit(id).addParameterTrue("download-commands");
  }

  public static void includedIn(int id, AsyncCallback<IncludedInInfo> cb) {
    call(id, "in").get(cb);
  }

  public static RestApi revision(int id, String revision) {
    return change(id).view("revisions").id(revision);
  }

  public static RestApi revision(PatchSet.Id id) {
    int cn = id.getParentKey().get();
    String revision = RevisionInfoCache.get(id);
    if (revision != null) {
      return revision(cn, revision);
    }
    return change(cn).view("revisions").id(id.get());
  }

  public static RestApi reviewers(int id) {
    return change(id).view("reviewers");
  }

  public static RestApi suggestReviewers(int id, String q, int n, boolean e) {
    RestApi api = change(id).view("suggest_reviewers").addParameter("n", n).addParameter("e", e);
    if (q != null) {
      api.addParameter("q", q);
    }
    return api;
  }

  public static RestApi vote(int id, int reviewer, String vote) {
    return reviewer(id, reviewer).view("votes").id(vote);
  }

  public static RestApi reviewer(int id, int reviewer) {
    return change(id).view("reviewers").id(reviewer);
  }

  public static RestApi reviewer(int id, String reviewer) {
    return change(id).view("reviewers").id(reviewer);
  }

  public static RestApi hashtags(int changeId) {
    return change(changeId).view("hashtags");
  }

  public static RestApi hashtag(int changeId, String hashtag) {
    return change(changeId).view("hashtags").id(hashtag);
  }

  /** Submit a specific revision of a change. */
  public static void cherrypick(
      int id, String commit, String destination, String message, AsyncCallback<ChangeInfo> cb) {
    CherryPickInput cherryPickInput = CherryPickInput.create();
    cherryPickInput.setMessage(message);
    cherryPickInput.setDestination(destination);
    call(id, commit, "cherrypick").post(cherryPickInput, cb);
  }

  /** Edit commit message for specific revision of a change. */
  public static void message(
      int id, String commit, String message, AsyncCallback<JavaScriptObject> cb) {
    CherryPickInput input = CherryPickInput.create();
    input.setMessage(message);
    call(id, commit, "message").post(input, cb);
  }

  /** Submit a specific revision of a change. */
  public static void submit(int id, String commit, AsyncCallback<SubmitInfo> cb) {
    JavaScriptObject in = JavaScriptObject.createObject();
    call(id, commit, "submit").post(in, cb);
  }

  /** Publish a specific revision of a draft change. */
  public static void publish(int id, String commit, AsyncCallback<JavaScriptObject> cb) {
    JavaScriptObject in = JavaScriptObject.createObject();
    call(id, commit, "publish").post(in, cb);
  }

  /** Delete a specific draft change. */
  public static void deleteChange(int id, AsyncCallback<JavaScriptObject> cb) {
    change(id).delete(cb);
  }

  /** Delete a specific draft patch set. */
  public static void deleteRevision(int id, String commit, AsyncCallback<JavaScriptObject> cb) {
    revision(id, commit).delete(cb);
  }

  /** Delete change edit. */
  public static void deleteEdit(int id, AsyncCallback<JavaScriptObject> cb) {
    edit(id).delete(cb);
  }

  /** Publish change edit. */
  public static void publishEdit(int id, AsyncCallback<JavaScriptObject> cb) {
    JavaScriptObject in = JavaScriptObject.createObject();
    change(id).view("edit:publish").post(in, cb);
  }

  /** Rebase change edit on latest patch set. */
  public static void rebaseEdit(int id, AsyncCallback<JavaScriptObject> cb) {
    JavaScriptObject in = JavaScriptObject.createObject();
    change(id).view("edit:rebase").post(in, cb);
  }

  /** Rebase a revision onto the branch tip or another change. */
  public static void rebase(int id, String commit, String base, AsyncCallback<ChangeInfo> cb) {
    RebaseInput rebaseInput = RebaseInput.create();
    rebaseInput.setBase(base);
    call(id, commit, "rebase").post(rebaseInput, cb);
  }

  private static class MessageInput extends JavaScriptObject {
    final native void message(String m) /*-{ if(m)this.message=m; }-*/;

    static MessageInput create() {
      return (MessageInput) createObject();
    }

    protected MessageInput() {}
  }

  private static class AssigneeInput extends JavaScriptObject {
    final native void assignee(String a) /*-{ if(a)this.assignee=a; }-*/;

    static AssigneeInput create() {
      return (AssigneeInput) createObject();
    }

    protected AssigneeInput() {}
  }

  private static class TopicInput extends JavaScriptObject {
    final native void topic(String t) /*-{ if(t)this.topic=t; }-*/;

    static TopicInput create() {
      return (TopicInput) createObject();
    }

    protected TopicInput() {}
  }

  private static class CreateChangeInput extends JavaScriptObject {
    static CreateChangeInput create() {
      return (CreateChangeInput) createObject();
    }

    public final native void branch(String b) /*-{ if(b)this.branch=b; }-*/;

    public final native void topic(String t) /*-{ if(t)this.topic=t; }-*/;

    public final native void project(String p) /*-{ if(p)this.project=p; }-*/;

    public final native void subject(String s) /*-{ if(s)this.subject=s; }-*/;

    public final native void status(String s) /*-{ if(s)this.status=s; }-*/;

    public final native void baseChange(String b) /*-{ if(b)this.base_change=b; }-*/;

    protected CreateChangeInput() {}
  }

  private static class CherryPickInput extends JavaScriptObject {
    static CherryPickInput create() {
      return (CherryPickInput) createObject();
    }

    final native void setDestination(String d) /*-{ this.destination = d; }-*/;

    final native void setMessage(String m) /*-{ this.message = m; }-*/;

    protected CherryPickInput() {}
  }

  private static class RebaseInput extends JavaScriptObject {
    final native void setBase(String b) /*-{ this.base = b; }-*/;

    static RebaseInput create() {
      return (RebaseInput) createObject();
    }

    protected RebaseInput() {}
  }

  private static RestApi call(int id, String action) {
    return change(id).view(action);
  }

  private static RestApi call(int id, String commit, String action) {
    return change(id).view("revisions").id(commit).view(action);
  }

  public static RestApi change(int id) {
    // TODO Switch to triplet project~branch~id format in URI.
    return new RestApi("/changes/").id(String.valueOf(id));
  }

  public static String emptyToNull(String str) {
    return str == null || str.isEmpty() ? null : str;
  }

  public static void commitWithLinks(int changeId, String revision, Callback<CommitInfo> callback) {
    revision(changeId, revision).view("commit").addParameterTrue("links").get(callback);
  }
}
