/*
 * 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/base/common.h"
#include "talk/base/helpers.h"
#include "talk/base/logging.h"
#include "talk/base/scoped_ptr.h"
#include "talk/base/stringencode.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"

namespace cricket {

SessionManager::SessionManager(PortAllocator *allocator,
                               talk_base::Thread *worker) {
  allocator_ = allocator;
  signaling_thread_ = talk_base::Thread::Current();
  if (worker == NULL) {
    worker_thread_ = talk_base::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() ? talk_base::ToString(talk_base::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) {
    talk_base::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) {
  talk_base::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
