/*
 * 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 "xmppclient.h"
#include "xmpptask.h"
#include "talk/xmpp/constants.h"
#include "talk/base/sigslot.h"
#include "talk/xmpp/saslplainmechanism.h"
#include "talk/xmpp/prexmppauth.h"
#include "talk/base/scoped_ptr.h"
#include "talk/xmpp/plainsaslhandler.h"

namespace buzz {

talk_base::TaskParent* XmppClient::GetParent(int code) {
  if (code == XMPP_CLIENT_TASK_CODE)
    return this;
  else
    return talk_base::Task::GetParent(code);
}

class XmppClient::Private :
    public sigslot::has_slots<>,
    public XmppSessionHandler,
    public XmppOutputHandler {
public:

  Private(XmppClient * client) :
    client_(client),
    socket_(NULL),
    engine_(NULL),
    proxy_port_(0),
    pre_engine_error_(XmppEngine::ERROR_NONE),
    pre_engine_subcode_(0),
    signal_closed_(false),
    allow_plain_(false) {}

  // the owner
  XmppClient * const client_;

  // the two main objects
  talk_base::scoped_ptr<AsyncSocket> socket_;
  talk_base::scoped_ptr<XmppEngine> engine_;
  talk_base::scoped_ptr<PreXmppAuth> pre_auth_;
  talk_base::CryptString pass_;
  std::string auth_cookie_;
  talk_base::SocketAddress server_;
  std::string proxy_host_;
  int proxy_port_;
  XmppEngine::Error pre_engine_error_;
  int pre_engine_subcode_;
  CaptchaChallenge captcha_challenge_;
  bool signal_closed_;
  bool allow_plain_;

  // implementations of interfaces
  void OnStateChange(int state);
  void WriteOutput(const char * bytes, size_t len);
  void StartTls(const std::string & domainname);
  void CloseConnection();

  // slots for socket signals
  void OnSocketConnected();
  void OnSocketRead();
  void OnSocketClosed();
};

XmppReturnStatus
XmppClient::Connect(const XmppClientSettings & settings, const std::string & lang, AsyncSocket * socket, PreXmppAuth * pre_auth) {
  if (socket == NULL)
    return XMPP_RETURN_BADARGUMENT;
  if (d_->socket_.get() != NULL)
    return XMPP_RETURN_BADSTATE;

  d_->socket_.reset(socket);

  d_->socket_->SignalConnected.connect(d_.get(), &Private::OnSocketConnected);
  d_->socket_->SignalRead.connect(d_.get(), &Private::OnSocketRead);
  d_->socket_->SignalClosed.connect(d_.get(), &Private::OnSocketClosed);

  d_->engine_.reset(XmppEngine::Create());
  d_->engine_->SetSessionHandler(d_.get());
  d_->engine_->SetOutputHandler(d_.get());
  if (!settings.resource().empty()) {
    d_->engine_->SetRequestedResource(settings.resource());
  }
  d_->engine_->SetUseTls(settings.use_tls());

  //
  // The talk.google.com server returns a certificate of "talk.google.com"
  // for non-Gmail accounts, so we tweak this as needed:
  // "foo@example.com" -> stream to="example.com"
  // tls certificate for "talk.google.com"
  // For Gmail accounts, and all other servers, we leave the strings empty,
  // which causes the jid's domain to be used:
  // "foo@gmail.com" -> stream to="gmail.com"
  // tls certificate for "gmail.com"
  //
  std::string server_name = settings.server().IPAsString();
  if (server_name == buzz::STR_TALK_GOOGLE_COM ||
      server_name == buzz::STR_TALKX_L_GOOGLE_COM ||
      server_name == buzz::STR_XMPP_GOOGLE_COM ||
      server_name == buzz::STR_XMPPX_L_GOOGLE_COM) {
    if (settings.host() != STR_GMAIL_COM) {
      d_->engine_->SetTlsServer("", STR_TALK_GOOGLE_COM);
    }
  }

  // Set language
  d_->engine_->SetLanguage(lang);

  d_->engine_->SetUser(buzz::Jid(settings.user(), settings.host(), STR_EMPTY));

  d_->pass_ = settings.pass();
  d_->auth_cookie_ = settings.auth_cookie();
  d_->server_ = settings.server();
  d_->proxy_host_ = settings.proxy_host();
  d_->proxy_port_ = settings.proxy_port();
  d_->allow_plain_ = settings.allow_plain();
  d_->pre_auth_.reset(pre_auth);

  return XMPP_RETURN_OK;
}

XmppEngine::State
XmppClient::GetState() {
  if (d_->engine_.get() == NULL)
    return XmppEngine::STATE_NONE;
  return d_->engine_->GetState();
}

XmppEngine::Error
XmppClient::GetError(int *subcode) {
  if (subcode) {
    *subcode = 0;
  }
  if (d_->engine_.get() == NULL)
    return XmppEngine::ERROR_NONE;
  if (d_->pre_engine_error_ != XmppEngine::ERROR_NONE) {
    if (subcode) {
      *subcode = d_->pre_engine_subcode_;
    }
    return d_->pre_engine_error_;
  }
  return d_->engine_->GetError(subcode);
}

const XmlElement *
XmppClient::GetStreamError() {
  if (d_->engine_.get() == NULL) {
    return NULL;
  }
  return d_->engine_->GetStreamError();
}

CaptchaChallenge XmppClient::GetCaptchaChallenge() {
  if (d_->engine_.get() == NULL)
    return CaptchaChallenge();
  return d_->captcha_challenge_;
}

std::string
XmppClient::GetAuthCookie() {
  if (d_->engine_.get() == NULL)
    return "";
  return d_->auth_cookie_;
}

int
XmppClient::ProcessStart() {
  if (d_->pre_auth_.get()) {
    d_->pre_auth_->SignalAuthDone.connect(this, &XmppClient::OnAuthDone);
    d_->pre_auth_->StartPreXmppAuth(
        d_->engine_->GetUser(), d_->server_, d_->pass_, d_->auth_cookie_);
    d_->pass_.Clear(); // done with this;
    return STATE_PRE_XMPP_LOGIN;
  }
  else {
    d_->engine_->SetSaslHandler(new PlainSaslHandler(
              d_->engine_->GetUser(), d_->pass_, d_->allow_plain_));
    d_->pass_.Clear(); // done with this;
    return STATE_START_XMPP_LOGIN;
  }
}

void
XmppClient::OnAuthDone() {
  Wake();
}

int
XmppClient::ProcessCookieLogin() {
  // Don't know how this could happen, but crash reports show it as NULL
  if (!d_->pre_auth_.get()) {
    d_->pre_engine_error_ = XmppEngine::ERROR_AUTH;
    EnsureClosed();
    return STATE_ERROR;
  }

  // Wait until pre authentication is done is done
  if (!d_->pre_auth_->IsAuthDone())
    return STATE_BLOCKED;

  if (!d_->pre_auth_->IsAuthorized()) {
    // maybe split out a case when gaia is down?
    if (d_->pre_auth_->HadError()) {
      d_->pre_engine_error_ = XmppEngine::ERROR_AUTH;
      d_->pre_engine_subcode_ = d_->pre_auth_->GetError();
    }
    else {
      d_->pre_engine_error_ = XmppEngine::ERROR_UNAUTHORIZED;
      d_->pre_engine_subcode_ = 0;
      d_->captcha_challenge_ = d_->pre_auth_->GetCaptchaChallenge();
    }
    d_->pre_auth_.reset(NULL); // done with this
    EnsureClosed();
    return STATE_ERROR;
  }

  // Save auth cookie as a result
  d_->auth_cookie_ = d_->pre_auth_->GetAuthCookie();

  // transfer ownership of pre_auth_ to engine
  d_->engine_->SetSaslHandler(d_->pre_auth_.release());
  return STATE_START_XMPP_LOGIN;
}

int
XmppClient::ProcessStartXmppLogin() {
  // Done with pre-connect tasks - connect!
  if (!d_->socket_->Connect(d_->server_)) {
    EnsureClosed();
    return STATE_ERROR;
  }

  return STATE_RESPONSE;
}

int
XmppClient::ProcessResponse() {
  // Hang around while we are connected.
  if (!delivering_signal_ && (d_->engine_.get() == NULL ||
    d_->engine_->GetState() == XmppEngine::STATE_CLOSED))
    return STATE_DONE;
  return STATE_BLOCKED;
}

XmppReturnStatus
XmppClient::Disconnect() {
  if (d_->socket_.get() == NULL)
    return XMPP_RETURN_BADSTATE;
  d_->engine_->Disconnect();
  d_->socket_.reset(NULL);
  return XMPP_RETURN_OK;
}

XmppClient::XmppClient(TaskParent * parent)
    : Task(parent),
      delivering_signal_(false),
      valid_(false) {
  d_.reset(new Private(this));
  valid_ = true;
}

XmppClient::~XmppClient() {
  valid_ = false;
}

const Jid &
XmppClient::jid() {
  return d_->engine_->FullJid();
}


std::string
XmppClient::NextId() {
  return d_->engine_->NextId();
}

XmppReturnStatus
XmppClient::SendStanza(const XmlElement * stanza) {
  return d_->engine_->SendStanza(stanza);
}

XmppReturnStatus
XmppClient::SendStanzaError(const XmlElement * old_stanza, XmppStanzaError xse, const std::string & message) {
  return d_->engine_->SendStanzaError(old_stanza, xse, message);
}

XmppReturnStatus
XmppClient::SendRaw(const std::string & text) {
  return d_->engine_->SendRaw(text);
}

XmppEngine*
XmppClient::engine() {
  return d_->engine_.get();
}

void
XmppClient::Private::OnSocketConnected() {
  engine_->Connect();
}

void
XmppClient::Private::OnSocketRead() {
  char bytes[4096];
  size_t bytes_read;
  for (;;) {
    if (!socket_->Read(bytes, sizeof(bytes), &bytes_read)) {
      // TODO: deal with error information
      return;
    }

    if (bytes_read == 0)
      return;

//#ifdef _DEBUG
    client_->SignalLogInput(bytes, bytes_read);
//#endif

    engine_->HandleInput(bytes, bytes_read);
  }
}

void
XmppClient::Private::OnSocketClosed() {
  int code = socket_->GetError();
  engine_->ConnectionClosed(code);
}

void
XmppClient::Private::OnStateChange(int state) {
  if (state == XmppEngine::STATE_CLOSED) {
    client_->EnsureClosed();
  }
  else {
    client_->SignalStateChange((XmppEngine::State)state);
  }
  client_->Wake();
}

void
XmppClient::Private::WriteOutput(const char * bytes, size_t len) {

//#ifdef _DEBUG
  client_->SignalLogOutput(bytes, len);
//#endif

  socket_->Write(bytes, len);
  // TODO: deal with error information
}

void
XmppClient::Private::StartTls(const std::string & domain) {
#if defined(FEATURE_ENABLE_SSL)
  socket_->StartTls(domain);
#endif
}

void
XmppClient::Private::CloseConnection() {
  socket_->Close();
}

void
XmppClient::AddXmppTask(XmppTask * task, XmppEngine::HandlerLevel level) {
  d_->engine_->AddStanzaHandler(task, level);
}

void
XmppClient::RemoveXmppTask(XmppTask * task) {
  d_->engine_->RemoveStanzaHandler(task);
}

void
XmppClient::EnsureClosed() {
  if (!d_->signal_closed_) {
    d_->signal_closed_ = true;
    delivering_signal_ = true;
    SignalStateChange(XmppEngine::STATE_CLOSED);
    delivering_signal_ = false;
  }
}


}
