/*
 * 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 <algorithm>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>
#include "talk/xmpp/constants.h"
#include "talk/xmpp/rostermoduleimpl.h"
#include "webrtc/base/common.h"
#include "webrtc/base/stringencode.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 (!rtc::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 (rtc::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_JOINING)
            return XMPP_CONNECTION_STATUS_JOINING;
    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());
}

}
