/*
 * libjingle
 * Copyright 2004--2006, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice, 
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products 
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "talk/xmpp/pubsub_task.h"

#include <map>
#include <string>

#include "talk/base/common.h"
#include "talk/xmpp/constants.h"
#include "talk/xmpp/xmppengine.h"

namespace buzz {

PubsubTask::PubsubTask(XmppTaskParentInterface* parent,
                       const buzz::Jid& pubsub_node_jid)
    : buzz::XmppTask(parent, buzz::XmppEngine::HL_SENDER),
      pubsub_node_jid_(pubsub_node_jid) {
}

PubsubTask::~PubsubTask() {
}

// Checks for pubsub publish events as well as responses to get IQs.
bool PubsubTask::HandleStanza(const buzz::XmlElement* stanza) {
  const buzz::QName& stanza_name(stanza->Name());
  if (stanza_name == buzz::QN_MESSAGE) {
    if (MatchStanzaFrom(stanza, pubsub_node_jid_)) {
      const buzz::XmlElement* pubsub_event_item =
          stanza->FirstNamed(QN_PUBSUB_EVENT);
      if (pubsub_event_item != NULL) {
        QueueStanza(pubsub_event_item);
        return true;
      }
    }
  } else if (stanza_name == buzz::QN_IQ) {
    if (MatchResponseIq(stanza, pubsub_node_jid_, task_id())) {
      const buzz::XmlElement* pubsub_item = stanza->FirstNamed(QN_PUBSUB);
      if (pubsub_item != NULL) {
        QueueStanza(pubsub_item);
        return true;
      }
    }
  }
  return false;
}

int PubsubTask::ProcessResponse() {
  const buzz::XmlElement* stanza = NextStanza();
  if (stanza == NULL) {
    return STATE_BLOCKED;
  }

  if (stanza->Attr(buzz::QN_TYPE) == buzz::STR_ERROR) {
    OnPubsubError(stanza->FirstNamed(buzz::QN_ERROR));
    return STATE_RESPONSE;
  }

  const buzz::QName& stanza_name(stanza->Name());
  if (stanza_name == QN_PUBSUB_EVENT) {
    HandlePubsubEventMessage(stanza);
  } else if (stanza_name == QN_PUBSUB) {
    HandlePubsubIqGetResponse(stanza);
  }

  return STATE_RESPONSE;
}

// Registers a function pointer to be called when the value of the pubsub
// node changes.
// Note that this does not actually change the XMPP pubsub
// subscription. All publish events are always received by everyone in the
// MUC. This function just controls whether the handle function will get
// called when the event is received.
bool PubsubTask::SubscribeToNode(const std::string& pubsub_node,
                                 NodeHandler handler) {
  subscribed_nodes_[pubsub_node] = handler;
  talk_base::scoped_ptr<buzz::XmlElement> get_iq_request(
      MakeIq(buzz::STR_GET, pubsub_node_jid_, task_id()));
  if (get_iq_request.get() == NULL) {
    return false;
  }
  buzz::XmlElement* pubsub_element = new buzz::XmlElement(QN_PUBSUB, true);
  buzz::XmlElement* items_element = new buzz::XmlElement(QN_PUBSUB_ITEMS, true);

  items_element->AddAttr(buzz::QN_NODE, pubsub_node);
  pubsub_element->AddElement(items_element);
  get_iq_request->AddElement(pubsub_element);

  if (SendStanza(get_iq_request.get()) != buzz::XMPP_RETURN_OK) {
    return false;
  }

  return true;
}

void PubsubTask::UnsubscribeFromNode(const std::string& pubsub_node) {
  subscribed_nodes_.erase(pubsub_node);
}

void PubsubTask::OnPubsubError(const buzz::XmlElement* error_stanza) {
}

// Checks for a pubsub event message like the following:
//
//  <message from="muvc-private-chat-some-id@groupchat.google.com"
//   to="john@site.com/gcomm582B14C9">
//    <event xmlns:"http://jabber.org/protocol/pubsub#event">
//      <items node="node-name">
//        <item id="some-id">
//          <payload/>
//        </item>
//      </items>
//    </event>
//  </message>
//
// It also checks for retraction event messages like the following:
//
//  <message from="muvc-private-chat-some-id@groupchat.google.com"
//   to="john@site.com/gcomm582B14C9">
//    <event xmlns:"http://jabber.org/protocol/pubsub#event">
//      <items node="node-name">
//        <retract id="some-id"/>
//      </items>
//    </event>
//  </message>
void PubsubTask::HandlePubsubEventMessage(
    const buzz::XmlElement* pubsub_event) {
  ASSERT(pubsub_event->Name() == QN_PUBSUB_EVENT);
  for (const buzz::XmlChild* child = pubsub_event->FirstChild();
       child != NULL;
       child = child->NextChild()) {
    const buzz::XmlElement* child_element = child->AsElement();
    const buzz::QName& child_name(child_element->Name());
    if (child_name == QN_PUBSUB_EVENT_ITEMS) {
      HandlePubsubItems(child_element);
    }
  }
}

// Checks for a response to an pubsub IQ get like the following:
//
//  <iq from="muvc-private-chat-some-id@groupchat.google.com"
//   to="john@site.com/gcomm582B14C9"
//   type="result">
//    <pubsub xmlns:"http://jabber.org/protocol/pubsub">
//      <items node="node-name">
//        <item id="some-id">
//          <payload/>
//        </item>
//      </items>
//    </event>
//  </message>
void PubsubTask::HandlePubsubIqGetResponse(
    const buzz::XmlElement* pubsub_iq_response) {
  ASSERT(pubsub_iq_response->Name() == QN_PUBSUB);
  for (const buzz::XmlChild* child = pubsub_iq_response->FirstChild();
       child != NULL;
       child = child->NextChild()) {
    const buzz::XmlElement* child_element = child->AsElement();
    const buzz::QName& child_name(child_element->Name());
    if (child_name == QN_PUBSUB_ITEMS) {
      HandlePubsubItems(child_element);
    }
  }
}

// Calls registered handlers in response to pubsub event or response to
// IQ pubsub get.
// 'items' is the child of a pubsub#event:event node or pubsub:pubsub node.
void PubsubTask::HandlePubsubItems(const buzz::XmlElement* items) {
  ASSERT(items->HasAttr(QN_NODE));
  const std::string& node_name(items->Attr(QN_NODE));
  NodeSubscriptions::iterator iter = subscribed_nodes_.find(node_name);
  if (iter != subscribed_nodes_.end()) {
    NodeHandler handler = iter->second;
    const buzz::XmlElement* item = items->FirstElement();
    while (item != NULL) {
      const buzz::QName& item_name(item->Name());
      if (item_name != QN_PUBSUB_EVENT_ITEM &&
          item_name != QN_PUBSUB_EVENT_RETRACT &&
          item_name != QN_PUBSUB_ITEM) {
        continue;
      }

      (this->*handler)(item);
      item = item->NextElement();
    }
    return;
  }
}

}
