/*
 * 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/xmpp/xmppclient.h"

#include "talk/xmpp/constants.h"
#include "talk/xmpp/plainsaslhandler.h"
#include "talk/xmpp/prexmppauth.h"
#include "talk/xmpp/saslplainmechanism.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/sigslot.h"
#include "webrtc/base/stringutils.h"
#include "xmpptask.h"

namespace buzz {

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

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

  virtual ~Private() {
    // We need to disconnect from socket_ before engine_ is destructed (by
    // the auto-generated destructor code).
    ResetSocket();
  }

  // the owner
  XmppClient* const client_;

  // the two main objects
  rtc::scoped_ptr<AsyncSocket> socket_;
  rtc::scoped_ptr<XmppEngine> engine_;
  rtc::scoped_ptr<PreXmppAuth> pre_auth_;
  rtc::CryptString pass_;
  std::string auth_mechanism_;
  std::string auth_token_;
  rtc::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_;

  void ResetSocket() {
    if (socket_) {
      socket_->SignalConnected.disconnect(this);
      socket_->SignalRead.disconnect(this);
      socket_->SignalClosed.disconnect(this);
      socket_.reset(NULL);
    }
  }

  // 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();
};

bool IsTestServer(const std::string& server_name,
                  const std::string& test_server_domain) {
  return (!test_server_domain.empty() &&
          rtc::ends_with(server_name.c_str(),
                               test_server_domain.c_str()));
}

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_)
    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_->SetTls(settings.use_tls());

  // The talk.google.com server returns a certificate with common-name:
  //   CN="gmail.com" for @gmail.com accounts,
  //   CN="googlemail.com" for @googlemail.com accounts,
  //   CN="talk.google.com" for other accounts (such as @example.com),
  // so we tweak the tls server setting for those other accounts to match the
  // returned certificate CN of "talk.google.com".
  // For other servers, we leave the strings empty, which causes the jid's
  // domain to be used.  We do the same for gmail.com and googlemail.com as the
  // returned CN matches the account domain in those cases.
  std::string server_name = settings.server().HostAsURIString();
  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 ||
      IsTestServer(server_name, settings.test_server_domain())) {
    if (settings.host() != STR_GMAIL_COM &&
        settings.host() != STR_GOOGLEMAIL_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_mechanism_ = settings.auth_mechanism();
  d_->auth_token_ = settings.auth_token();
  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() const {
  if (!d_->engine_)
    return XmppEngine::STATE_NONE;
  return d_->engine_->GetState();
}

XmppEngine::Error XmppClient::GetError(int* subcode) {
  if (subcode) {
    *subcode = 0;
  }
  if (!d_->engine_)
    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_) {
    return NULL;
  }
  return d_->engine_->GetStreamError();
}

CaptchaChallenge XmppClient::GetCaptchaChallenge() {
  if (!d_->engine_)
    return CaptchaChallenge();
  return d_->captcha_challenge_;
}

std::string XmppClient::GetAuthMechanism() {
  if (!d_->engine_)
    return "";
  return d_->auth_mechanism_;
}

std::string XmppClient::GetAuthToken() {
  if (!d_->engine_)
    return "";
  return d_->auth_token_;
}

int XmppClient::ProcessStart() {
  // Should not happen, but was observed in crash reports
  if (!d_->socket_) {
    LOG(LS_ERROR) << "socket_ already reset";
    return STATE_DONE;
  }

  if (d_->pre_auth_) {
    d_->pre_auth_->SignalAuthDone.connect(this, &XmppClient::OnAuthDone);
    d_->pre_auth_->StartPreXmppAuth(
        d_->engine_->GetUser(), d_->server_, d_->pass_,
        d_->auth_mechanism_, d_->auth_token_);
    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::ProcessTokenLogin() {
  // Should not happen, but was observed in crash reports
  if (!d_->socket_) {
    LOG(LS_ERROR) << "socket_ already reset";
    return STATE_DONE;
  }

  // Don't know how this could happen, but crash reports show it as NULL
  if (!d_->pre_auth_) {
    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 token as a result

  d_->auth_mechanism_ = d_->pre_auth_->GetAuthMechanism();
  d_->auth_token_ = d_->pre_auth_->GetAuthToken();

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

int XmppClient::ProcessStartXmppLogin() {
  // Should not happen, but was observed in crash reports
  if (!d_->socket_) {
    LOG(LS_ERROR) << "socket_ already reset";
    return STATE_DONE;
  }

  // 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_ || d_->engine_->GetState() == XmppEngine::STATE_CLOSED))
    return STATE_DONE;
  return STATE_BLOCKED;
}

XmppReturnStatus XmppClient::Disconnect() {
  if (!d_->socket_)
    return XMPP_RETURN_BADSTATE;
  Abort();
  d_->engine_->Disconnect();
  d_->ResetSocket();
  return XMPP_RETURN_OK;
}

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

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

const Jid& XmppClient::jid() const {
  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 (;;) {
    // Should not happen, but was observed in crash reports
    if (!socket_) {
      LOG(LS_ERROR) << "socket_ already reset";
      return;
    }

    if (!socket_->Read(bytes, sizeof(bytes), &bytes_read)) {
      // TODO: deal with error information
      return;
    }

    if (bytes_read == 0)
      return;

//#ifdef _DEBUG
    client_->SignalLogInput(bytes, static_cast<int>(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, static_cast<int>(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;
  }
}

}  // namespace buzz
