/*
 * libjingle
 * Copyright 2004--2005, 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 <vector>
#include <string>
#include <map>
#include <algorithm>
#include <sstream>
#include <iostream>
#include "talk/base/common.h"
#include "talk/base/stringencode.h"
#include "talk/xmpp/constants.h"
#include "talk/xmpp/rostermoduleimpl.h"

namespace buzz {

// enum prase and persist helpers ----------------------------------------------
static bool
StringToPresenceShow(const std::string& input, XmppPresenceShow* show)
{
  // If this becomes a perf issue we can use a hash or a map here
  if (STR_SHOW_AWAY == input)
    *show = XMPP_PRESENCE_AWAY;
  else if (STR_SHOW_DND == input)
    *show = XMPP_PRESENCE_DND;
  else if (STR_SHOW_XA == input)
    *show = XMPP_PRESENCE_XA;
  else if (STR_SHOW_CHAT == input)
    *show = XMPP_PRESENCE_CHAT;
  else if (STR_EMPTY == input)
    *show = XMPP_PRESENCE_DEFAULT;
  else
    return false;

  return true;
}

static bool
PresenceShowToString(XmppPresenceShow show, const std::string ** output)
{
  switch(show) {
    case XMPP_PRESENCE_AWAY:
      *output = &STR_SHOW_AWAY;
      return true;
    case XMPP_PRESENCE_CHAT:
      *output = &STR_SHOW_CHAT;
      return true;
    case XMPP_PRESENCE_XA:
      *output = &STR_SHOW_XA;
      return true;
    case XMPP_PRESENCE_DND:
      *output = &STR_SHOW_DND;
      return true;
    case XMPP_PRESENCE_DEFAULT:
      *output = &STR_EMPTY;
      return true;
  }

  *output = &STR_EMPTY;
  return false;
}

static bool
StringToSubscriptionState(const std::string& subscription,
                          const std::string& ask,
                          XmppSubscriptionState* state)
{
  if (ask == "subscribe")
  {
    if (subscription == "none") {
      *state = XMPP_SUBSCRIPTION_NONE_ASKED;
      return true;
    }
    if (subscription == "from") {
      *state = XMPP_SUBSCRIPTION_FROM_ASKED;
      return true;
    }
  } else if (ask == STR_EMPTY)
  {
    if (subscription == "none") {
      *state = XMPP_SUBSCRIPTION_NONE;
      return true;
    }
    if (subscription == "from") {
      *state = XMPP_SUBSCRIPTION_FROM;
      return true;
    }
    if (subscription == "to") {
      *state = XMPP_SUBSCRIPTION_TO;
      return true;
    }
    if (subscription == "both") {
      *state = XMPP_SUBSCRIPTION_BOTH;
      return true;
    }
  }

  return false;
}

static bool
StringToSubscriptionRequestType(const std::string& string,
                                XmppSubscriptionRequestType* type)
{
  if (string == "subscribe")
    *type = XMPP_REQUEST_SUBSCRIBE;
  else if (string == "unsubscribe")
    *type = XMPP_REQUEST_UNSUBSCRIBE;
  else if (string == "subscribed")
    *type = XMPP_REQUEST_SUBSCRIBED;
  else if (string == "unsubscribed")
    *type = XMPP_REQUEST_UNSUBSCRIBED;
  else
    return false;
  return true;
}

// XmppPresenceImpl class ------------------------------------------------------
XmppPresence*
XmppPresence::Create() {
  return new XmppPresenceImpl();
}

XmppPresenceImpl::XmppPresenceImpl() {
}

const Jid
XmppPresenceImpl::jid() const {
  if (!raw_xml_.get())
    return JID_EMPTY;

  return Jid(raw_xml_->Attr(QN_FROM));
}

XmppPresenceAvailable
XmppPresenceImpl::available() const {
  if (!raw_xml_.get())
    return XMPP_PRESENCE_UNAVAILABLE;

  if (raw_xml_->Attr(QN_TYPE) == "unavailable")
    return XMPP_PRESENCE_UNAVAILABLE;
  else if (raw_xml_->Attr(QN_TYPE) == "error")
    return XMPP_PRESENCE_ERROR;
  else
    return XMPP_PRESENCE_AVAILABLE;
}

XmppReturnStatus
XmppPresenceImpl::set_available(XmppPresenceAvailable available) {
  if (!raw_xml_.get())
    CreateRawXmlSkeleton();

  if (available == XMPP_PRESENCE_AVAILABLE)
    raw_xml_->ClearAttr(QN_TYPE);
  else if (available == XMPP_PRESENCE_UNAVAILABLE)
    raw_xml_->SetAttr(QN_TYPE, "unavailable");
  else if (available == XMPP_PRESENCE_ERROR)
    raw_xml_->SetAttr(QN_TYPE, "error");
  return XMPP_RETURN_OK;
}

XmppPresenceShow
XmppPresenceImpl::presence_show() const {
  if (!raw_xml_.get())
    return XMPP_PRESENCE_DEFAULT;

  XmppPresenceShow show;

  if (StringToPresenceShow(raw_xml_->TextNamed(QN_SHOW), &show))
    return show;

  return XMPP_PRESENCE_DEFAULT;
}

XmppReturnStatus
XmppPresenceImpl::set_presence_show(XmppPresenceShow show) {
  if (!raw_xml_.get())
    CreateRawXmlSkeleton();

  const std::string* show_string;

  if(!PresenceShowToString(show, &show_string))
    return XMPP_RETURN_BADARGUMENT;

  raw_xml_->ClearNamedChildren(QN_SHOW);

  if (show!=XMPP_PRESENCE_DEFAULT) {
    raw_xml_->AddElement(new XmlElement(QN_SHOW));
    raw_xml_->AddText(*show_string, 1);
  }

  return XMPP_RETURN_OK;
}

int
XmppPresenceImpl::priority() const {
  if (!raw_xml_.get())
    return 0;

  int raw_priority;
  if (!talk_base::FromString(raw_xml_->TextNamed(QN_PRIORITY), &raw_priority))
    raw_priority = 0;
  if (raw_priority < -128)
    raw_priority = -128;
  if (raw_priority > 127)
    raw_priority = 127;

  return raw_priority;
}

XmppReturnStatus
XmppPresenceImpl::set_priority(int priority) {
  if (!raw_xml_.get())
    CreateRawXmlSkeleton();

  if (priority < -128 || priority > 127)
    return XMPP_RETURN_BADARGUMENT;

  raw_xml_->ClearNamedChildren(QN_PRIORITY);
  if (0 != priority) {
    std::string priority_string;
    if (talk_base::ToString(priority, &priority_string)) {
      raw_xml_->AddElement(new XmlElement(QN_PRIORITY));
      raw_xml_->AddText(priority_string, 1);
    }
  }

  return XMPP_RETURN_OK;
}

const std::string&
XmppPresenceImpl::status() const {
  if (!raw_xml_.get())
    return STR_EMPTY;

  XmlElement* status_element;
  XmlElement* element;

  // Search for a status element with no xml:lang attribute on it.  if we can't
  // find that then just return the first status element in the stanza.
  for (status_element = element = raw_xml_->FirstNamed(QN_STATUS);
       element;
       element = element->NextNamed(QN_STATUS)) {
    if (!element->HasAttr(QN_XML_LANG)) {
      status_element = element;
      break;
    }
  }

  if (status_element) {
    return status_element->BodyText();
  }

  return STR_EMPTY;
}

XmppReturnStatus
XmppPresenceImpl::set_status(const std::string& status) {
  if (!raw_xml_.get())
    CreateRawXmlSkeleton();

  raw_xml_->ClearNamedChildren(QN_STATUS);

  if (status != STR_EMPTY) {
    raw_xml_->AddElement(new XmlElement(QN_STATUS));
    raw_xml_->AddText(status, 1);
  }

  return XMPP_RETURN_OK;
}

const XmlElement*
XmppPresenceImpl::raw_xml() const {
  if (!raw_xml_.get())
    const_cast<XmppPresenceImpl*>(this)->CreateRawXmlSkeleton();
  return raw_xml_.get();
}

XmppReturnStatus
XmppPresenceImpl::set_raw_xml(const XmlElement * xml) {
  if (!xml ||
      xml->Name() != QN_PRESENCE)
    return XMPP_RETURN_BADARGUMENT;

  const std::string& type = xml->Attr(QN_TYPE);
  if (type != STR_EMPTY && type != "unavailable")
    return XMPP_RETURN_BADARGUMENT;

  raw_xml_.reset(new XmlElement(*xml));

  return XMPP_RETURN_OK;
}

void
XmppPresenceImpl::CreateRawXmlSkeleton() {
  raw_xml_.reset(new XmlElement(QN_PRESENCE));
}

// XmppRosterContactImpl -------------------------------------------------------
XmppRosterContact*
XmppRosterContact::Create() {
  return new XmppRosterContactImpl();
}

XmppRosterContactImpl::XmppRosterContactImpl() {
  ResetGroupCache();
}

void
XmppRosterContactImpl::SetXmlFromWire(const XmlElement* xml) {
  ResetGroupCache();
  if (xml)
    raw_xml_.reset(new XmlElement(*xml));
  else
    raw_xml_.reset(NULL);
}

void
XmppRosterContactImpl::ResetGroupCache() {
  group_count_ = -1;
  group_index_returned_ = -1;
  group_returned_ = NULL;
}

const Jid
XmppRosterContactImpl::jid() const {
  return Jid(raw_xml_->Attr(QN_JID));
}

XmppReturnStatus
XmppRosterContactImpl::set_jid(const Jid& jid)
{
  if (!raw_xml_.get())
    CreateRawXmlSkeleton();

  if (!jid.IsValid())
    return XMPP_RETURN_BADARGUMENT;

  raw_xml_->SetAttr(QN_JID, jid.Str());

  return XMPP_RETURN_OK;
}

const std::string&
XmppRosterContactImpl::name() const {
  return raw_xml_->Attr(QN_NAME);
}

XmppReturnStatus
XmppRosterContactImpl::set_name(const std::string& name) {
  if (!raw_xml_.get())
    CreateRawXmlSkeleton();

  if (name == STR_EMPTY)
    raw_xml_->ClearAttr(QN_NAME);
  else
    raw_xml_->SetAttr(QN_NAME, name);

  return XMPP_RETURN_OK;
}

XmppSubscriptionState
XmppRosterContactImpl::subscription_state() const {
  if (!raw_xml_.get())
    return XMPP_SUBSCRIPTION_NONE;

  XmppSubscriptionState state;

  if (StringToSubscriptionState(raw_xml_->Attr(QN_SUBSCRIPTION),
                                raw_xml_->Attr(QN_ASK),
                                &state))
    return state;

  return XMPP_SUBSCRIPTION_NONE;
}

size_t
XmppRosterContactImpl::GetGroupCount() const {
  if (!raw_xml_.get())
    return 0;

  if (-1 == group_count_) {
    XmlElement *group_element = raw_xml_->FirstNamed(QN_ROSTER_GROUP);
    int group_count = 0;
    while(group_element) {
      group_count++;
      group_element = group_element->NextNamed(QN_ROSTER_GROUP);
    }

    ASSERT(group_count > 0); // protect the cast
    XmppRosterContactImpl * me = const_cast<XmppRosterContactImpl*>(this);
    me->group_count_ = group_count;
  }

  return group_count_;
}

const std::string&
XmppRosterContactImpl::GetGroup(size_t index) const {
  if (index >= GetGroupCount())
    return STR_EMPTY;

  // We cache the last group index and element that we returned.  This way
  // going through the groups in order is order n and not n^2.  This could be
  // enhanced if necessary by starting at the cached value if the index asked
  // is after the cached one.
  if (group_index_returned_ >= 0 &&
      index == static_cast<size_t>(group_index_returned_) + 1)
  {
    XmppRosterContactImpl * me = const_cast<XmppRosterContactImpl*>(this);
    me->group_returned_ = group_returned_->NextNamed(QN_ROSTER_GROUP);
    ASSERT(group_returned_ != NULL);
    me->group_index_returned_++;
  } else if (group_index_returned_ < 0 ||
             static_cast<size_t>(group_index_returned_) != index) {
    XmlElement * group_element = raw_xml_->FirstNamed(QN_ROSTER_GROUP);
    size_t group_index = 0;
    while(group_index < index) {
      ASSERT(group_element != NULL);
      group_index++;
      group_element = group_element->NextNamed(QN_ROSTER_GROUP);
    }

    XmppRosterContactImpl * me = const_cast<XmppRosterContactImpl*>(this);
    me->group_index_returned_ = static_cast<int>(group_index);
    me->group_returned_ = group_element;
  }

  return group_returned_->BodyText();
}

XmppReturnStatus
XmppRosterContactImpl::AddGroup(const std::string& group) {
  if (group == STR_EMPTY)
    return XMPP_RETURN_BADARGUMENT;

  if (!raw_xml_.get())
    CreateRawXmlSkeleton();

  if (FindGroup(group, NULL, NULL))
    return XMPP_RETURN_OK;

  raw_xml_->AddElement(new XmlElement(QN_ROSTER_GROUP));
  raw_xml_->AddText(group, 1);
  ++group_count_;

  return XMPP_RETURN_OK;
}

XmppReturnStatus
XmppRosterContactImpl::RemoveGroup(const std::string& group) {
  if (group == STR_EMPTY)
    return XMPP_RETURN_BADARGUMENT;

  if (!raw_xml_.get())
    return XMPP_RETURN_OK;

  XmlChild * child_before;
  if (FindGroup(group, NULL, &child_before)) {
    raw_xml_->RemoveChildAfter(child_before);
    ResetGroupCache();
  }
  return XMPP_RETURN_OK;
}

bool
XmppRosterContactImpl::FindGroup(const std::string& group,
                                 XmlElement** element,
                                 XmlChild** child_before) {
  XmlChild * prev_child = NULL;
  XmlChild * next_child;
  XmlChild * child;
  for (child = raw_xml_->FirstChild(); child; child = next_child) {
    next_child = child->NextChild();
    if (!child->IsText() &&
        child->AsElement()->Name() == QN_ROSTER_GROUP &&
        child->AsElement()->BodyText() == group) {
      if (element)
        *element = child->AsElement();
      if (child_before)
        *child_before = prev_child;
      return true;
    }
    prev_child = child;
  }

  return false;
}

const XmlElement*
XmppRosterContactImpl::raw_xml() const {
  if (!raw_xml_.get())
    const_cast<XmppRosterContactImpl*>(this)->CreateRawXmlSkeleton();
  return raw_xml_.get();
}

XmppReturnStatus
XmppRosterContactImpl::set_raw_xml(const XmlElement* xml) {
  if (!xml ||
      xml->Name() != QN_ROSTER_ITEM ||
      xml->HasAttr(QN_SUBSCRIPTION) ||
      xml->HasAttr(QN_ASK))
    return XMPP_RETURN_BADARGUMENT;

  ResetGroupCache();

  raw_xml_.reset(new XmlElement(*xml));

  return XMPP_RETURN_OK;
}

void
XmppRosterContactImpl::CreateRawXmlSkeleton() {
  raw_xml_.reset(new XmlElement(QN_ROSTER_ITEM));
}

// XmppRosterModuleImpl --------------------------------------------------------
XmppRosterModule *
XmppRosterModule::Create() {
  return new XmppRosterModuleImpl();
}

XmppRosterModuleImpl::XmppRosterModuleImpl() :
  roster_handler_(NULL),
  incoming_presence_map_(new JidPresenceVectorMap()),
  incoming_presence_vector_(new PresenceVector()),
  contacts_(new ContactVector()) {

}

XmppRosterModuleImpl::~XmppRosterModuleImpl() {
  DeleteIncomingPresence();
  DeleteContacts();
}

XmppReturnStatus
XmppRosterModuleImpl::set_roster_handler(XmppRosterHandler * handler) {
  roster_handler_ = handler;
  return XMPP_RETURN_OK;
}

XmppRosterHandler*
XmppRosterModuleImpl::roster_handler() {
  return roster_handler_;
}

XmppPresence*
XmppRosterModuleImpl::outgoing_presence() {
  return &outgoing_presence_;
}

XmppReturnStatus
XmppRosterModuleImpl::BroadcastPresence() {
  // Scrub the outgoing presence
  const XmlElement* element = outgoing_presence_.raw_xml();

  ASSERT(!element->HasAttr(QN_TO) &&
         !element->HasAttr(QN_FROM) &&
          (element->Attr(QN_TYPE) == STR_EMPTY ||
           element->Attr(QN_TYPE) == "unavailable"));

  if (!engine())
    return XMPP_RETURN_BADSTATE;

  return engine()->SendStanza(element);
}

XmppReturnStatus
XmppRosterModuleImpl::SendDirectedPresence(const XmppPresence* presence,
                                           const Jid& to_jid) {
  if (!presence)
    return XMPP_RETURN_BADARGUMENT;

  if (!engine())
    return XMPP_RETURN_BADSTATE;

  XmlElement element(*(presence->raw_xml()));

  if (element.Name() != QN_PRESENCE ||
      element.HasAttr(QN_TO) ||
      element.HasAttr(QN_FROM))
    return XMPP_RETURN_BADARGUMENT;

  if (element.HasAttr(QN_TYPE)) {
    if (element.Attr(QN_TYPE) != STR_EMPTY &&
        element.Attr(QN_TYPE) != "unavailable") {
      return XMPP_RETURN_BADARGUMENT;
    }
  }

  element.SetAttr(QN_TO, to_jid.Str());

  return engine()->SendStanza(&element);
}

size_t
XmppRosterModuleImpl::GetIncomingPresenceCount() {
  return incoming_presence_vector_->size();
}

const XmppPresence*
XmppRosterModuleImpl::GetIncomingPresence(size_t index) {
  if (index >= incoming_presence_vector_->size())
    return NULL;
  return (*incoming_presence_vector_)[index];
}

size_t
XmppRosterModuleImpl::GetIncomingPresenceForJidCount(const Jid& jid)
{
  // find the vector in the map
  JidPresenceVectorMap::iterator pos;
  pos = incoming_presence_map_->find(jid);
  if (pos == incoming_presence_map_->end())
    return 0;

  ASSERT(pos->second != NULL);

  return pos->second->size();
}

const XmppPresence*
XmppRosterModuleImpl::GetIncomingPresenceForJid(const Jid& jid,
                                                size_t index) {
  JidPresenceVectorMap::iterator pos;
  pos = incoming_presence_map_->find(jid);
  if (pos == incoming_presence_map_->end())
    return NULL;

  ASSERT(pos->second != NULL);

  if (index >= pos->second->size())
    return NULL;

  return (*pos->second)[index];
}

XmppReturnStatus
XmppRosterModuleImpl::RequestRosterUpdate() {
  if (!engine())
    return XMPP_RETURN_BADSTATE;

  XmlElement roster_get(QN_IQ);
  roster_get.AddAttr(QN_TYPE, "get");
  roster_get.AddAttr(QN_ID, engine()->NextId());
  roster_get.AddElement(new XmlElement(QN_ROSTER_QUERY, true));
  return engine()->SendIq(&roster_get, this, NULL);
}

size_t
XmppRosterModuleImpl::GetRosterContactCount() {
  return contacts_->size();
}

const XmppRosterContact*
XmppRosterModuleImpl::GetRosterContact(size_t index) {
  if (index >= contacts_->size())
    return NULL;
  return (*contacts_)[index];
}

class RosterPredicate {
public:
  explicit RosterPredicate(const Jid& jid) : jid_(jid) {
  }

  bool operator() (XmppRosterContactImpl *& contact) {
    return contact->jid() == jid_;
  }

private:
  Jid jid_;
};

const XmppRosterContact*
XmppRosterModuleImpl::FindRosterContact(const Jid& jid) {
  ContactVector::iterator pos;

  pos = std::find_if(contacts_->begin(),
                     contacts_->end(),
                     RosterPredicate(jid));
  if (pos == contacts_->end())
    return NULL;

  return *pos;
}

XmppReturnStatus
XmppRosterModuleImpl::RequestRosterChange(
  const XmppRosterContact* contact) {
  if (!contact)
    return XMPP_RETURN_BADARGUMENT;

  Jid jid = contact->jid();

  if (!jid.IsValid())
    return XMPP_RETURN_BADARGUMENT;

  if (!engine())
    return XMPP_RETURN_BADSTATE;

  const XmlElement* contact_xml = contact->raw_xml();
  if (contact_xml->Name() != QN_ROSTER_ITEM ||
      contact_xml->HasAttr(QN_SUBSCRIPTION) ||
      contact_xml->HasAttr(QN_ASK))
    return XMPP_RETURN_BADARGUMENT;

  XmlElement roster_add(QN_IQ);
  roster_add.AddAttr(QN_TYPE, "set");
  roster_add.AddAttr(QN_ID, engine()->NextId());
  roster_add.AddElement(new XmlElement(QN_ROSTER_QUERY, true));
  roster_add.AddElement(new XmlElement(*contact_xml), 1);

  return engine()->SendIq(&roster_add, this, NULL);
}

XmppReturnStatus
XmppRosterModuleImpl::RequestRosterRemove(const Jid& jid) {
  if (!jid.IsValid())
    return XMPP_RETURN_BADARGUMENT;

  if (!engine())
    return XMPP_RETURN_BADSTATE;

  XmlElement roster_add(QN_IQ);
  roster_add.AddAttr(QN_TYPE, "set");
  roster_add.AddAttr(QN_ID, engine()->NextId());
  roster_add.AddElement(new XmlElement(QN_ROSTER_QUERY, true));
  roster_add.AddAttr(QN_JID, jid.Str(), 1);
  roster_add.AddAttr(QN_SUBSCRIPTION, "remove", 1);

  return engine()->SendIq(&roster_add, this, NULL);
}

XmppReturnStatus
XmppRosterModuleImpl::RequestSubscription(const Jid& jid) {
  return SendSubscriptionRequest(jid, "subscribe");
}

XmppReturnStatus
XmppRosterModuleImpl::CancelSubscription(const Jid& jid) {
  return SendSubscriptionRequest(jid, "unsubscribe");
}

XmppReturnStatus
XmppRosterModuleImpl::ApproveSubscriber(const Jid& jid) {
  return SendSubscriptionRequest(jid, "subscribed");
}

XmppReturnStatus
XmppRosterModuleImpl::CancelSubscriber(const Jid& jid) {
  return SendSubscriptionRequest(jid, "unsubscribed");
}

void
XmppRosterModuleImpl::IqResponse(XmppIqCookie, const XmlElement * stanza) {
  // The only real Iq response that we expect to recieve are initial roster
  // population
  if (stanza->Attr(QN_TYPE) == "error")
  {
    if (roster_handler_)
      roster_handler_->RosterError(this, stanza);

    return;
  }

  ASSERT(stanza->Attr(QN_TYPE) == "result");

  InternalRosterItems(stanza);
}

bool
XmppRosterModuleImpl::HandleStanza(const XmlElement * stanza)
{
  ASSERT(engine() != NULL);

  // There are two types of stanzas that we care about: presence and roster push
  // Iqs
  if (stanza->Name() == QN_PRESENCE) {
    const std::string&  jid_string = stanza->Attr(QN_FROM);
    Jid jid(jid_string);

    if (!jid.IsValid())
      return false; // if the Jid isn't valid, don't process

    const std::string& type = stanza->Attr(QN_TYPE);
    XmppSubscriptionRequestType request_type;
    if (StringToSubscriptionRequestType(type, &request_type))
      InternalSubscriptionRequest(jid, stanza, request_type);
    else if (type == "unavailable" || type == STR_EMPTY)
      InternalIncomingPresence(jid, stanza);
    else if (type == "error")
      InternalIncomingPresenceError(jid, stanza);
    else
      return false;

    return true;
  } else if (stanza->Name() == QN_IQ) {
    const XmlElement * roster_query = stanza->FirstNamed(QN_ROSTER_QUERY);
    if (!roster_query || stanza->Attr(QN_TYPE) != "set")
      return false;

    InternalRosterItems(stanza);

    // respond to the IQ
    XmlElement result(QN_IQ);
    result.AddAttr(QN_TYPE, "result");
    result.AddAttr(QN_TO, stanza->Attr(QN_FROM));
    result.AddAttr(QN_ID, stanza->Attr(QN_ID));

    engine()->SendStanza(&result);
    return true;
  }

  return false;
}

void
XmppRosterModuleImpl::DeleteIncomingPresence() {
  // Clear out the vector of all presence notifications
  {
    PresenceVector::iterator pos;
    for (pos = incoming_presence_vector_->begin();
         pos < incoming_presence_vector_->end();
         ++pos) {
      XmppPresenceImpl * presence = *pos;
      *pos = NULL;
      delete presence;
    }
    incoming_presence_vector_->clear();
  }

  // Clear out all of the small presence vectors per Jid
  {
    JidPresenceVectorMap::iterator pos;
    for (pos = incoming_presence_map_->begin();
         pos != incoming_presence_map_->end();
         ++pos) {
      PresenceVector* presence_vector = pos->second;
      pos->second = NULL;
      delete presence_vector;
    }
    incoming_presence_map_->clear();
  }
}

void
XmppRosterModuleImpl::DeleteContacts() {
  ContactVector::iterator pos;
  for (pos = contacts_->begin();
       pos < contacts_->end();
       ++pos) {
    XmppRosterContact* contact = *pos;
    *pos = NULL;
    delete contact;
  }
  contacts_->clear();
}

XmppReturnStatus
XmppRosterModuleImpl::SendSubscriptionRequest(const Jid& jid,
                                              const std::string& type) {
  if (!jid.IsValid())
    return XMPP_RETURN_BADARGUMENT;

  if (!engine())
    return XMPP_RETURN_BADSTATE;

  XmlElement presence_request(QN_PRESENCE);
  presence_request.AddAttr(QN_TO, jid.Str());
  presence_request.AddAttr(QN_TYPE, type);

  return engine()->SendStanza(&presence_request);
}


void
XmppRosterModuleImpl::InternalSubscriptionRequest(const Jid& jid,
                                                  const XmlElement* stanza,
                                                  XmppSubscriptionRequestType
                                                    request_type) {
  if (roster_handler_)
    roster_handler_->SubscriptionRequest(this, jid, request_type, stanza);
}

class PresencePredicate {
public:
  explicit PresencePredicate(const Jid& jid) : jid_(jid) {
  }

  bool operator() (XmppPresenceImpl *& contact) {
    return contact->jid() == jid_;
  }

private:
  Jid jid_;
};

void
XmppRosterModuleImpl::InternalIncomingPresence(const Jid& jid,
                                               const XmlElement* stanza) {
  bool added = false;
  Jid bare_jid = jid.BareJid();

  // First add the presence to the map
  JidPresenceVectorMap::iterator pos;
  pos = incoming_presence_map_->find(jid.BareJid());
  if (pos == incoming_presence_map_->end()) {
    // Insert a new entry into the map.  Get the position of this new entry
    pos = (incoming_presence_map_->insert(
            std::make_pair(bare_jid, new PresenceVector()))).first;
  }

  PresenceVector * presence_vector = pos->second;
  ASSERT(presence_vector != NULL);

  // Try to find this jid in the bare jid bucket
  PresenceVector::iterator presence_pos;
  XmppPresenceImpl* presence;
  presence_pos = std::find_if(presence_vector->begin(),
                              presence_vector->end(),
                              PresencePredicate(jid));

  // Update/add it to the bucket
  if (presence_pos == presence_vector->end()) {
    presence = new XmppPresenceImpl();
    if (XMPP_RETURN_OK == presence->set_raw_xml(stanza)) {
      added = true;
      presence_vector->push_back(presence);
    } else {
      delete presence;
      presence = NULL;
    }
  } else {
    presence = *presence_pos;
    presence->set_raw_xml(stanza);
  }

  // now add to the comprehensive vector
  if (added)
    incoming_presence_vector_->push_back(presence);

  // Call back to the user with the changed presence information
  if (roster_handler_)
    roster_handler_->IncomingPresenceChanged(this, presence);
}


void
XmppRosterModuleImpl::InternalIncomingPresenceError(const Jid& jid,
                                                    const XmlElement* stanza) {
  if (roster_handler_)
    roster_handler_->SubscriptionError(this, jid, stanza);
}

void
XmppRosterModuleImpl::InternalRosterItems(const XmlElement* stanza) {
  const XmlElement* result_data = stanza->FirstNamed(QN_ROSTER_QUERY);
  if (!result_data)
    return; // unknown stuff in result!

  bool all_new = contacts_->empty();

  for (const XmlElement* roster_item = result_data->FirstNamed(QN_ROSTER_ITEM);
       roster_item;
       roster_item = roster_item->NextNamed(QN_ROSTER_ITEM))
  {
    const std::string& jid_string = roster_item->Attr(QN_JID);
    Jid jid(jid_string);
    if (!jid.IsValid())
      continue;

    // This algorithm is N^2 on the number of incoming contacts after the
    // initial load. There is no way to do this faster without allowing
    // duplicates, introducing more data structures or write a custom data
    // structure.  We'll see if this becomes a perf problem and fix it if it
    // does.
    ContactVector::iterator pos = contacts_->end();

    if (!all_new) {
      pos = std::find_if(contacts_->begin(),
                         contacts_->end(),
                         RosterPredicate(jid));
    }

    if (pos != contacts_->end()) { // Update/remove a current contact
      if (roster_item->Attr(QN_SUBSCRIPTION) == "remove") {
        XmppRosterContact* contact = *pos;
        contacts_->erase(pos);
        if (roster_handler_)
          roster_handler_->ContactRemoved(this, contact,
            std::distance(contacts_->begin(), pos));
        delete contact;
      } else {
        XmppRosterContact* old_contact = *pos;
        *pos = new XmppRosterContactImpl();
        (*pos)->SetXmlFromWire(roster_item);
        if (roster_handler_)
          roster_handler_->ContactChanged(this, old_contact,
            std::distance(contacts_->begin(), pos));
        delete old_contact;
      }
    } else { // Add a new contact
      XmppRosterContactImpl* contact = new XmppRosterContactImpl();
      contact->SetXmlFromWire(roster_item);
      contacts_->push_back(contact);
      if (roster_handler_ && !all_new)
        roster_handler_->ContactsAdded(this, contacts_->size() - 1, 1);
    }
  }

  // Send a consolidated update if all contacts are new
  if (roster_handler_ && all_new)
    roster_handler_->ContactsAdded(this, 0, contacts_->size());
}

}
