/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.waveprotocol.box.server.robots.passive;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.wave.api.BlipData;
import com.google.wave.api.Context;
import com.google.wave.api.Gadget;
import com.google.wave.api.data.converter.ContextResolver;
import com.google.wave.api.data.converter.EventDataConverter;
import com.google.wave.api.event.*;
import com.google.wave.api.impl.EventMessageBundle;
import com.google.wave.api.robot.Capability;
import com.google.wave.api.robot.RobotName;
import org.waveprotocol.box.server.robots.util.ConversationUtil;
import org.waveprotocol.box.server.util.WaveletDataUtil;
import org.waveprotocol.wave.model.conversation.*;
import org.waveprotocol.wave.model.document.Doc.E;
import org.waveprotocol.wave.model.document.Doc.N;
import org.waveprotocol.wave.model.document.Doc.T;
import org.waveprotocol.wave.model.document.DocHandler;
import org.waveprotocol.wave.model.document.ObservableDocument;
import org.waveprotocol.wave.model.document.indexed.DocumentEvent;
import org.waveprotocol.wave.model.document.indexed.DocumentEvent.AnnotationChanged;
import org.waveprotocol.wave.model.document.indexed.DocumentEvent.AttributesModified;
import org.waveprotocol.wave.model.document.indexed.DocumentEvent.ContentInserted;
import org.waveprotocol.wave.model.document.raw.impl.Node;
import org.waveprotocol.wave.model.operation.OperationException;
import org.waveprotocol.wave.model.operation.SilentOperationSink;
import org.waveprotocol.wave.model.operation.wave.BasicWaveletOperationContextFactory;
import org.waveprotocol.wave.model.operation.wave.TransformedWaveletDelta;
import org.waveprotocol.wave.model.operation.wave.WaveletBlipOperation;
import org.waveprotocol.wave.model.operation.wave.WaveletOperation;
import org.waveprotocol.wave.model.wave.*;
import org.waveprotocol.wave.model.wave.data.ObservableWaveletData;
import org.waveprotocol.wave.model.wave.opbased.OpBasedWavelet;
import org.waveprotocol.wave.model.wave.opbased.WaveletListenerImpl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Generates Robot API Events from operations applied to a Wavelet.
 *
 * <p>
 * Events that exist in the API:
 * <li>WaveletBlipCreated (DONE)</li>
 * <li>WaveletBlipRemoved (DONE)</li>
 * <li>WaveletParticipantsChanged (DONE)</li>
 * <li>WaveletSelfAdded (DONE)</li>
 * <li>WaveletSelfRemoved (DONE)</li>
 * <li>DocumentChanged (DONE)</li>
 * <li>AnnotatedTextChanged (DONE)</li>
 * <li>FormButtonClicked (TBD)</li>
 * <li>GadgetStateChanged (DONE)</li>
 * <li>BlipContributorChanged (TBD)</li>
 * <li>WaveletTagsChanged (TBD)</li>
 * <li>WaveletTitleChanged (TBD)</li>
 * <li>BlipSubmitted (Will not be supported, submit ops will be phased out)</li>
 *
 * @author ljvderijk@google.com (Lennard de Rijk)
 */
public class EventGenerator {

  private static class EventGeneratingWaveletListener extends WaveletListenerImpl {
    @SuppressWarnings("unused")
    private final Map<EventType, Capability> capabilities;

    /**
     * Creates a {@link WaveletListener} which will generate events according to
     * the capabilities.
     *
     * @param capabilities the capabilities which we are interested in.
     */
    public EventGeneratingWaveletListener(Map<EventType, Capability> capabilities) {
      this.capabilities = capabilities;
    }
    // TODO(ljvderijk): implement more events. This class should listen for
    // non-conversational blip changes and robot data documents as indicated by
    // IdConstants.ROBOT_PREFIX
  }

  private class EventGeneratingConversationListener extends ConversationListenerImpl {
    private final Map<EventType, Capability> capabilities;
    private final Conversation conversation;
    private final EventMessageBundle messages;

    // Event collectors
    private final List<String> participantsAdded = Lists.newArrayList();
    private final List<String> participantsRemoved = Lists.newArrayList();

    // Changes for each delta
    private ParticipantId deltaAuthor;
    private Long deltaTimestamp;

    /**
     * Creates a {@link ObservableConversation.Listener} which will generate
     * events according to the capabilities.
     *
     * @param conversation the conversation we are observing.
     * @param capabilities the capabilities which we are interested in.
     * @param messages the bundle to put the events in.
     */
    public EventGeneratingConversationListener(Conversation conversation,
        Map<EventType, Capability> capabilities, EventMessageBundle messages, RobotName robotName) {
      this.conversation = conversation;
      this.capabilities = capabilities;
      this.messages = messages;
    }

    /**
     * Prepares this listener for events coming from a single delta.
     *
     * @param author the author of the delta.
     * @param timestamp the timestamp of the delta.
     */
    public void deltaBegin(ParticipantId author, long timestamp) {
      Preconditions.checkState(
          deltaAuthor == null && deltaTimestamp == null, "DeltaEnd wasn't called");
      Preconditions.checkNotNull(author, "Author should not be null");
      Preconditions.checkNotNull(timestamp, "Timestamp should not be null");

      deltaAuthor = author;
      deltaTimestamp = timestamp;
    }

    @Override
    public void onParticipantAdded(ParticipantId participant) {
      if (capabilities.containsKey(EventType.WAVELET_PARTICIPANTS_CHANGED)) {
        boolean removedBefore = participantsRemoved.remove(participant.getAddress());
        if (!removedBefore) {
          participantsAdded.add(participant.getAddress());
        }
      }

      // This deviates from Google Wave production which always sends this
      // event, even if it wasn't present in your capabilities.
      if (capabilities.containsKey(EventType.WAVELET_SELF_ADDED) && participant.equals(robotId)) {
        // The robot has been added
        String rootBlipId = ConversationUtil.getRootBlipId(conversation);
        WaveletSelfAddedEvent event = new WaveletSelfAddedEvent(
            null, null, deltaAuthor.getAddress(), deltaTimestamp, rootBlipId);
        addEvent(event, capabilities, rootBlipId, messages);
      }
    }

    @Override
    public void onParticipantRemoved(ParticipantId participant) {
      if (capabilities.containsKey(EventType.WAVELET_PARTICIPANTS_CHANGED)) {
        participantsRemoved.add(participant.getAddress());
      }

      if (capabilities.containsKey(EventType.WAVELET_SELF_REMOVED) && participant.equals(robotId)) {
        String rootBlipId = ConversationUtil.getRootBlipId(conversation);
        WaveletSelfRemovedEvent event = new WaveletSelfRemovedEvent(
            null, null, deltaAuthor.getAddress(), deltaTimestamp, rootBlipId);
        addEvent(event, capabilities, rootBlipId, messages);
      }
    }

    @Override
    public void onBlipAdded(ObservableConversationBlip blip) {
      if (capabilities.containsKey(EventType.WAVELET_BLIP_CREATED)) {
        String rootBlipId = ConversationUtil.getRootBlipId(conversation);
        WaveletBlipCreatedEvent event = new WaveletBlipCreatedEvent(
            null, null, deltaAuthor.getAddress(), deltaTimestamp, rootBlipId, blip.getId());
        addEvent(event, capabilities, rootBlipId, messages);
      }
    }

    @Override
    public void onBlipDeleted(ObservableConversationBlip blip) {
      if (capabilities.containsKey(EventType.WAVELET_BLIP_REMOVED)) {
        String rootBlipId = ConversationUtil.getRootBlipId(conversation);
        WaveletBlipRemovedEvent event = new WaveletBlipRemovedEvent(
            null, null, deltaAuthor.getAddress(), deltaTimestamp, rootBlipId, blip.getId());
        addEvent(event, capabilities, rootBlipId, messages);
      }
    }

    /**
     * Generates the events that are collected over the span of one delta.
     */
    public void deltaEnd() {
      if (!participantsAdded.isEmpty() || !participantsRemoved.isEmpty()) {
        String rootBlipId = ConversationUtil.getRootBlipId(conversation);

        WaveletParticipantsChangedEvent event =
            new WaveletParticipantsChangedEvent(null, null, deltaAuthor.getAddress(),
                deltaTimestamp, rootBlipId, participantsAdded, participantsRemoved);
        addEvent(event, capabilities, rootBlipId, messages);
      }
      clearOncePerDeltaCollectors();

      deltaAuthor = null;
      deltaTimestamp = null;
    }

    /**
     * Clear the data structures responsible for collecting data for events that
     * should only be fired once per delta.
     */
    private void clearOncePerDeltaCollectors() {
      participantsAdded.clear();
      participantsRemoved.clear();
    }
  }

  private class EventGeneratingDocumentHandler implements DocHandler {

    /** Public so we can manage the subscription */
    public final ObservableDocument doc;

    private final ConversationBlip blip;
    private final Map<EventType, Capability> capabilities;
    private final EventMessageBundle messages;
    private ParticipantId deltaAuthor;
    private Long deltaTimestamp;

    /**
     * Set to true if a {@link DocumentChangedEvent} has been generated by this
     * handler.
     */
    private boolean documentChangedEventGenerated;

    private EventDataConverter converter;
    private Wavelet wavelet;

    public EventGeneratingDocumentHandler(ObservableDocument doc, ConversationBlip blip,
        Map<EventType, Capability> capabilities, EventMessageBundle messages,
        ParticipantId deltaAuthor, Long deltaTimestamp, Wavelet wavelet,
        EventDataConverter converter) {
      this.doc = doc;
      this.blip = blip;
      this.capabilities = capabilities;
      this.messages = messages;
      this.converter = converter;
      this.wavelet = wavelet;
      setAuthorAndTimeStamp(deltaAuthor, deltaTimestamp);
    }

    @Override
    public void onDocumentEvents(EventBundle<N, E, T> event) {
      Iterable<DocumentEvent<N, E, T>> eventComponents = event.getEventComponents();

      for (DocumentEvent<N, E, T> eventComponent : eventComponents) {
        if (eventComponent.getType() == DocumentEvent.Type.ANNOTATION_CHANGED) {
          if (capabilities.containsKey(EventType.ANNOTATED_TEXT_CHANGED)) {
            AnnotationChanged<N, E, T> anotationChangedEvent =
                (AnnotationChanged<N, E, T>) eventComponent;
            AnnotatedTextChangedEvent apiEvent =
                new AnnotatedTextChangedEvent(null, null, deltaAuthor.getAddress(), deltaTimestamp,
                    blip.getId(), anotationChangedEvent.key, anotationChangedEvent.newValue);
            addEvent(apiEvent, capabilities, blip.getId(), messages);
          }
        } else {
          // used to distinguish between attribute changes and gadget state
          // changes
          Boolean gadgetStateChangeEvent = false;
          if (eventComponent.getType() == DocumentEvent.Type.ATTRIBUTES) {
            if (capabilities.containsKey(EventType.GADGET_STATE_CHANGED)) {
              Map<String, String> oldState = new HashMap<>();
              Integer index = -1;
              try {
                AttributesModified<N, E, T> attributesModified =
                    (AttributesModified<N, E, T>) eventComponent;
                // When a gadget state changes, the AttributesModifies event has
                // always
                // an oldValue map of the form {"value", something} (key is
                // always value).
                // To obtain the key of the changed state, the attribute "name"
                // has to be obtained
                // from the Element of the AttributesModified event.
                String name =
                    ((org.waveprotocol.wave.model.document.raw.impl.Element) attributesModified
                        .getElement()).getAttribute("name");
                String oldValue = attributesModified.getOldValues().get("value");
                if (name != null || oldValue != null) {
                  oldState.put(name, oldValue);
                }
                BlipData b = converter.toBlipData(blip, wavelet, messages);
                Map<Integer, com.google.wave.api.Element> elements = b.getElements();
                Set<Integer> keys = elements.keySet();
                // The gadget element provided by the eventComponent
                org.waveprotocol.wave.model.document.raw.impl.Element rawGadget =
                    ((Node) attributesModified.getElement()).getParentElement();
                for (Integer key : keys) {
                  try {
                    Gadget gadget = (Gadget) elements.get(key);
                    if (sameGadgets(rawGadget, gadget)) {
                      index = key;
                      break;
                    }
                  } catch (ClassCastException e) {
                    // if it is not a gadget we do not compare them
                  }
                }
              } catch (ClassCastException e) {
                e.printStackTrace();
              }
              if (oldState.size() != 0 && index != -1) {
                // if the attribute changed belongs to a gadget
                gadgetStateChangeEvent = true;
                final GadgetStateChangedEvent gadgetEvent =
                    new GadgetStateChangedEvent(null, messages, deltaAuthor.getAddress(),
                        deltaTimestamp, blip.getId(), index, oldState);
                addEvent(gadgetEvent, capabilities, blip.getId(), messages);
              }
            }
          }
          if (capabilities.containsKey(EventType.FORM_BUTTON_CLICKED)) {
            if (eventComponent.getType() == DocumentEvent.Type.CONTENT_INSERTED) {
              ContentInserted<N, E, T> contentInserted = (ContentInserted<N, E, T>) eventComponent;
              org.waveprotocol.wave.model.document.raw.impl.Element elementInserted = ((org.waveprotocol.wave.model.document.raw.impl.Element) contentInserted.getSubtreeElement());
              if (elementInserted.getTagName().equals("click")) {
                FormButtonClickedEvent buttonClickedEvent =
                    new FormButtonClickedEvent(null, null,
                        elementInserted.getAttribute("clicker"), Long.decode(elementInserted
                            .getAttribute("time")), blip.getId(), elementInserted
                            .getParentElement().getAttribute("name"));
                addEvent(buttonClickedEvent, capabilities, blip.getId(), messages);
              }
            }

          } else
          if (capabilities.containsKey(EventType.DOCUMENT_CHANGED)
              && !documentChangedEventGenerated && !gadgetStateChangeEvent) {
            DocumentChangedEvent apiEvent =
                new DocumentChangedEvent(null, null, deltaAuthor.getAddress(), deltaTimestamp,
                    blip.getId());
            addEvent(apiEvent, capabilities, blip.getId(), messages);
            // Only one documentChangedEvent should be generated per bundle.
            documentChangedEventGenerated = true;
          }
        }
      }
    }

    /**
     * Sets the author and timestamp for the events that will be coming in.
     * Should be changed at least for every delta that will touch the document
     * that the handler is listening to.
     *
     * @param author the author of the delta.
     * @param timestamp the timestamp at which the delta is applied.
     */
    public void setAuthorAndTimeStamp(ParticipantId author, long timestamp) {
      Preconditions.checkNotNull(author, "Author should not be null");
      Preconditions.checkNotNull(timestamp, "Timestamp should not be null");
      this.deltaAuthor = author;
      this.deltaTimestamp = timestamp;
    }

    /**
     * Check if an {@link org.waveprotocol.wave.model.document.raw.impl.Element}
     * is and a {@link Gadget}
     *
     * @param rawElement
     * @param element
     * @return
     */
    private boolean sameGadgets(org.waveprotocol.wave.model.document.raw.impl.Element rawElement,
        Gadget element) {
      String ifr1 = rawElement.getAttribute("ifr");
      String ifr2 = element.getProperty("ifr");
      return (ifr1 != null && ifr1.equals(ifr2));
    }
  }

  /**
   * Adds an {@link Event} to the given {@link EventMessageBundle}.
   *
   * If a blip id is specified this will be added to the
   * {@link EventMessageBundle}'s required blips list with the context given by
   * the robot's capabilities. If a robot does not specify a context for this
   * event the default context will be used. Ergo this code is not responsible
   * for filtering operations that a robot is not interested in.
   *
   * @param event to add.
   * @param capabilities the capabilities to get the context from.
   * @param blipId id of the blip this event is related to, may be null.
   * @param messages {@link EventMessageBundle} to edit.
   */
  private void addEvent(Event event, Map<EventType, Capability> capabilities, String blipId,
      EventMessageBundle messages) {
    if (!isEventFilteredOut(event)) {
      // Add the given blip to the required blip lists with the context
      // specified by the robot's capabilities.
      if (!Strings.isNullOrEmpty(blipId)) {
        Capability capability = capabilities.get(event.getType());
        List<Context> contexts;
        if (capability == null) {
          contexts = Capability.DEFAULT_CONTEXT;
        } else {
          contexts = capability.getContexts();
        }
        messages.requireBlip(blipId, contexts);
      }
      // Add the event to the bundle.
      messages.addEvent(event);
    }
  }

  /**
   * Checks whether the event should be filtered out. It can happen
   * if the robot received several deltas where in some delta it is added to
   * the wavelet but it didn't receive the WAVELET_SELF_ADDED event yet.
   * Or if robot already received WAVELET_SELF_REMOVED
   * event - then it should not receive events after that.
   *
   * @param event  the event to filter.
   * @return true if the event should be filtered out
   */
  protected boolean isEventFilteredOut(Event event) {
    boolean isEventSuspensionOveriden = false;
    if (event.getType().equals(EventType.WAVELET_SELF_REMOVED)) {
      // Stop processing events.
      isEventProcessingSuspended = true;
      // Allow robot receive WAVELET_SELF_REMOVED event, but suspend after that.
      isEventSuspensionOveriden = true;
    }
    if (event.getType().equals(EventType.WAVELET_SELF_ADDED)) {
      // Start processing events.
      isEventProcessingSuspended = false;
    }
    if ((isEventProcessingSuspended && !isEventSuspensionOveriden)
        || event.getModifiedBy().equals(robotName.toParticipantAddress())) {
      // Robot was removed from wave or this is self generated event.
      return true;
    }
    return false;
  }

  /**
   * The name of the Robot to which this {@link EventGenerator} belongs. Used
   * for events where "self" is important.
   */
  private final RobotName robotName;

  /** Used to create conversations. */
  private final ConversationUtil conversationUtil;

  /**
   * Indicates that robot was removed from wavelet and thus event processing
   * should be suspended.
   */
  private boolean isEventProcessingSuspended;

  private final ParticipantId robotId;

  /**
   * Constructs a new {@link EventGenerator} for the robot with the given name.
   *
   * @param robotName the name of the robot.
   * @param conversationUtil used to create conversations.
   */
  public EventGenerator(RobotName robotName, ConversationUtil conversationUtil) {
    this.robotName = robotName;
    this.conversationUtil = conversationUtil;
    this.robotId = ParticipantId.ofUnsafe(robotName.toParticipantAddress());
  }

  /**
   * Generates the {@link EventMessageBundle} for the specified capabilities.
   *
   * @param waveletAndDeltas for which the events are to be generated
   * @param capabilities the capabilities to filter events on
   * @param converter converter for generating the API implementations of
   *        WaveletData and BlipData.
   * @returns true if an event was generated, false otherwise
   */
  public EventMessageBundle generateEvents(WaveletAndDeltas waveletAndDeltas,
      Map<EventType, Capability> capabilities, EventDataConverter converter) {
    EventMessageBundle messages = new EventMessageBundle(robotName.toEmailAddress(), "");
    ObservableWaveletData snapshot =
        WaveletDataUtil.copyWavelet(waveletAndDeltas.getSnapshotBeforeDeltas());
    isEventProcessingSuspended = !snapshot.getParticipants().contains(robotId);

    if (robotName.hasProxyFor()) {
      // This robot is proxying so set the proxy field.
      messages.setProxyingFor(robotName.getProxyFor());
    }

    // Sending any operations will cause an exception.
    OpBasedWavelet wavelet =
        new OpBasedWavelet(snapshot.getWaveId(), snapshot,
            // This doesn't thrown an exception, the sinks will
            new BasicWaveletOperationContextFactory(null),
            ParticipationHelper.DEFAULT, SilentOperationSink.VOID, SilentOperationSink.VOID);

    ObservableConversation conversation = getRootConversation(wavelet);

    if (conversation == null) {
      return messages;
    }

    // Start listening
    EventGeneratingConversationListener conversationListener =
        new EventGeneratingConversationListener(conversation, capabilities, messages, robotName);
    conversation.addListener(conversationListener);
    EventGeneratingWaveletListener waveletListener =
        new EventGeneratingWaveletListener(capabilities);
    wavelet.addListener(waveletListener);

    Map<String, EventGeneratingDocumentHandler> docHandlers = Maps.newHashMap();
    try {
      for (TransformedWaveletDelta delta : waveletAndDeltas.getDeltas()) {
        // TODO(ljvderijk): Set correct timestamp and hashed version once
        // wavebus sends them along
        long timestamp = 0L;
        conversationListener.deltaBegin(delta.getAuthor(), timestamp);

        for (WaveletOperation op : delta) {
          // Check if we need to attach a doc handler.
          if ((op instanceof WaveletBlipOperation)) {
            attachDocHandler(conversation, op, docHandlers, capabilities, messages,
                delta.getAuthor(), timestamp, wavelet, converter);
          }
          op.apply(snapshot);
        }
        conversationListener.deltaEnd();
      }
    } catch (OperationException e) {
      throw new IllegalStateException("Operation failed to apply when generating events", e);
    } finally {
      conversation.removeListener(conversationListener);
      wavelet.removeListener(waveletListener);
      for (EventGeneratingDocumentHandler docHandler : docHandlers.values()) {
        docHandler.doc.removeListener(docHandler);
      }
    }

    if (messages.getEvents().isEmpty()) {
      // No events found, no need to resolve contexts
      return messages;
    }

    // Resolve the context of the bundle now that all events have been
    // processed.
    ContextResolver.resolveContext(messages, wavelet, conversation, converter);

    return messages;
  }

  /**
   * Attaches a doc handler to the blip the operation applies to.
   *
   * @param conversation the conversation the op is to be applied to.
   * @param op the op to be applied
   * @param docHandlers the list of attached dochandlers.
   * @param capabilities the capabilities of the robot.
   * @param messages the bundle to put the generated events in.
   * @param deltaAuthor the author of the events generated.
   * @param timestamp the timestamp at which these events occurred.
   */
  private void attachDocHandler(ObservableConversation conversation, WaveletOperation op,
      Map<String, EventGeneratingDocumentHandler> docHandlers,
      Map<EventType, Capability> capabilities, EventMessageBundle messages,
      ParticipantId deltaAuthor, long timestamp, Wavelet wavelet, EventDataConverter converter) {
    WaveletBlipOperation blipOp = (WaveletBlipOperation) op;
    String blipId = blipOp.getBlipId();
    // Ignoring the documents outside the conversation such as tags
    // and robot data docs.
    ObservableConversationBlip blip = conversation.getBlip(blipId);
    if (blip != null) {
      String blipId1 = blip.getId();

      EventGeneratingDocumentHandler docHandler = docHandlers.get(blipId1);
      if (docHandler == null) {
        ObservableDocument doc = (ObservableDocument) blip.getContent();
        docHandler =
            new EventGeneratingDocumentHandler(doc, blip, capabilities, messages, deltaAuthor,
                timestamp, wavelet, converter);
        doc.addListener(docHandler);
        docHandlers.put(blipId1, docHandler);
      } else {
        docHandler.setAuthorAndTimeStamp(deltaAuthor, timestamp);
      }
    }
  }

  /**
   * Returns the root conversation from the given wavelet. Or null if there is
   * none.
   *
   * @param wavelet the wavelet to get the conversation from.
   */
  private ObservableConversation getRootConversation(ObservableWavelet wavelet) {
    if (!WaveletBasedConversation.waveletHasConversation(wavelet)) {
      // No conversation present, bail.
      return null;
    }

    ObservableConversation conversation = conversationUtil.buildConversation(wavelet).getRoot();
    if (conversation.getRootThread().getFirstBlip() == null) {
      // No root blip is present, this will cause Robot API code
      // to fail when resolving the context of events. This might be fixed later
      // on by making changes to the ContextResolver.
      return null;
    }
    return conversation;
  }
}
