// Copyright 2015 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "buffet/notification/xmpp_iq_stanza_handler.h"

#include <base/bind.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/stringprintf.h>

#include "buffet/notification/xml_node.h"
#include "buffet/notification/xmpp_channel.h"

namespace buffet {

namespace {

// Default timeout for <iq> requests to the server. If the response hasn't been
// received within this time interval, the request is considered as failed.
const int kTimeoutIntervalSeconds = 30;

// Builds an XML stanza that looks like this:
//  <iq id='${id}' type='${type}' from='${from}' to='${to}'>$body</iq>
// where 'to' and 'from' are optional attributes.
std::string BuildIqStanza(const std::string& id,
                          const std::string& type,
                          const std::string& to,
                          const std::string& from,
                          const std::string& body) {
  std::string to_attr;
  if (!to.empty()) {
    CHECK_EQ(std::string::npos, to.find_first_of("<'>"))
        << "Destination address contains invalid XML characters";
    base::StringAppendF(&to_attr, " to='%s'", to.c_str());
  }
  std::string from_attr;
  if (!from.empty()) {
    CHECK_EQ(std::string::npos, from.find_first_of("<'>"))
        << "Source address contains invalid XML characters";
    base::StringAppendF(&from_attr, " from='%s'", from.c_str());
  }
  return base::StringPrintf("<iq id='%s' type='%s'%s%s>%s</iq>",
                            id.c_str(), type.c_str(), from_attr.c_str(),
                            to_attr.c_str(), body.c_str());
}

}  // anonymous namespace

IqStanzaHandler::IqStanzaHandler(
    XmppChannelInterface* xmpp_channel,
    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
    : xmpp_channel_{xmpp_channel}, task_runner_{task_runner} {}

void IqStanzaHandler::SendRequest(
    const std::string& type,
    const std::string& from,
    const std::string& to,
    const std::string& body,
    const ResponseCallback& response_callback,
    const TimeoutCallback& timeout_callback) {
  // Remember the response callback to call later.
  requests_.emplace(++last_request_id_, response_callback);
  // Schedule a time-out callback for this request.
  task_runner_->PostDelayedTask(
      FROM_HERE,
      base::Bind(&IqStanzaHandler::OnTimeOut,
                 weak_ptr_factory_.GetWeakPtr(),
                 last_request_id_,
                 timeout_callback),
      base::TimeDelta::FromSeconds(kTimeoutIntervalSeconds));

  std::string message = BuildIqStanza(std::to_string(last_request_id_),
                                      type, to, from, body);
  xmpp_channel_->SendMessage(message);
}

bool IqStanzaHandler::HandleIqStanza(std::unique_ptr<XmlNode> stanza) {
  std::string type;
  if (!stanza->GetAttribute("type", &type)) {
    LOG(ERROR) << "IQ stanza missing 'type' attribute";
    return false;
  }

  std::string id_str;
  if (!stanza->GetAttribute("id", &id_str)) {
    LOG(ERROR) << "IQ stanza missing 'id' attribute";
    return false;
  }

  if (type == "result" || type == "error") {
    // These are response stanzas from the server.
    // Find the corresponding request.
    RequestId id;
    if (!base::StringToInt(id_str, &id)) {
      LOG(ERROR) << "IQ stanza's 'id' attribute is invalid";
      return false;
    }
    auto p = requests_.find(id);
    if (p != requests_.end()) {
      task_runner_->PostTask(
          FROM_HERE,
          base::Bind(p->second, base::Passed(std::move(stanza))));
      requests_.erase(p);
    }
  } else {
    // We do not support server-initiated IQ requests ("set" / "get" / "query").
    // So just reply with "not implemented" error (and swap "to"/"from" attrs).
    std::string error_body =
        "<error type='modify'>"
        "<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
        "</error>";
    std::string message = BuildIqStanza(id_str, "error",
                                        stanza->GetAttributeOrEmpty("from"),
                                        stanza->GetAttributeOrEmpty("to"),
                                        error_body);
    xmpp_channel_->SendMessage(message);
  }
  return true;
}

void IqStanzaHandler::OnTimeOut(RequestId id,
                                const TimeoutCallback& timeout_callback) {
  // Request has not been processed yes, so a real timeout occurred.
  if (requests_.erase(id) > 0)
    timeout_callback.Run();
}

}  // namespace buffet
