// Copyright (C) 2013 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.rpc;

import com.google.gwt.user.client.rpc.AsyncCallback;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Class for grouping together callbacks and calling them in order.
 * <p>
 * Callbacks are added to the group with {@link #add(AsyncCallback)}, which
 * returns a wrapped callback suitable for passing to an asynchronous RPC call.
 * The last callback must be added using {@link #addFinal(AsyncCallback)} or
 * {@link #done()} must be invoked.
 *
 * The enclosing group buffers returned results and ensures that
 * {@code onSuccess} is called exactly once for each callback in the group, in
 * the same order that callbacks were added. This allows callers to, for
 * example, use a {@link ScreenLoadCallback} as the last callback in the list
 * and only display the screen once all callbacks have succeeded.
 * <p>
 * In the event of a failure, the <em>first</em> caught exception is sent to
 * <em>all</em> callbacks' {@code onFailure} methods, in order; subsequent
 * successes or failures are all ignored. Note that this means
 * {@code onFailure} may be called with an exception unrelated to the callback
 * processing it.
 */
public class CallbackGroup {
  private final List<CallbackGlue> callbacks;
  private final Set<CallbackGlue> remaining;
  private boolean finalAdded;

  private boolean failed;
  private Throwable failedThrowable;

  public static <T> Callback<T> emptyCallback() {
    return new Callback<T>() {
      @Override
      public void onSuccess(T result) {
      }

      @Override
      public void onFailure(Throwable err) {
      }
    };
  }

  public CallbackGroup() {
    callbacks = new ArrayList<>();
    remaining = new HashSet<>();
  }

  public <T> Callback<T> addEmpty() {
    Callback<T> cb = emptyCallback();
    return add(cb);
  }

  public <T> Callback<T> add(final AsyncCallback<T> cb) {
    checkFinalAdded();
    return handleAdd(cb);
  }

  public <T> HttpCallback<T> add(HttpCallback<T> cb) {
    checkFinalAdded();
    if (failed) {
      cb.onFailure(failedThrowable);
      return new HttpCallback<T>() {
        @Override
        public void onSuccess(HttpResponse<T> result) {
        }

        @Override
        public void onFailure(Throwable caught) {
        }
      };
    }

    HttpCallbackImpl<T> w = new HttpCallbackImpl<>(cb);
    callbacks.add(w);
    remaining.add(w);
    return w;
  }

  public <T> Callback<T> addFinal(final AsyncCallback<T> cb) {
    checkFinalAdded();
    finalAdded = true;
    return handleAdd(cb);
  }

  public void done() {
    finalAdded = true;
    apply();
  }

  public void addListener(AsyncCallback<Void> cb) {
    if (!failed && finalAdded && remaining.isEmpty()) {
      cb.onSuccess(null);
    } else {
      handleAdd(cb).onSuccess(null);
    }
  }

  public void addListener(CallbackGroup group) {
    addListener(group.<Void> addEmpty());
  }

  private void success(CallbackGlue cb) {
    remaining.remove(cb);
    apply();
  }

  private <T> void failure(CallbackGlue w, Throwable caught) {
    if (!failed) {
      failed = true;
      failedThrowable = caught;
    }
    remaining.remove(w);
    apply();
  }

  private void apply() {
    if (finalAdded && remaining.isEmpty()) {
      if (failed) {
        for (CallbackGlue cb : callbacks) {
          cb.applyFailed();
        }
      } else {
        for (CallbackGlue cb : callbacks) {
          cb.applySuccess();
        }
      }
      callbacks.clear();
    }
  }

  private <T> Callback<T> handleAdd(AsyncCallback<T> cb) {
    if (failed) {
      cb.onFailure(failedThrowable);
      return emptyCallback();
    }

    CallbackImpl<T> wrapper = new CallbackImpl<>(cb);
    callbacks.add(wrapper);
    remaining.add(wrapper);
    return wrapper;
  }

  private void checkFinalAdded() {
    if (finalAdded) {
      throw new IllegalStateException("final callback already added");
    }
  }

  public interface Callback<T>
      extends AsyncCallback<T>, com.google.gwtjsonrpc.common.AsyncCallback<T> {
  }

  private interface CallbackGlue {
    void applySuccess();
    void applyFailed();
  }

  private class CallbackImpl<T> implements Callback<T>, CallbackGlue {
    AsyncCallback<T> delegate;
    T result;

    CallbackImpl(AsyncCallback<T> delegate) {
      this.delegate = delegate;
    }

    @Override
    public void onSuccess(T value) {
      this.result = value;
      success(this);
    }

    @Override
    public void onFailure(Throwable caught) {
      failure(this, caught);
    }

    @Override
    public void applySuccess() {
      AsyncCallback<T> cb = delegate;
      if (cb != null) {
        delegate = null;
        cb.onSuccess(result);
        result = null;
      }
    }

    @Override
    public void applyFailed() {
      AsyncCallback<T> cb = delegate;
      if (cb != null) {
        delegate = null;
        result = null;
        cb.onFailure(failedThrowable);
      }
    }
  }

  private class HttpCallbackImpl<T> implements HttpCallback<T>, CallbackGlue {
    private HttpCallback<T> delegate;
    private HttpResponse<T> result;

    HttpCallbackImpl(HttpCallback<T> delegate) {
      this.delegate = delegate;
    }

    @Override
    public void onSuccess(HttpResponse<T> result) {
      this.result = result;
      success(this);
    }

    @Override
    public void onFailure(Throwable caught) {
      failure(this, caught);
    }

    @Override
    public void applySuccess() {
      HttpCallback<T> cb = delegate;
      if (cb != null) {
        delegate = null;
        cb.onSuccess(result);
        result = null;
      }
    }

    @Override
    public void applyFailed() {
      HttpCallback<T> cb = delegate;
      if (cb != null) {
        delegate = null;
        result = null;
        cb.onFailure(failedThrowable);
      }
    }
  }
}
