// 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.account.AccountApi;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Image;
import com.google.gwtexpui.globalkey.client.KeyCommand;
import com.google.web.bindery.event.shared.Event;
import com.google.web.bindery.event.shared.HandlerRegistration;

import java.util.LinkedHashMap;
import java.util.Map;

/** Supports the star icon displayed on changes and tracking the status. */
public class StarredChanges {
  private static final Event.Type<ChangeStarHandler> TYPE =
      new Event.Type<ChangeStarHandler>();

  /** Handler that can receive notifications of a change's starred status. */
  public static interface ChangeStarHandler {
    public void onChangeStar(ChangeStarEvent event);
  }

  /** Event fired when a star changes status. The new status is reported. */
  public static class ChangeStarEvent extends Event<ChangeStarHandler> {
    private boolean starred;

    public ChangeStarEvent(Change.Id source, boolean starred) {
      setSource(source);
      this.starred = starred;
    }

    public boolean isStarred() {
      return starred;
    }

    @Override
    public Type<ChangeStarHandler> getAssociatedType() {
      return TYPE;
    }

    @Override
    protected void dispatch(ChangeStarHandler handler) {
      handler.onChangeStar(this);
    }
  }

  /**
   * Create a star icon for the given change, and current status. Returns null
   * if the user is not signed in and cannot support starred changes.
   */
  public static Icon createIcon(Change.Id source, boolean starred) {
    return Gerrit.isSignedIn() ? new Icon(source, starred) : null;
  }

  /** Make a key command that toggles the star for a change. */
  public static KeyCommand newKeyCommand(final Icon icon) {
    return new KeyCommand(0, 's', Util.C.changeTableStar()) {
      @Override
      public void onKeyPress(KeyPressEvent event) {
        icon.toggleStar();
      }
    };
  }

  /** Add a handler to listen for starred status to change. */
  public static HandlerRegistration addHandler(
      Change.Id source,
      ChangeStarHandler handler) {
    return Gerrit.EVENT_BUS.addHandlerToSource(TYPE, source, handler);
  }

  /**
   * Broadcast the current starred value of a change to UI widgets. This does
   * not RPC to the server and does not alter the starred status of a change.
   */
  public static void fireChangeStarEvent(Change.Id id, boolean starred) {
    Gerrit.EVENT_BUS.fireEventFromSource(
        new ChangeStarEvent(id, starred),
        id);
  }

  /**
   * Set the starred status of a change. This method broadcasts to all
   * interested UI widgets and sends an RPC to the server to record the
   * updated status.
   */
  public static void toggleStar(
      final Change.Id changeId,
      final boolean newValue) {
    pending.put(changeId, newValue);
    fireChangeStarEvent(changeId, newValue);
    if (!busy) {
      startRequest();
    }
  }

  private static boolean busy;
  private static final Map<Change.Id, Boolean> pending =
      new LinkedHashMap<Change.Id, Boolean>(4);

  private static void startRequest() {
    busy = true;

    final Change.Id id = pending.keySet().iterator().next();
    final boolean starred = pending.remove(id);
    RestApi call = AccountApi.self().view("starred.changes").id(id.get());
    AsyncCallback<JavaScriptObject> cb = new AsyncCallback<JavaScriptObject>() {
      @Override
      public void onSuccess(JavaScriptObject none) {
        if (pending.isEmpty()) {
          busy = false;
        } else {
          startRequest();
        }
      }

      @Override
      public void onFailure(Throwable caught) {
        if (!starred && RestApi.isStatus(caught, 404)) {
          onSuccess(null);
          return;
        }

        fireChangeStarEvent(id, !starred);
        for (Map.Entry<Change.Id, Boolean> e : pending.entrySet()) {
          fireChangeStarEvent(e.getKey(), !e.getValue());
        }
        pending.clear();
        busy = false;
      }
    };
    if (starred) {
      call.put(cb);
    } else {
      call.delete(cb);
    }
  }

  public static class Icon extends Image
      implements ChangeStarHandler, ClickHandler {
    private final Change.Id changeId;
    private boolean starred;
    private HandlerRegistration handler;

    Icon(Change.Id changeId, boolean starred) {
      super(resource(starred));
      this.changeId = changeId;
      this.starred = starred;
      addClickHandler(this);
    }

    /**
     * Toggles the state of the star, as if the user clicked on the image. This
     * will broadcast the new star status to all interested UI widgets, and RPC
     * to the server to store the changed value.
     */
    public void toggleStar() {
      StarredChanges.toggleStar(changeId, !starred);
    }

    @Override
    protected void onLoad() {
      handler = StarredChanges.addHandler(changeId, this);
    }

    @Override
    protected void onUnload() {
      handler.removeHandler();
      handler = null;
    }

    @Override
    public void onChangeStar(ChangeStarEvent event) {
      setResource(resource(event.isStarred()));
      starred = event.isStarred();
    }

    @Override
    public void onClick(ClickEvent event) {
      toggleStar();
    }

    private static ImageResource resource(boolean starred) {
      return starred ? Gerrit.RESOURCES.starFilled() : Gerrit.RESOURCES.starOpen();
    }
  }

  private StarredChanges() {
  }
}
