package org.buddycloud.channelserver.packetprocessor.iq.namespace.pubsub;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.BlockingQueue;

import org.buddycloud.channelserver.channel.ChannelManager;
import org.buddycloud.channelserver.packetprocessor.PacketProcessor;
import org.buddycloud.channelserver.queue.UnknownFederatedPacketException;
import org.buddycloud.channelserver.utils.XMLConstants;
import org.buddycloud.channelserver.utils.node.item.payload.Buddycloud;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.dom4j.QName;
import org.dom4j.dom.DOMElement;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Packet;
import org.xmpp.packet.PacketError;
import org.xmpp.packet.IQ.Type;

public abstract class PacketProcessorAbstract implements PacketProcessor<IQ> {

  protected BlockingQueue<Packet> outQueue;
  protected ChannelManager channelManager;
  protected List<PubSubElementProcessor> elementProcessors = new LinkedList<PubSubElementProcessor>();
  
  protected Element pubsub;
  protected JID actor;
  
  protected void getActor(IQ reqIQ) throws InterruptedException, IllegalActorException {

    if (pubsub.elementText(XMLConstants.ACTOR_ELEM) == null) {
      return;
    }
    actor = new JID(pubsub.elementText(XMLConstants.ACTOR_ELEM).trim());
    String domain = actor.getDomain();
    
    String from = reqIQ.getFrom().getDomain();
    int startPosition = from.length() - domain.length();
    if (from.substring(startPosition).equals(domain)) {
      return;
    }
    throw new IllegalActorException();
  }
  
  @Override
  public void process(IQ reqIQ) throws Exception {

      pubsub = reqIQ.getChildElement();
      try {
        getActor(reqIQ);
      } catch (IllegalActorException e) {
        sendPolicyViolationResponse(reqIQ);
        return;
      }

      // Let's get the possible rsm element
      Element rsm = pubsub.element(new QName("set", new Namespace("", "http://jabber.org/protocol/rsm")));

      @SuppressWarnings("unchecked")
      List<Element> elements = pubsub.elements();

      boolean handled = false;
      for (Element x : elements) {
          for (PubSubElementProcessor elementProcessor : elementProcessors) {
              if (elementProcessor.accept(x)) {
                  elementProcessor.process(x, actor, reqIQ, rsm);
                  handled = true;
              }
          }
      }

      if (!handled) {
          sendFeatureNotImplementedResponse(reqIQ);
      }
  }
  
  public void purgeElementProcessors() {
    elementProcessors.clear();
  }
  
  public void addElementProcessor(PubSubElementProcessor processor) {
    elementProcessors.add(processor);
  }

  private void sendFeatureNotImplementedResponse(IQ reqIQ) throws InterruptedException {
    IQ reply = IQ.createResultIQ(reqIQ);
    reply.setChildElement(reqIQ.getChildElement().createCopy());
    reply.setType(Type.error);
    PacketError pe = new PacketError(org.xmpp.packet.PacketError.Condition.feature_not_implemented, org.xmpp.packet.PacketError.Type.cancel);
    reply.setError(pe);
    outQueue.put(reply);
  }
  
  private void sendPolicyViolationResponse(IQ reqIQ) throws InterruptedException {
    IQ reply = IQ.createResultIQ(reqIQ);
    reply.setChildElement(reqIQ.getChildElement().createCopy());
    reply.setType(Type.error);

    Element standardError = new DOMElement(XMLConstants.POLICY_VIOLATION, new org.dom4j.Namespace("", JabberPubsub.NS_XMPP_STANZAS));
    Element extraError = new DOMElement(XMLConstants.INVALID_NODE, new org.dom4j.Namespace("", Buddycloud.NS_ERROR));
    Element error = new DOMElement(XMLConstants.ERROR_ELEM);
    error.addAttribute(XMLConstants.TYPE_ATTR, PacketError.Type.cancel.toXMPP());
    error.add(standardError);
    error.add(extraError);
    reply.setChildElement(error);
    outQueue.put(reply);
  }
  
}

@@ -164,16 +164,60 @@
 Queue;%0A%0A
+import org.apache.commons.lang.StringUtils;%0A
 import o
@@ -341,83 +341,8 @@
 or;%0A
-import org.buddycloud.channelserver.queue.UnknownFederatedPacketException;%0A
 impo
@@ -603,16 +603,48 @@
 ket.IQ;%0A
+import org.xmpp.packet.IQ.Type;%0A
 import o
@@ -733,40 +733,8 @@
 ror;
-%0Aimport org.xmpp.packet.IQ.Type;
 %0A%0Apu
@@ -1001,18 +1001,16 @@
 sor%3E();%0A
-  
 %0A  prote
@@ -1053,18 +1053,16 @@
  actor;%0A
-  
 %0A  prote
@@ -1071,19 +1071,24 @@
 ed void 
-get
+validate
 Actor(IQ
@@ -1309,207 +1309,100 @@
 ));%0A
+%0A
     
+if (
 String
- domain = actor.getDomain();%0A    %0A    String from = reqIQ.getFrom().getDomain();%0A    int startPosition = from.length() - domain.length();%0A    if (from.substring(startPosition).equals(domain
+Utils.endsWithIgnoreCase(reqIQ.getFrom().getDomain(), %22.%22 + actor.getDomain()
 )) %7B
@@ -1465,18 +1465,16 @@
 ();%0A  %7D%0A
-  
 %0A  @Over
@@ -1590,19 +1590,24 @@
         
-get
+validate
 Actor(re

Improve actor validation.