/*
 * 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 char** 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_)
    return Jid();

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

XmppPresenceAvailable
XmppPresenceImpl::available() const {
  if (!raw_xml_)
    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_)
    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_)
    return XMPP_PRESENCE_DEFAULT;

  XmppPresenceShow show = XMPP_PRESENCE_DEFAULT;
  StringToPresenceShow(raw_xml_->TextNamed(QN_SHOW), &show);
  return show;
}

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

  const char* 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_)
    return 0;

  int raw_priority = 0;
  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_)
    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_)
    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_)
    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;
}

XmppPresenceConnectionStatus
XmppPresenceImpl::connection_status() const {
  if (!raw_xml_)
      return XMPP_CONNECTION_STATUS_UNKNOWN;

  XmlElement* con = raw_xml_->FirstNamed(QN_GOOGLE_PSTN_CONFERENCE_STATUS);
  if (con) {
    std::string status = con->Attr(QN_ATTR_STATUS);
    if (status == STR_PSTN_CONFERENCE_STATUS_CONNECTING)
      return XMPP_CONNECTION_STATUS_CONNECTING;
    else if (status == STR_PSTN_CONFERENCE_STATUS_CONNECTED)
      return XMPP_CONNECTION_STATUS_CONNECTED;
    else if (status == STR_PSTN_CONFERENCE_STATUS_HANGUP)
        return XMPP_CONNECTION_STATUS_HANGUP;
  }

  return XMPP_CONNECTION_STATUS_CONNECTED;
}

const std::string
XmppPresenceImpl::google_user_id() const {
  if (!raw_xml_)
    return std::string();

  XmlElement* muc_user_x = raw_xml_->FirstNamed(QN_MUC_USER_X);
  if (muc_user_x) {
    XmlElement* muc_user_item = muc_user_x->FirstNamed(QN_MUC_USER_ITEM);
    if (muc_user_item) {
      return muc_user_item->Attr(QN_GOOGLE_USER_ID);
    }
  }

  return std::string();
}

const std::string
XmppPresenceImpl::nickname() const {
  if (!raw_xml_)
    return std::string();

  XmlElement* nickname = raw_xml_->FirstNamed(QN_NICKNAME);
  if (nickname) {
    return nickname->BodyText();
  }

  return std::string();
}

const XmlElement*
XmppPresenceImpl::raw_xml() const {
  if (!raw_xml_)
    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;

  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_)
    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_)
    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_)
    return XMPP_SUBSCRIPTION_NONE;

  XmppSubscriptionState state = XMPP_SUBSCRIPTION_NONE;

  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_)
    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_)
    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_)
    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_)
    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());
}

}
