/*
 * 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 "talk/examples/call/presencepushtask.h"

#include "talk/base/stringencode.h"
#include "talk/examples/call/muc.h"
#include "talk/xmpp/constants.h"



namespace buzz {

// string helper functions -----------------------------------------------------

static bool
IsXmlSpace(int ch) {
  return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
}

static bool ListContainsToken(const std::string & list,
                              const std::string & token) {
  size_t i = list.find(token);
  if (i == std::string::npos || token.empty())
    return false;
  bool boundary_before = (i == 0 || IsXmlSpace(list[i - 1]));
  bool boundary_after = (i == list.length() - token.length() ||
                         IsXmlSpace(list[i + token.length()]));
  return boundary_before && boundary_after;
}


bool PresencePushTask::HandleStanza(const XmlElement * stanza) {
  if (stanza->Name() != QN_PRESENCE)
    return false;
  QueueStanza(stanza);
  return true;
}

static bool IsUtf8FirstByte(int c) {
  return (((c)&0x80)==0) || // is single byte
    ((unsigned char)((c)-0xc0)<0x3e); // or is lead byte
}

int PresencePushTask::ProcessStart() {
  const XmlElement * stanza = NextStanza();
  if (stanza == NULL)
    return STATE_BLOCKED;

  Jid from(stanza->Attr(QN_FROM));
  std::map<Jid, buzz::Muc*>::const_iterator elem =
      client_->mucs().find(from.BareJid());
  if (elem == client_->mucs().end()) {
    HandlePresence(from, stanza);
  } else {
    HandleMucPresence(elem->second, from, stanza);
  }

  return STATE_START;
}

void PresencePushTask::HandlePresence(const Jid& from,
                                      const XmlElement* stanza) {
  if (stanza->Attr(QN_TYPE) == STR_ERROR)
    return;

  Status s;
  FillStatus(from, stanza, &s);
  SignalStatusUpdate(s);
}

void PresencePushTask::HandleMucPresence(buzz::Muc* muc,
                                         const Jid& from,
                                         const XmlElement* stanza) {
  if (from == muc->local_jid()) {
    if (!stanza->HasAttr(QN_TYPE)) {
      // We joined the MUC.
      const XmlElement* elem = stanza->FirstNamed(QN_MUC_USER_X);
      // Status code=110 or 100 is not guaranteed to be present, so we
      // only check the item element and Muc join status.
      if (elem) {
        if (elem->FirstNamed(QN_MUC_USER_ITEM) &&
            muc->state() == buzz::Muc::MUC_JOINING) {
          SignalMucJoined(muc->jid());
        }
      }
    } else {
      // We've been kicked. Bye.
      int error = 0;
      if (stanza->Attr(QN_TYPE) == STR_ERROR) {
        const XmlElement* elem = stanza->FirstNamed(QN_ERROR);
        if (elem && elem->HasAttr(QN_CODE)) {
          error = atoi(elem->Attr(QN_CODE).c_str());
        }
      }
      SignalMucLeft(muc->jid(), error);
    }
  } else {
    MucStatus s;
    FillMucStatus(from, stanza, &s);
    SignalMucStatusUpdate(muc->jid(), s);
  }
}

void PresencePushTask::FillStatus(const Jid& from, const XmlElement* stanza,
                                  Status* s) {
  s->set_jid(from);
  if (stanza->Attr(QN_TYPE) == STR_UNAVAILABLE) {
    s->set_available(false);
  } else {
    s->set_available(true);
    const XmlElement * status = stanza->FirstNamed(QN_STATUS);
    if (status != NULL) {
      s->set_status(status->BodyText());

      // Truncate status messages longer than 300 bytes
      if (s->status().length() > 300) {
        size_t len = 300;

        // Be careful not to split legal utf-8 chars in half
        while (!IsUtf8FirstByte(s->status()[len]) && len > 0) {
          len -= 1;
        }
        std::string truncated(s->status(), 0, len);
        s->set_status(truncated);
      }
    }

    const XmlElement * priority = stanza->FirstNamed(QN_PRIORITY);
    if (priority != NULL) {
      int pri;
      if (talk_base::FromString(priority->BodyText(), &pri)) {
        s->set_priority(pri);
      }
    }

    const XmlElement * show = stanza->FirstNamed(QN_SHOW);
    if (show == NULL || show->FirstChild() == NULL) {
      s->set_show(Status::SHOW_ONLINE);
    }
    else {
      if (show->BodyText() == "away") {
        s->set_show(Status::SHOW_AWAY);
      }
      else if (show->BodyText() == "xa") {
        s->set_show(Status::SHOW_XA);
      }
      else if (show->BodyText() == "dnd") {
        s->set_show(Status::SHOW_DND);
      }
      else if (show->BodyText() == "chat") {
        s->set_show(Status::SHOW_CHAT);
      }
      else {
        s->set_show(Status::SHOW_ONLINE);
      }
    }

    const XmlElement * caps = stanza->FirstNamed(QN_CAPS_C);
    if (caps != NULL) {
      std::string node = caps->Attr(QN_NODE);
      std::string ver = caps->Attr(QN_VER);
      std::string exts = caps->Attr(QN_EXT);

      s->set_know_capabilities(true);

      if (node == GOOGLE_CLIENT_NODE) {
        s->set_is_google_client(true);
        s->set_version(ver);
      }

      if (ListContainsToken(exts, "voice-v1")) {
        s->set_voice_capability(true);
      }
      if (ListContainsToken(exts, "video-v1")) {
        s->set_video_capability(true);
      }
    }

    const XmlElement* delay = stanza->FirstNamed(kQnDelayX);
    if (delay != NULL) {
      // Ideally we would parse this according to the Psuedo ISO-8601 rules
      // that are laid out in JEP-0082:
      // http://www.jabber.org/jeps/jep-0082.html
      std::string stamp = delay->Attr(kQnStamp);
      s->set_sent_time(stamp);
    }

    const XmlElement* nick = stanza->FirstNamed(QN_NICKNAME);
    if (nick) {
      s->set_nick(nick->BodyText());
    }
  }
}

void PresencePushTask::FillMucStatus(const Jid& from, const XmlElement* stanza,
                                     MucStatus* s) {
  FillStatus(from, stanza, s);
}

}
