/*
 * Copyright (C) 2017 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.android.tools.idea.observable;

import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import java.util.ArrayList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Convenience class for managing property listeners.
 * <p/>
 * Although you can always use {@link ObservableValue#addListener(InvalidationListener)} directly,
 * occasionally this requires creating a local field to store a listener so you can remove it
 * later. This can be fine for one or two listeners, but for more complex cases, use this class
 * to manage listeners for you (and remove them all easily using {@link #releaseAll()}
 * <p/>
 * This class also provides convenience methods for listening by {@link Receiver}, which has more
 * type safety than using a generic {@link InvalidationListener}.
 * <p/>
 * Finally, it provides a {@link #listenAll(Collection)} method, which allows you to register a
 * single listener for many properties in aggregate.
 * <p/>
 * Note: This class is currently not thread-safe. You are expected to add and remove listeners on
 * the dispatch thread to avoid undefined behavior.
 */
public final class ListenerManager {

  /**
   * List of all listeners registered by one of the listen calls.
   */
  private final List<ListenerPairing> myListeners = new ArrayList<>();

  /**
   * The listen methods take either an invalidation listener (untyped) or a receiver (typed).
   * When a user adds a receiver, those are wrapped in an invalidation listener, and the
   * relationship is recorded here so we can later remove by receiver as well.
   */
  private final Map<Receiver<?>, InvalidationListener> myReceiverMapping = Maps.newHashMap();

  /**
   * List of listeners registered by listenAll.
   */
  private final List<CompositeListener> myCompositeListeners = Lists.newArrayListWithExpectedSize(0);

  private final BatchInvoker myInvoker;

  public ListenerManager() {
    myInvoker = new BatchInvoker();
  }

  public ListenerManager(@NotNull BatchInvoker.Strategy invokeStrategy) {
    myInvoker = new BatchInvoker(invokeStrategy);
  }

  /**
   * Registers the target listener with the specified observable.
   */
  public void listen(@NotNull ObservableValue<?> src, @NotNull InvalidationListener listener) {
    myListeners.add(new ListenerPairing(src, listener));
  }

  /**
   * Like {@link #listen(ObservableValue, InvalidationListener)} but with a typed receiver.
   */
  public <T> void listen(@NotNull final ObservableValue<T> src, @NotNull final Receiver<T> receiver) {
    InvalidationListener listenerWrapper = () -> receiver.receive(src.get());
    myReceiverMapping.put(receiver, listenerWrapper);

    listen(src, listenerWrapper);
  }

  /**
   * A convenience method which both registers the target listener and then fires it with the
   * observable's latest value (to initialize it, essentially).
   */
  public void listenAndFire(@NotNull ObservableValue<?> src, @NotNull InvalidationListener listener) {
    listen(src, listener);
    listener.onInvalidated();
  }

  /**
   * A convenience method which both registers the target receiver and then fires it with the
   * observable's latest value (to initialize it, essentially).
   */
  public <T> void listenAndFire(@NotNull final ObservableValue<T> src, @NotNull final Receiver<T> receiver) {
    listen(src, receiver);
    receiver.receive(src.get());
  }

  /**
   * Listen to a collection of observable values, firing an event whenever one or more of them
   * change on any given frame.
   *
   * This method starts a fluent chain, but to actually hook up a listener, you must also call
   * {@link CompositeListener#with(Runnable)} as well.
   *
   * For example: {@code listeners.listenAll(x, y, w, h).}<b>{@code with(repaint);}</b>
   */
  @NotNull
  public CompositeListener listenAll(@NotNull ObservableValue<?>... values) {
    CompositeListener listener = new CompositeListener(values);
    myCompositeListeners.add(listener);
    return listener;
  }

  /**
   * Convenience version of {@link #listenAll(ObservableValue[])} that works when you have a
   * {@link Collection} instead of an array.
   */
  @NotNull
  public CompositeListener listenAll(@NotNull Collection<? extends ObservableValue<?>> values) {
    //noinspection unchecked
    return listenAll(Iterables.toArray(values, ObservableValue.class));
  }

  /**
   * Releases a listener previously registered via
   * {@link #listen(ObservableValue, InvalidationListener)}. If the listener was registered with
   * multiple observables, they will all be released.
   */
  public void release(@NotNull InvalidationListener listener) {
    Iterator<ListenerPairing> i = myListeners.iterator();
    while (i.hasNext()) {
      ListenerPairing listenerPairing = i.next();

      if (listenerPairing.myListener == listener) {
        listenerPairing.dispose();
        i.remove();
      }
    }
  }

  /**
   * Releases a receiver previously registered via
   * {@link #listen(ObservableValue, Receiver)}. If the receiver was registered with
   * multiple observables, they will all be released.
   */
  public void release(@NotNull Receiver<?> receiver) {
    InvalidationListener listenerWrapper = myReceiverMapping.get(receiver);
    if (listenerWrapper == null) {
      return;
    }
    release(listenerWrapper);
  }

  /**
   * Releases all listeners previously registered to a target observable via
   * {@link #listen(ObservableValue, InvalidationListener)} or
   * {@link #listen(ObservableValue, Receiver)}.
   */
  public void release(@NotNull ObservableValue<?> observable) {
    Iterator<ListenerPairing> i = myListeners.iterator();
    while (i.hasNext()) {
      ListenerPairing listenerPairing = i.next();

      if (listenerPairing.myObservable == observable) {
        listenerPairing.dispose();
        i.remove();
      }
    }
  }

  /**
   * Releases a listener previously registered via {@link #listenAll(ObservableValue...)}
   */
  public void release(@NotNull Runnable listenAllRunnable) {
    Iterator<CompositeListener> iterator = myCompositeListeners.iterator();
    while (iterator.hasNext()) {
      CompositeListener listener = iterator.next();
      if (listener.ownsRunnable(listenAllRunnable)) {
        listener.dispose();
        iterator.remove();
      }
    }
  }

  /**
   * Release all listeners registered with this manager.
   */
  public void releaseAll() {
    for (ListenerPairing listener : myListeners) {
      listener.dispose();
    }
    myListeners.clear();
    for (CompositeListener listener : myCompositeListeners) {
      listener.dispose();
    }
    myCompositeListeners.clear();
  }

  private static class ListenerPairing {
    private final ObservableValue<?> myObservable;
    private final InvalidationListener myListener;

    public ListenerPairing(ObservableValue<?> src, InvalidationListener listener) {
      myObservable = src;
      myListener = listener;

      src.addListener(listener);
    }

    public void dispose() {
      myObservable.removeListener(myListener);
    }
  }

  /**
   * Intermediate class which gives the {@link #listenAll(ObservableValue[])} method a fluent
   * interface.
   */
  public final class CompositeListener implements InvalidationListener, Runnable {

    @NotNull private final ObservableValue<?>[] myValues;
    @Nullable private Runnable myOnAnyInvalidated;

    public CompositeListener(@NotNull ObservableValue<?>... values) {
      myValues = values;
      for (ObservableValue<?> value : myValues) {
        value.addListener(this);
      }
    }

    public void dispose() {
      for (ObservableValue<?> value : myValues) {
        value.removeListener(this);
      }
    }

    /**
     * Specify the callback which will be triggered whenever any of the values we are listening to
     * changes.
     */
    public void with(@NotNull Runnable onAnyInvalidated) {
      myOnAnyInvalidated = onAnyInvalidated;
    }

    /**
     * Like {@link #with(Runnable)} but immediately runs the target callback once registered.
     *
     * This is essentially the {@link #listenAndFire(ObservableValue, InvalidationListener)}
     * equivalent of {@link #listenAll(ObservableValue[])}
     */
    public void withAndFire(@NotNull Runnable onAnyInvalidated) {
      with(onAnyInvalidated);
      run();
    }

    boolean ownsRunnable(@NotNull Runnable onAnyInvalidated) {
      return onAnyInvalidated.equals(myOnAnyInvalidated);
    }

    @Override
    public void onInvalidated() {
      myInvoker.enqueue(this);
    }

    @Override
    public void run() {
      if (myOnAnyInvalidated != null) {
        myOnAnyInvalidated.run();
      }
    }
  }
}
