/*
 * 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/p2p/base/sessionmanager.h"

#include "talk/p2p/base/constants.h"
#include "talk/p2p/base/session.h"
#include "talk/p2p/base/sessionmessages.h"
#include "talk/xmpp/constants.h"
#include "talk/xmpp/jid.h"
#include "webrtc/base/common.h"
#include "webrtc/base/helpers.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/stringencode.h"

namespace cricket {

SessionManager::SessionManager(PortAllocator *allocator,
                               rtc::Thread *worker) {
  allocator_ = allocator;
  signaling_thread_ = rtc::Thread::Current();
  if (worker == NULL) {
    worker_thread_ = rtc::Thread::Current();
  } else {
    worker_thread_ = worker;
  }
  timeout_ = 50;
}

SessionManager::~SessionManager() {
  // Note: Session::Terminate occurs asynchronously, so it's too late to
  // delete them now.  They better be all gone.
  ASSERT(session_map_.empty());
  // TerminateAll();
  SignalDestroyed();
}

void SessionManager::AddClient(const std::string& content_type,
                               SessionClient* client) {
  ASSERT(client_map_.find(content_type) == client_map_.end());
  client_map_[content_type] = client;
}

void SessionManager::RemoveClient(const std::string& content_type) {
  ClientMap::iterator iter = client_map_.find(content_type);
  ASSERT(iter != client_map_.end());
  client_map_.erase(iter);
}

SessionClient* SessionManager::GetClient(const std::string& content_type) {
  ClientMap::iterator iter = client_map_.find(content_type);
  return (iter != client_map_.end()) ? iter->second : NULL;
}

Session* SessionManager::CreateSession(const std::string& local_name,
                                       const std::string& content_type) {
  std::string id;
  return CreateSession(id, local_name, content_type);
}

Session* SessionManager::CreateSession(const std::string& id,
                                       const std::string& local_name,
                                       const std::string& content_type) {
  std::string sid =
      id.empty() ? rtc::ToString(rtc::CreateRandomId64()) : id;
  return CreateSession(local_name, local_name, sid, content_type, false);
}

Session* SessionManager::CreateSession(
    const std::string& local_name, const std::string& initiator_name,
    const std::string& sid, const std::string& content_type,
    bool received_initiate) {
  SessionClient* client = GetClient(content_type);
  ASSERT(client != NULL);

  Session* session = new Session(this, local_name, initiator_name,
                                 sid, content_type, client);
  session->SetIdentity(transport_desc_factory_.identity());
  session_map_[session->id()] = session;
  session->SignalRequestSignaling.connect(
      this, &SessionManager::OnRequestSignaling);
  session->SignalOutgoingMessage.connect(
      this, &SessionManager::OnOutgoingMessage);
  session->SignalErrorMessage.connect(this, &SessionManager::OnErrorMessage);
  SignalSessionCreate(session, received_initiate);
  session->client()->OnSessionCreate(session, received_initiate);
  return session;
}

void SessionManager::DestroySession(Session* session) {
  if (session != NULL) {
    SessionMap::iterator it = session_map_.find(session->id());
    if (it != session_map_.end()) {
      SignalSessionDestroy(session);
      session->client()->OnSessionDestroy(session);
      session_map_.erase(it);
      delete session;
    }
  }
}

Session* SessionManager::GetSession(const std::string& sid) {
  SessionMap::iterator it = session_map_.find(sid);
  if (it != session_map_.end())
    return it->second;
  return NULL;
}

void SessionManager::TerminateAll() {
  while (session_map_.begin() != session_map_.end()) {
    Session* session = session_map_.begin()->second;
    session->Terminate();
  }
}

bool SessionManager::IsSessionMessage(const buzz::XmlElement* stanza) {
  return cricket::IsSessionMessage(stanza);
}

Session* SessionManager::FindSession(const std::string& sid,
                                     const std::string& remote_name) {
  SessionMap::iterator iter = session_map_.find(sid);
  if (iter == session_map_.end())
    return NULL;

  Session* session = iter->second;
  if (buzz::Jid(remote_name) != buzz::Jid(session->remote_name()))
    return NULL;

  return session;
}

void SessionManager::OnIncomingMessage(const buzz::XmlElement* stanza) {
  SessionMessage msg;
  ParseError error;

  if (!ParseSessionMessage(stanza, &msg, &error)) {
    SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
                     error.text, NULL);
    return;
  }

  Session* session = FindSession(msg.sid, msg.from);
  if (session) {
    session->OnIncomingMessage(msg);
    return;
  }
  if (msg.type != ACTION_SESSION_INITIATE) {
    SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
                     "unknown session", NULL);
    return;
  }

  std::string content_type;
  if (!ParseContentType(msg.protocol, msg.action_elem,
                        &content_type, &error)) {
    SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
                     error.text, NULL);
    return;
  }

  if (!GetClient(content_type)) {
    SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
                     "unknown content type: " + content_type, NULL);
    return;
  }

  session = CreateSession(msg.to, msg.initiator, msg.sid,
                          content_type, true);
  session->OnIncomingMessage(msg);
}

void SessionManager::OnIncomingResponse(const buzz::XmlElement* orig_stanza,
    const buzz::XmlElement* response_stanza) {
  if (orig_stanza == NULL || response_stanza == NULL) {
    return;
  }

  SessionMessage msg;
  ParseError error;
  if (!ParseSessionMessage(orig_stanza, &msg, &error)) {
    LOG(LS_WARNING) << "Error parsing incoming response: " << error.text
                    << ":" << orig_stanza;
    return;
  }

  Session* session = FindSession(msg.sid, msg.to);
  if (!session) {
    // Also try the QN_FROM in the response stanza, in case we sent the request
    // to a bare JID but got the response from a full JID.
    std::string ack_from = response_stanza->Attr(buzz::QN_FROM);
    session = FindSession(msg.sid, ack_from);
  }
  if (session) {
    session->OnIncomingResponse(orig_stanza, response_stanza, msg);
  }
}

void SessionManager::OnFailedSend(const buzz::XmlElement* orig_stanza,
                                  const buzz::XmlElement* error_stanza) {
  SessionMessage msg;
  ParseError error;
  if (!ParseSessionMessage(orig_stanza, &msg, &error)) {
    return;  // TODO: log somewhere?
  }

  Session* session = FindSession(msg.sid, msg.to);
  if (session) {
    rtc::scoped_ptr<buzz::XmlElement> synthetic_error;
    if (!error_stanza) {
      // A failed send is semantically equivalent to an error response, so we
      // can just turn the former into the latter.
      synthetic_error.reset(
        CreateErrorMessage(orig_stanza, buzz::QN_STANZA_ITEM_NOT_FOUND,
                           "cancel", "Recipient did not respond", NULL));
      error_stanza = synthetic_error.get();
    }

    session->OnFailedSend(orig_stanza, error_stanza);
  }
}

void SessionManager::SendErrorMessage(const buzz::XmlElement* stanza,
                                      const buzz::QName& name,
                                      const std::string& type,
                                      const std::string& text,
                                      const buzz::XmlElement* extra_info) {
  rtc::scoped_ptr<buzz::XmlElement> msg(
      CreateErrorMessage(stanza, name, type, text, extra_info));
  SignalOutgoingMessage(this, msg.get());
}

buzz::XmlElement* SessionManager::CreateErrorMessage(
    const buzz::XmlElement* stanza,
    const buzz::QName& name,
    const std::string& type,
    const std::string& text,
    const buzz::XmlElement* extra_info) {
  buzz::XmlElement* iq = new buzz::XmlElement(buzz::QN_IQ);
  iq->SetAttr(buzz::QN_TO, stanza->Attr(buzz::QN_FROM));
  iq->SetAttr(buzz::QN_ID, stanza->Attr(buzz::QN_ID));
  iq->SetAttr(buzz::QN_TYPE, "error");

  CopyXmlChildren(stanza, iq);

  buzz::XmlElement* error = new buzz::XmlElement(buzz::QN_ERROR);
  error->SetAttr(buzz::QN_TYPE, type);
  iq->AddElement(error);

  // If the error name is not in the standard namespace, we have to first add
  // some error from that namespace.
  if (name.Namespace() != buzz::NS_STANZA) {
     error->AddElement(
         new buzz::XmlElement(buzz::QN_STANZA_UNDEFINED_CONDITION));
  }
  error->AddElement(new buzz::XmlElement(name));

  if (extra_info)
    error->AddElement(new buzz::XmlElement(*extra_info));

  if (text.size() > 0) {
    // It's okay to always use English here.  This text is for debugging
    // purposes only.
    buzz::XmlElement* text_elem = new buzz::XmlElement(buzz::QN_STANZA_TEXT);
    text_elem->SetAttr(buzz::QN_XML_LANG, "en");
    text_elem->SetBodyText(text);
    error->AddElement(text_elem);
  }

  // TODO: Should we include error codes as well for SIP compatibility?

  return iq;
}

void SessionManager::OnOutgoingMessage(Session* session,
                                       const buzz::XmlElement* stanza) {
  SignalOutgoingMessage(this, stanza);
}

void SessionManager::OnErrorMessage(BaseSession* session,
                                    const buzz::XmlElement* stanza,
                                    const buzz::QName& name,
                                    const std::string& type,
                                    const std::string& text,
                                    const buzz::XmlElement* extra_info) {
  SendErrorMessage(stanza, name, type, text, extra_info);
}

void SessionManager::OnSignalingReady() {
  for (SessionMap::iterator it = session_map_.begin();
      it != session_map_.end();
      ++it) {
    it->second->OnSignalingReady();
  }
}

void SessionManager::OnRequestSignaling(Session* session) {
  SignalRequestSignaling();
}

}  // namespace cricket
