// Copyright 2015 The Weave 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 "src/privet/privet_handler.h"

#include <algorithm>
#include <memory>
#include <set>
#include <string>
#include <utility>

#include <base/bind.h>
#include <base/location.h>
#include <base/strings/stringprintf.h>
#include <base/values.h>
#include <weave/device.h>
#include <weave/enum_to_string.h>
#include <weave/provider/task_runner.h>

#include "src/config.h"
#include "src/http_constants.h"
#include "src/privet/cloud_delegate.h"
#include "src/privet/constants.h"
#include "src/privet/device_delegate.h"
#include "src/privet/device_ui_kind.h"
#include "src/privet/security_delegate.h"
#include "src/privet/wifi_delegate.h"
#include "src/string_utils.h"
#include "src/utils.h"

namespace weave {
namespace privet {

namespace {

const char kInfoVersionKey[] = "version";
const char kInfoVersionValue[] = "3.0";

const char kNameKey[] = "name";
const char kDescrptionKey[] = "description";
const char kLocationKey[] = "location";

const char kGcdKey[] = "gcd";
const char kWifiKey[] = "wifi";
const char kStatusKey[] = "status";
const char kErrorKey[] = "error";
const char kCryptoKey[] = "crypto";
const char kStatusErrorValue[] = "error";

const char kInfoIdKey[] = "id";
const char kInfoServicesKey[] = "services";

const char kInfoEndpointsKey[] = "endpoints";
const char kInfoEndpointsHttpPortKey[] = "httpPort";
const char kInfoEndpointsHttpUpdatePortKey[] = "httpUpdatesPort";
const char kInfoEndpointsHttpsPortKey[] = "httpsPort";
const char kInfoEndpointsHttpsUpdatePortKey[] = "httpsUpdatesPort";

const char kInfoModelIdKey[] = "modelManifestId";
const char kInfoModelManifestKey[] = "basicModelManifest";
const char kInfoManifestUiDeviceKind[] = "uiDeviceKind";
const char kInfoManifestOemName[] = "oemName";
const char kInfoManifestModelName[] = "modelName";

const char kInfoAuthenticationKey[] = "authentication";

const char kInfoAuthAnonymousMaxScopeKey[] = "anonymousMaxScope";

const char kInfoWifiCapabilitiesKey[] = "capabilities";
const char kInfoWifiSsidKey[] = "ssid";
const char kInfoWifiHostedSsidKey[] = "hostedSsid";
const char kInfoTimeKey[] = "time";
const char kInfoSessionIdKey[] = "sessionId";

const char kPairingKey[] = "pairing";
const char kPairingSessionIdKey[] = "sessionId";
const char kPairingDeviceCommitmentKey[] = "deviceCommitment";
const char kPairingClientCommitmentKey[] = "clientCommitment";
const char kPairingFingerprintKey[] = "certFingerprint";
const char kPairingSignatureKey[] = "certSignature";

const char kAuthModeKey[] = "mode";
const char kAuthCodeKey[] = "authCode";
const char kAuthRequestedScopeKey[] = "requestedScope";
const char kAuthScopeAutoValue[] = "auto";

const char kAuthAccessTokenKey[] = "accessToken";
const char kAuthTokenTypeKey[] = "tokenType";
const char kAuthExpiresInKey[] = "expiresIn";
const char kAuthScopeKey[] = "scope";
const char kAuthClientTokenKey[] = "clientToken";

const char kAuthorizationHeaderPrefix[] = "Privet";

const char kErrorDebugInfoKey[] = "debugInfo";

const char kSetupStartSsidKey[] = "ssid";
const char kSetupStartPassKey[] = "passphrase";
const char kSetupStartTicketIdKey[] = "ticketId";
const char kSetupStartUserKey[] = "user";
const char kSetupStartClientIdKey[] = "client_id";
const char kSetupStartClientSecretKey[] = "client_secret";
const char kSetupStartApiKeyKey[] = "api_key";
const char kSetupStartOAuthUrlKey[] = "oauth_url";
const char kSetupStartServiceUrlKey[] = "service_url";
const char kSetupStartXmppEndpointKey[] = "xmpp_endpoint";

std::string oauth_url;
std::string client_id;
std::string client_secret;
std::string api_key;
std::string service_url;
std::string xmpp_endpoint;

const char kFingerprintKey[] = "fingerprint";
const char kTraitsKey[] = "traits";
const char kComponentsKey[] = "components";
const char kCommandsIdKey[] = "id";
const char kPathKey[] = "path";
const char kFilterKey[] = "filter";

const char kStateFingerprintKey[] = "stateFingerprint";
const char kCommandsFingerprintKey[] = "commandsFingerprint";
const char kTraitsFingerprintKey[] = "traitsFingerprint";
const char kComponentsFingerprintKey[] = "componentsFingerprint";
const char kWaitTimeoutKey[] = "waitTimeout";

const char kInvalidParamValueFormat[] = "Invalid parameter: '%s'='%s'";

template <class Container>
std::unique_ptr<base::ListValue> ToValue(const Container& list) {
  std::unique_ptr<base::ListValue> value_list(new base::ListValue());
  for (const std::string& val : list)
    value_list->AppendString(val);
  return value_list;
}

struct {
  const char* const reason;
  int code;
} kReasonToCode[] = {
    {errors::kInvalidClientCommitment, http::kForbidden},
    {errors::kInvalidFormat, http::kBadRequest},
    {errors::kMissingAuthorization, http::kDenied},
    {errors::kInvalidAuthorization, http::kDenied},
    {errors::kInvalidAuthorizationScope, http::kForbidden},
    {errors::kAuthorizationExpired, http::kForbidden},
    {errors::kCommitmentMismatch, http::kForbidden},
    {errors::kUnknownSession, http::kNotFound},
    {errors::kInvalidAuthCode, http::kForbidden},
    {errors::kInvalidAuthMode, http::kBadRequest},
    {errors::kInvalidRequestedScope, http::kBadRequest},
    {errors::kAccessDenied, http::kForbidden},
    {errors::kInvalidParams, http::kBadRequest},
    {errors::kSetupUnavailable, http::kBadRequest},
    {errors::kDeviceBusy, http::kServiceUnavailable},
    {errors::kInvalidState, http::kInternalServerError},
    {errors::kNotFound, http::kNotFound},
    {errors::kNotImplemented, http::kNotSupported},
    {errors::kAlreadyClaimed, http::kDenied},
};

std::string GetAuthTokenFromAuthHeader(const std::string& auth_header) {
  return SplitAtFirst(auth_header, " ", true).second;
}

// Creates JSON similar to GCD server error format.
std::unique_ptr<base::DictionaryValue> ErrorToJson(const Error& error) {
  std::unique_ptr<base::DictionaryValue> output{ErrorInfoToJson(error)};

  // Optional debug information.
  std::unique_ptr<base::ListValue> errors{new base::ListValue};
  for (const Error* it = &error; it; it = it->GetInnerError()) {
    std::unique_ptr<base::DictionaryValue> inner{ErrorInfoToJson(*it)};
    tracked_objects::Location location{it->GetLocation().function_name.c_str(),
                                       it->GetLocation().file_name.c_str(),
                                       it->GetLocation().line_number, nullptr};
    inner->SetString(kErrorDebugInfoKey, location.ToString());
    errors->Append(std::move(inner));
  }
  output->Set(kErrorDebugInfoKey, std::move(errors));
  return output;
}

template <class T>
void SetStateProperties(const T& state, base::DictionaryValue* parent) {
  if (!state.error()) {
    parent->SetString(kStatusKey, EnumToString(state.status()));
    return;
  }
  parent->SetString(kStatusKey, kStatusErrorValue);
  parent->Set(kErrorKey, ErrorToJson(*state.error()));
}

void ReturnError(const Error& error,
                 const PrivetHandler::RequestCallback& callback) {
  int code = http::kInternalServerError;
  for (const auto& it : kReasonToCode) {
    if (error.HasError(it.reason)) {
      code = it.code;
      break;
    }
  }
  std::unique_ptr<base::DictionaryValue> output{new base::DictionaryValue};
  output->Set(kErrorKey, ErrorToJson(error));
  callback.Run(code, *output);
}

void OnCommandRequestSucceeded(const PrivetHandler::RequestCallback& callback,
                               const base::DictionaryValue& output,
                               ErrorPtr error) {
  if (!error)
    return callback.Run(http::kOk, output);

  if (error->HasError("unknown_command")) {
    Error::AddTo(&error, FROM_HERE, errors::kNotFound, "Unknown command ID");
    return ReturnError(*error, callback);
  }
  if (error->HasError("access_denied")) {
    Error::AddTo(&error, FROM_HERE, errors::kAccessDenied, error->GetMessage());
    return ReturnError(*error, callback);
  }
  return ReturnError(*error, callback);
}

std::unique_ptr<base::DictionaryValue> CreateManifestSection(
    const CloudDelegate& cloud) {
  std::unique_ptr<base::DictionaryValue> manifest(new base::DictionaryValue());
  manifest->SetString(kInfoManifestUiDeviceKind,
                      GetDeviceUiKind(cloud.GetModelId()));
  manifest->SetString(kInfoManifestOemName, cloud.GetOemName());
  manifest->SetString(kInfoManifestModelName, cloud.GetModelName());
  return manifest;
}

std::unique_ptr<base::DictionaryValue> CreateEndpointsSection(
    const DeviceDelegate& device) {
  std::unique_ptr<base::DictionaryValue> endpoints(new base::DictionaryValue());
  auto http_endpoint = device.GetHttpEnpoint();
  endpoints->SetInteger(kInfoEndpointsHttpPortKey, http_endpoint.first);
  endpoints->SetInteger(kInfoEndpointsHttpUpdatePortKey, http_endpoint.second);

  auto https_endpoint = device.GetHttpsEnpoint();
  endpoints->SetInteger(kInfoEndpointsHttpsPortKey, https_endpoint.first);
  endpoints->SetInteger(kInfoEndpointsHttpsUpdatePortKey,
                        https_endpoint.second);

  return endpoints;
}

std::unique_ptr<base::DictionaryValue> CreateInfoAuthSection(
    const SecurityDelegate& security,
    AuthScope anonymous_max_scope) {
  std::unique_ptr<base::DictionaryValue> auth(new base::DictionaryValue());

  auth->SetString(kInfoAuthAnonymousMaxScopeKey,
                  EnumToString(anonymous_max_scope));

  std::unique_ptr<base::ListValue> pairing_types(new base::ListValue());
  for (PairingType type : security.GetPairingTypes())
    pairing_types->AppendString(EnumToString(type));
  auth->Set(kPairingKey, std::move(pairing_types));

  std::unique_ptr<base::ListValue> auth_types(new base::ListValue());
  for (AuthType type : security.GetAuthTypes())
    auth_types->AppendString(EnumToString(type));
  auth->Set(kAuthModeKey, std::move(auth_types));

  std::unique_ptr<base::ListValue> crypto_types(new base::ListValue());
  for (CryptoType type : security.GetCryptoTypes())
    crypto_types->AppendString(EnumToString(type));
  auth->Set(kCryptoKey, std::move(crypto_types));

  return auth;
}

std::unique_ptr<base::DictionaryValue> CreateWifiSection(
    const WifiDelegate& wifi) {
  std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());

  std::unique_ptr<base::ListValue> capabilities(new base::ListValue());
  for (WifiType type : wifi.GetTypes())
    capabilities->AppendString(EnumToString(type));
  result->Set(kInfoWifiCapabilitiesKey, std::move(capabilities));

  result->SetString(kInfoWifiSsidKey, wifi.GetCurrentlyConnectedSsid());

  std::string hosted_ssid = wifi.GetHostedSsid();
  const ConnectionState& state = wifi.GetConnectionState();
  if (!hosted_ssid.empty()) {
    DCHECK(!state.IsStatusEqual(ConnectionState::kDisabled));
    DCHECK(!state.IsStatusEqual(ConnectionState::kOnline));
    result->SetString(kInfoWifiHostedSsidKey, hosted_ssid);
  }
  SetStateProperties(state, result.get());
  return result;
}

void SetGcdProperties(const CloudDelegate& cloud, base::DictionaryValue* dict) {
  dict->SetString(kInfoIdKey, cloud.GetCloudId());
  dict->SetString(kSetupStartOAuthUrlKey, cloud.GetOAuthUrl());
  dict->SetString(kSetupStartServiceUrlKey, cloud.GetServiceUrl());
  dict->SetString(kSetupStartXmppEndpointKey, cloud.GetXmppEndpoint());
}

std::unique_ptr<base::DictionaryValue> CreateGcdSection(
    const CloudDelegate& cloud) {
  std::unique_ptr<base::DictionaryValue> gcd(new base::DictionaryValue());
  SetGcdProperties(cloud, gcd.get());
  SetStateProperties(cloud.GetConnectionState(), gcd.get());
  return gcd;
}

AuthScope GetAnonymousMaxScope(const CloudDelegate& cloud,
                               const WifiDelegate* wifi) {
  if (wifi && !wifi->GetHostedSsid().empty())
    return AuthScope::kNone;
  return cloud.GetAnonymousMaxScope();
}

// Forward-declaration.
std::unique_ptr<base::DictionaryValue> CloneComponentTree(
    const base::DictionaryValue& parent,
    const std::set<std::string>& filter);

// Clones a particular component JSON object in a manner similar to that of
// DeepCopy(), except it includes only sub-objects specified in |filter| (if not
// empty) and has special handling for "components" sub-dictionary.
std::unique_ptr<base::DictionaryValue> CloneComponent(
    const base::DictionaryValue& component,
    const std::set<std::string>& filter) {
  std::unique_ptr<base::DictionaryValue> clone{new base::DictionaryValue};
  for (base::DictionaryValue::Iterator it(component); !it.IsAtEnd();
       it.Advance()) {
    if (filter.empty() || filter.find(it.key()) != filter.end()) {
      if (it.key() == kComponentsKey) {
        // Handle "components" separately as we need to recursively clone
        // sub-components.
        const base::DictionaryValue* sub_components = nullptr;
        CHECK(it.value().GetAsDictionary(&sub_components));
        clone->SetWithoutPathExpansion(
            it.key(), CloneComponentTree(*sub_components, filter));
      } else {
        clone->SetWithoutPathExpansion(it.key(), it.value().CreateDeepCopy());
      }
    }
  }
  return clone;
}

// Clones a dictionary containing a bunch of component JSON objects in a manner
// similar to that of CreateDeepCopy(). Calls CloneComponent() on each instance
// of the component sub-object.
std::unique_ptr<base::DictionaryValue> CloneComponentTree(
    const base::DictionaryValue& parent,
    const std::set<std::string>& filter) {
  std::unique_ptr<base::DictionaryValue> clone{new base::DictionaryValue};
  for (base::DictionaryValue::Iterator it(parent); !it.IsAtEnd();
       it.Advance()) {
    const base::DictionaryValue* component = nullptr;
    CHECK(it.value().GetAsDictionary(&component));
    clone->SetWithoutPathExpansion(
        it.key(), CloneComponent(*component, filter));
  }
  return clone;
}

}  // namespace

std::vector<std::string> PrivetHandler::GetHttpPaths() const {
  std::vector<std::string> result;
  for (const auto& pair : handlers_) {
    if (!pair.second.https_only)
      result.push_back(pair.first);
  }
  return result;
}

std::vector<std::string> PrivetHandler::GetHttpsPaths() const {
  std::vector<std::string> result;
  for (const auto& pair : handlers_)
    result.push_back(pair.first);
  return result;
}

PrivetHandler::PrivetHandler(CloudDelegate* cloud,
                             DeviceDelegate* device,
                             SecurityDelegate* security,
                             WifiDelegate* wifi,
                             base::Clock* clock)
    : cloud_(cloud),
      device_(device),
      security_(security),
      wifi_(wifi),
      clock_(clock ? clock : &default_clock_) {
  CHECK(cloud_);
  CHECK(device_);
  CHECK(security_);
  CHECK(clock_);

  cloud_->AddOnTraitsChangedCallback(base::Bind(
      &PrivetHandler::OnTraitDefsChanged, weak_ptr_factory_.GetWeakPtr()));
  cloud_->AddOnStateChangedCallback(base::Bind(&PrivetHandler::OnStateChanged,
                                               weak_ptr_factory_.GetWeakPtr()));
  cloud_->AddOnComponentsChangeCallback(base::Bind(
      &PrivetHandler::OnComponentTreeChanged, weak_ptr_factory_.GetWeakPtr()));

  AddHandler("/privet/info", &PrivetHandler::HandleInfo, AuthScope::kNone);
  AddHandler("/privet/v3/pairing/start", &PrivetHandler::HandlePairingStart,
             AuthScope::kNone);
  AddHandler("/privet/v3/pairing/confirm", &PrivetHandler::HandlePairingConfirm,
             AuthScope::kNone);
  AddHandler("/privet/v3/pairing/cancel", &PrivetHandler::HandlePairingCancel,
             AuthScope::kNone);

  AddSecureHandler("/privet/v3/auth", &PrivetHandler::HandleAuth,
                   AuthScope::kNone);
  AddSecureHandler("/privet/v3/accessControl/claim",
                   &PrivetHandler::HandleAccessControlClaim, AuthScope::kOwner);
  AddSecureHandler("/privet/v3/accessControl/confirm",
                   &PrivetHandler::HandleAccessControlConfirm,
                   AuthScope::kOwner);
  AddSecureHandler("/privet/v3/setup/start", &PrivetHandler::HandleSetupStart,
                   AuthScope::kManager);
  AddSecureHandler("/privet/v3/setup/status", &PrivetHandler::HandleSetupStatus,
                   AuthScope::kManager);
  AddSecureHandler("/privet/v3/commands/execute",
                   &PrivetHandler::HandleCommandsExecute, AuthScope::kViewer);
  AddSecureHandler("/privet/v3/commands/status",
                   &PrivetHandler::HandleCommandsStatus, AuthScope::kViewer);
  AddSecureHandler("/privet/v3/commands/cancel",
                   &PrivetHandler::HandleCommandsCancel, AuthScope::kViewer);
  AddSecureHandler("/privet/v3/commands/list",
                   &PrivetHandler::HandleCommandsList, AuthScope::kViewer);
  AddSecureHandler("/privet/v3/checkForUpdates",
                   &PrivetHandler::HandleCheckForUpdates, AuthScope::kViewer);
  AddSecureHandler("/privet/v3/traits", &PrivetHandler::HandleTraits,
                   AuthScope::kViewer);
  AddSecureHandler("/privet/v3/components", &PrivetHandler::HandleComponents,
                   AuthScope::kViewer);
}

PrivetHandler::~PrivetHandler() {
  for (const auto& req : update_requests_)
    ReplyToUpdateRequest(req.callback);
}

void PrivetHandler::OnTraitDefsChanged() {
  ++traits_fingerprint_;
  auto pred = [this](const UpdateRequestParameters& params) {
    return params.traits_fingerprint == 0;
  };
  auto last =
      std::partition(update_requests_.begin(), update_requests_.end(), pred);
  for (auto p = last; p != update_requests_.end(); ++p)
    ReplyToUpdateRequest(p->callback);
  update_requests_.erase(last, update_requests_.end());
}

void PrivetHandler::OnStateChanged() {
  // State updates also change the component tree, so update both fingerprints.
  ++state_fingerprint_;
  ++components_fingerprint_;
  auto pred = [this](const UpdateRequestParameters& params) {
    return params.state_fingerprint == 0 && params.components_fingerprint == 0;
  };
  auto last =
      std::partition(update_requests_.begin(), update_requests_.end(), pred);
  for (auto p = last; p != update_requests_.end(); ++p)
    ReplyToUpdateRequest(p->callback);
  update_requests_.erase(last, update_requests_.end());
}

void PrivetHandler::OnComponentTreeChanged() {
  ++components_fingerprint_;
  auto pred = [this](const UpdateRequestParameters& params) {
    return params.components_fingerprint == 0;
  };
  auto last =
      std::partition(update_requests_.begin(), update_requests_.end(), pred);
  for (auto p = last; p != update_requests_.end(); ++p)
    ReplyToUpdateRequest(p->callback);
  update_requests_.erase(last, update_requests_.end());
}

void PrivetHandler::HandleRequest(const std::string& api,
                                  const std::string& auth_header,
                                  const base::DictionaryValue* input,
                                  const RequestCallback& callback) {
  ErrorPtr error;
  if (!input) {
    Error::AddTo(&error, FROM_HERE, errors::kInvalidFormat, "Malformed JSON");
    return ReturnError(*error, callback);
  }
  auto handler = handlers_.find(api);
  if (handler == handlers_.end()) {
    Error::AddTo(&error, FROM_HERE, errors::kNotFound, "Path not found");
    return ReturnError(*error, callback);
  }
  if (auth_header.empty()) {
    Error::AddTo(&error, FROM_HERE, errors::kMissingAuthorization,
                 "Authorization header must not be empty");
    return ReturnError(*error, callback);
  }
  std::string token = GetAuthTokenFromAuthHeader(auth_header);
  if (token.empty()) {
    Error::AddToPrintf(&error, FROM_HERE, errors::kInvalidAuthorization,
                       "Invalid authorization header: %s", auth_header.c_str());
    return ReturnError(*error, callback);
  }
  UserInfo user_info;
  if (token != EnumToString(AuthType::kAnonymous)) {
    if (!security_->ParseAccessToken(token, &user_info, &error))
      return ReturnError(*error, callback);
  }

  if (handler->second.scope > user_info.scope()) {
    Error::AddToPrintf(&error, FROM_HERE, errors::kInvalidAuthorizationScope,
                       "Scope '%s' does not allow '%s'",
                       EnumToString(user_info.scope()).c_str(), api.c_str());
    return ReturnError(*error, callback);
  }
  (this->*handler->second.handler)(*input, user_info, callback);
}

void PrivetHandler::AddHandler(const std::string& path,
                               ApiHandler handler,
                               AuthScope scope) {
  HandlerParameters params;
  params.handler = handler;
  params.scope = scope;
  params.https_only = false;
  CHECK(handlers_.insert(std::make_pair(path, params)).second);
}

void PrivetHandler::AddSecureHandler(const std::string& path,
                                     ApiHandler handler,
                                     AuthScope scope) {
  HandlerParameters params;
  params.handler = handler;
  params.scope = scope;
  params.https_only = true;
  CHECK(handlers_.insert(std::make_pair(path, params)).second);
}

void PrivetHandler::HandleInfo(const base::DictionaryValue&,
                               const UserInfo& user_info,
                               const RequestCallback& callback) {
  base::DictionaryValue output;

  std::string name = cloud_->GetName();
  std::string model_id = cloud_->GetModelId();

  output.SetString(kInfoVersionKey, kInfoVersionValue);
  output.SetString(kInfoIdKey, cloud_->GetDeviceId());
  output.SetString(kNameKey, name);

  std::string description{cloud_->GetDescription()};
  if (!description.empty())
    output.SetString(kDescrptionKey, description);

  std::string location{cloud_->GetLocation()};
  if (!location.empty())
    output.SetString(kLocationKey, location);

  output.SetString(kInfoModelIdKey, model_id);
  output.Set(kInfoModelManifestKey, CreateManifestSection(*cloud_));
  output.Set(
      kInfoServicesKey,
      ToValue(std::vector<std::string>{GetDeviceUiKind(cloud_->GetModelId())}));

  output.Set(
      kInfoAuthenticationKey,
      CreateInfoAuthSection(*security_, GetAnonymousMaxScope(*cloud_, wifi_)));

  output.Set(kInfoEndpointsKey, CreateEndpointsSection(*device_));

  if (wifi_)
    output.Set(kWifiKey, CreateWifiSection(*wifi_));

  output.Set(kGcdKey, CreateGcdSection(*cloud_));

  output.SetDouble(kInfoTimeKey, clock_->Now().ToJsTime());
  output.SetString(kInfoSessionIdKey, security_->CreateSessionId());

  callback.Run(http::kOk, output);
}

void PrivetHandler::HandlePairingStart(const base::DictionaryValue& input,
                                       const UserInfo& user_info,
                                       const RequestCallback& callback) {
  ErrorPtr error;

  std::string pairing_str;
  input.GetString(kPairingKey, &pairing_str);

  std::string crypto_str;
  input.GetString(kCryptoKey, &crypto_str);

  PairingType pairing;
  std::set<PairingType> modes = security_->GetPairingTypes();
  if (!StringToEnum(pairing_str, &pairing) ||
      modes.find(pairing) == modes.end()) {
    Error::AddToPrintf(&error, FROM_HERE, errors::kInvalidParams,
                       kInvalidParamValueFormat, kPairingKey,
                       pairing_str.c_str());
    return ReturnError(*error, callback);
  }

  CryptoType crypto;
  std::set<CryptoType> cryptos = security_->GetCryptoTypes();
  if (!StringToEnum(crypto_str, &crypto) ||
      cryptos.find(crypto) == cryptos.end()) {
    Error::AddToPrintf(&error, FROM_HERE, errors::kInvalidParams,
                       kInvalidParamValueFormat, kCryptoKey,
                       crypto_str.c_str());
    return ReturnError(*error, callback);
  }

  std::string id;
  std::string commitment;
  if (!security_->StartPairing(pairing, crypto, &id, &commitment, &error))
    return ReturnError(*error, callback);

  base::DictionaryValue output;
  output.SetString(kPairingSessionIdKey, id);
  output.SetString(kPairingDeviceCommitmentKey, commitment);
  callback.Run(http::kOk, output);
}

void PrivetHandler::HandlePairingConfirm(const base::DictionaryValue& input,
                                         const UserInfo& user_info,
                                         const RequestCallback& callback) {
  std::string id;
  input.GetString(kPairingSessionIdKey, &id);

  std::string commitment;
  input.GetString(kPairingClientCommitmentKey, &commitment);

  std::string fingerprint;
  std::string signature;
  ErrorPtr error;
  if (!security_->ConfirmPairing(id, commitment, &fingerprint, &signature,
                                 &error)) {
    return ReturnError(*error, callback);
  }

  base::DictionaryValue output;
  output.SetString(kPairingFingerprintKey, fingerprint);
  output.SetString(kPairingSignatureKey, signature);
  callback.Run(http::kOk, output);
}

void PrivetHandler::HandlePairingCancel(const base::DictionaryValue& input,
                                        const UserInfo& user_info,
                                        const RequestCallback& callback) {
  std::string id;
  input.GetString(kPairingSessionIdKey, &id);

  ErrorPtr error;
  if (!security_->CancelPairing(id, &error))
    return ReturnError(*error, callback);

  base::DictionaryValue output;
  callback.Run(http::kOk, output);
}

void PrivetHandler::HandleAuth(const base::DictionaryValue& input,
                               const UserInfo& user_info,
                               const RequestCallback& callback) {
  ErrorPtr error;

  std::string auth_code_type;
  AuthType auth_type{};
  if (!input.GetString(kAuthModeKey, &auth_code_type) ||
      !StringToEnum(auth_code_type, &auth_type)) {
    Error::AddToPrintf(&error, FROM_HERE, errors::kInvalidAuthMode,
                       kInvalidParamValueFormat, kAuthModeKey,
                       auth_code_type.c_str());
    return ReturnError(*error, callback);
  }

  AuthScope desired_scope = AuthScope::kOwner;
  AuthScope acceptable_scope = AuthScope::kViewer;

  std::string requested_scope;
  input.GetString(kAuthRequestedScopeKey, &requested_scope);
  if (requested_scope != kAuthScopeAutoValue) {
    if (!StringToEnum(requested_scope, &desired_scope)) {
      Error::AddToPrintf(&error, FROM_HERE, errors::kInvalidRequestedScope,
                         kInvalidParamValueFormat, kAuthRequestedScopeKey,
                         requested_scope.c_str());
      return ReturnError(*error, callback);
    }
    acceptable_scope = std::max(desired_scope, acceptable_scope);
  }

  if (auth_type == AuthType::kAnonymous)
    desired_scope = GetAnonymousMaxScope(*cloud_, wifi_);

  std::string auth_code;
  input.GetString(kAuthCodeKey, &auth_code);

  std::string access_token;
  base::TimeDelta access_token_ttl;
  AuthScope access_token_scope = AuthScope::kNone;
  if (!security_->CreateAccessToken(auth_type, auth_code, desired_scope,
                                    &access_token, &access_token_scope,
                                    &access_token_ttl, &error)) {
    return ReturnError(*error, callback);
  }

  CHECK_LE(static_cast<int32_t>(access_token_scope),
           static_cast<int32_t>(desired_scope));

  if (access_token_scope < acceptable_scope) {
    Error::AddToPrintf(&error, FROM_HERE, errors::kAccessDenied,
                       "Scope '%s' is not allowed",
                       EnumToString(access_token_scope).c_str());
    return ReturnError(*error, callback);
  }

  base::DictionaryValue output;
  output.SetString(kAuthAccessTokenKey, access_token);
  output.SetString(kAuthTokenTypeKey, kAuthorizationHeaderPrefix);
  output.SetInteger(kAuthExpiresInKey, access_token_ttl.InSeconds());
  output.SetString(kAuthScopeKey, EnumToString(access_token_scope));

  callback.Run(http::kOk, output);
}

void PrivetHandler::HandleAccessControlClaim(const base::DictionaryValue& input,
                                             const UserInfo& user_info,
                                             const RequestCallback& callback) {
  ErrorPtr error;
  auto token = security_->ClaimRootClientAuthToken(&error);
  if (token.empty())
    return ReturnError(*error, callback);

  base::DictionaryValue output;
  output.SetString(kAuthClientTokenKey, token);
  callback.Run(http::kOk, output);
}

void PrivetHandler::HandleAccessControlConfirm(
    const base::DictionaryValue& input,
    const UserInfo& user_info,
    const RequestCallback& callback) {
  ErrorPtr error;

  std::string token;
  if (!input.GetString(kAuthClientTokenKey, &token)) {
    Error::AddToPrintf(&error, FROM_HERE, errors::kInvalidParams,
                       kInvalidParamValueFormat, kAuthClientTokenKey,
                       token.c_str());
    return ReturnError(*error, callback);
  }

  if (!security_->ConfirmClientAuthToken(token, &error))
    return ReturnError(*error, callback);

  base::DictionaryValue output;
  callback.Run(http::kOk, output);
}

void PrivetHandler::HandleSetupStart(const base::DictionaryValue& input,
                                     const UserInfo& user_info,
                                     const RequestCallback& callback) {
  std::string name{cloud_->GetName()};
  input.GetString(kNameKey, &name);

  std::string description{cloud_->GetDescription()};
  input.GetString(kDescrptionKey, &description);

  std::string location{cloud_->GetLocation()};
  input.GetString(kLocationKey, &location);

  std::string ssid;
  std::string passphrase;
  RegistrationData registration_data;
  std::string user;

  const base::DictionaryValue* wifi = nullptr;
  if (input.GetDictionary(kWifiKey, &wifi)) {
    if (!wifi_ || wifi_->GetTypes().empty()) {
      ErrorPtr error;
      Error::AddTo(&error, FROM_HERE, errors::kSetupUnavailable,
                   "WiFi setup unavailable");
      return ReturnError(*error, callback);
    }
    wifi->GetString(kSetupStartSsidKey, &ssid);
    if (ssid.empty()) {
      ErrorPtr error;
      Error::AddToPrintf(&error, FROM_HERE, errors::kInvalidParams,
                         kInvalidParamValueFormat, kSetupStartSsidKey, "");
      return ReturnError(*error, callback);
    }
    wifi->GetString(kSetupStartPassKey, &passphrase);
  }

  const base::DictionaryValue* registration = nullptr;
  if (input.GetDictionary(kGcdKey, &registration)) {
    if (user_info.scope() < AuthScope::kOwner) {
      ErrorPtr error;
      Error::AddTo(&error, FROM_HERE, errors::kInvalidAuthorizationScope,
                   "Only owner can register device");
      return ReturnError(*error, callback);
    }
    registration->GetString(kSetupStartTicketIdKey,
                            &registration_data.ticket_id);
    if (registration_data.ticket_id.empty()) {
      ErrorPtr error;
      Error::AddToPrintf(&error, FROM_HERE, errors::kInvalidParams,
                         kInvalidParamValueFormat, kSetupStartTicketIdKey, "");
      return ReturnError(*error, callback);
    }
    registration->GetString(kSetupStartUserKey, &user);
    registration->GetString(kSetupStartClientIdKey,
                            &registration_data.client_id);
    registration->GetString(kSetupStartClientSecretKey,
                            &registration_data.client_secret);
    registration->GetString(kSetupStartApiKeyKey, &registration_data.api_key);
    registration->GetString(kSetupStartOAuthUrlKey,
                            &registration_data.oauth_url);
    registration->GetString(kSetupStartServiceUrlKey,
                            &registration_data.service_url);
    registration->GetString(kSetupStartXmppEndpointKey,
                            &registration_data.xmpp_endpoint);
  }

  cloud_->UpdateDeviceInfo(name, description, location);

  ErrorPtr error;
  if (!ssid.empty() && !wifi_->ConfigureCredentials(ssid, passphrase, &error))
    return ReturnError(*error, callback);

  if (!registration_data.ticket_id.empty() &&
      !cloud_->Setup(registration_data, &error)) {
    return ReturnError(*error, callback);
  }

  ReplyWithSetupStatus(callback);
}

void PrivetHandler::HandleSetupStatus(const base::DictionaryValue&,
                                      const UserInfo& user_info,
                                      const RequestCallback& callback) {
  ReplyWithSetupStatus(callback);
}

void PrivetHandler::ReplyWithSetupStatus(
    const RequestCallback& callback) const {
  base::DictionaryValue output;

  const SetupState& state = cloud_->GetSetupState();
  if (!state.IsStatusEqual(SetupState::kNone)) {
    base::DictionaryValue* gcd = new base::DictionaryValue;
    output.Set(kGcdKey, gcd);
    SetStateProperties(state, gcd);
    if (state.IsStatusEqual(SetupState::kSuccess)) {
      SetGcdProperties(*cloud_, gcd);
    }
  }

  if (wifi_) {
    const SetupState& state = wifi_->GetSetupState();
    if (!state.IsStatusEqual(SetupState::kNone)) {
      base::DictionaryValue* wifi = new base::DictionaryValue;
      output.Set(kWifiKey, wifi);
      SetStateProperties(state, wifi);
      if (state.IsStatusEqual(SetupState::kSuccess))
        wifi->SetString(kInfoWifiSsidKey, wifi_->GetCurrentlyConnectedSsid());
    }
  }

  callback.Run(http::kOk, output);
}

void PrivetHandler::HandleTraits(const base::DictionaryValue& input,
                                 const UserInfo& user_info,
                                 const RequestCallback& callback) {
  base::DictionaryValue output;
  output.Set(kTraitsKey, cloud_->GetTraits().CreateDeepCopy());
  output.SetString(kFingerprintKey, std::to_string(traits_fingerprint_));

  callback.Run(http::kOk, output);
}

void PrivetHandler::HandleComponents(const base::DictionaryValue& input,
                                     const UserInfo& user_info,
                                     const RequestCallback& callback) {
  std::string path;
  std::set<std::string> filter;
  std::unique_ptr<base::DictionaryValue> components;

  input.GetString(kPathKey, &path);
  const base::ListValue* filter_items = nullptr;
  if (input.GetList(kFilterKey, &filter_items)) {
    for (const auto& value : *filter_items) {
      std::string filter_item;
      if (value->GetAsString(&filter_item))
        filter.insert(filter_item);
    }
  }
  const base::DictionaryValue* component = nullptr;
  if (!path.empty()) {
    ErrorPtr error;
    component = cloud_->FindComponent(path, &error);
    if (!component)
      return ReturnError(*error, callback);
    components.reset(new base::DictionaryValue);
    // Get the last element of the path and use it as a dictionary key here.
    auto parts = Split(path, ".", true, false);
    components->Set(parts.back(), CloneComponent(*component, filter));
  } else {
    components =
        CloneComponentTree(*cloud_->GetComponentsForUser(user_info), filter);
  }
  base::DictionaryValue output;
  output.Set(kComponentsKey, std::move(components));
  output.SetString(kFingerprintKey, std::to_string(components_fingerprint_));

  callback.Run(http::kOk, output);
}

void PrivetHandler::HandleCommandsExecute(const base::DictionaryValue& input,
                                          const UserInfo& user_info,
                                          const RequestCallback& callback) {
  cloud_->AddCommand(input, user_info,
                     base::Bind(&OnCommandRequestSucceeded, callback));
}

void PrivetHandler::HandleCommandsStatus(const base::DictionaryValue& input,
                                         const UserInfo& user_info,
                                         const RequestCallback& callback) {
  std::string id;
  if (!input.GetString(kCommandsIdKey, &id)) {
    ErrorPtr error;
    Error::AddToPrintf(&error, FROM_HERE, errors::kInvalidParams,
                       kInvalidParamValueFormat, kCommandsIdKey, id.c_str());
    return ReturnError(*error, callback);
  }
  cloud_->GetCommand(id, user_info,
                     base::Bind(&OnCommandRequestSucceeded, callback));
}

void PrivetHandler::HandleCommandsList(const base::DictionaryValue& input,
                                       const UserInfo& user_info,
                                       const RequestCallback& callback) {
  cloud_->ListCommands(user_info,
                       base::Bind(&OnCommandRequestSucceeded, callback));
}

void PrivetHandler::HandleCommandsCancel(const base::DictionaryValue& input,
                                         const UserInfo& user_info,
                                         const RequestCallback& callback) {
  std::string id;
  if (!input.GetString(kCommandsIdKey, &id)) {
    ErrorPtr error;
    Error::AddToPrintf(&error, FROM_HERE, errors::kInvalidParams,
                       kInvalidParamValueFormat, kCommandsIdKey, id.c_str());
    return ReturnError(*error, callback);
  }
  cloud_->CancelCommand(id, user_info,
                        base::Bind(&OnCommandRequestSucceeded, callback));
}

void PrivetHandler::HandleCheckForUpdates(const base::DictionaryValue& input,
                                          const UserInfo& user_info,
                                          const RequestCallback& callback) {
  int timeout_seconds = -1;
  input.GetInteger(kWaitTimeoutKey, &timeout_seconds);
  base::TimeDelta timeout = device_->GetHttpRequestTimeout();
  // Allow 10 seconds to cut the timeout short to make sure HTTP server doesn't
  // kill the connection before we have a chance to respond. 10 seconds chosen
  // at random here without any scientific basis for the value.
  const base::TimeDelta safety_gap = base::TimeDelta::FromSeconds(10);
  if (timeout != base::TimeDelta::Max()) {
    if (timeout > safety_gap)
      timeout -= safety_gap;
    else
      timeout = base::TimeDelta::FromSeconds(0);
  }
  if (timeout_seconds >= 0)
    timeout = std::min(timeout, base::TimeDelta::FromSeconds(timeout_seconds));
  if (timeout == base::TimeDelta{})
    return ReplyToUpdateRequest(callback);

  std::string state_fingerprint;
  std::string commands_fingerprint;
  std::string traits_fingerprint;
  std::string components_fingerprint;
  input.GetString(kStateFingerprintKey, &state_fingerprint);
  input.GetString(kCommandsFingerprintKey, &commands_fingerprint);
  input.GetString(kTraitsFingerprintKey, &traits_fingerprint);
  input.GetString(kComponentsFingerprintKey, &components_fingerprint);
  const bool ignore_state = state_fingerprint.empty();
  const bool ignore_commands = commands_fingerprint.empty();
  const bool ignore_traits = traits_fingerprint.empty();
  const bool ignore_components = components_fingerprint.empty();
  // If all fingerprints are missing, nothing to wait for, return immediately.
  if (ignore_state && ignore_commands && ignore_traits && ignore_components)
    return ReplyToUpdateRequest(callback);
  // If the current state fingerprint is different from the requested one,
  // return new fingerprints.
  if (!ignore_state && state_fingerprint != std::to_string(state_fingerprint_))
    return ReplyToUpdateRequest(callback);
  // If the current commands fingerprint is different from the requested one,
  // return new fingerprints.
  // NOTE: We are using traits fingerprint for command fingerprint as well.
  if (!ignore_commands &&
      commands_fingerprint != std::to_string(traits_fingerprint_)) {
    return ReplyToUpdateRequest(callback);
  }
  // If the current traits fingerprint is different from the requested one,
  // return new fingerprints.
  if (!ignore_traits &&
      traits_fingerprint != std::to_string(traits_fingerprint_)) {
    return ReplyToUpdateRequest(callback);
  }
  // If the current components fingerprint is different from the requested one,
  // return new fingerprints.
  if (!ignore_components &&
      components_fingerprint != std::to_string(components_fingerprint_)) {
    return ReplyToUpdateRequest(callback);
  }

  UpdateRequestParameters params;
  params.request_id = ++last_update_request_id_;
  params.callback = callback;
  params.traits_fingerprint =
      (ignore_traits && ignore_commands) ? 0 : traits_fingerprint_;
  params.state_fingerprint = ignore_state ? 0 : state_fingerprint_;
  params.components_fingerprint =
      ignore_components ? 0 : components_fingerprint_;
  update_requests_.push_back(params);
  if (timeout != base::TimeDelta::Max()) {
    device_->PostDelayedTask(
        FROM_HERE,
        base::Bind(&PrivetHandler::OnUpdateRequestTimeout,
                   weak_ptr_factory_.GetWeakPtr(), last_update_request_id_),
        timeout);
  }
}

void PrivetHandler::ReplyToUpdateRequest(
    const RequestCallback& callback) const {
  base::DictionaryValue output;
  output.SetString(kStateFingerprintKey, std::to_string(state_fingerprint_));
  output.SetString(kCommandsFingerprintKey,
                   std::to_string(traits_fingerprint_));
  output.SetString(kTraitsFingerprintKey, std::to_string(traits_fingerprint_));
  output.SetString(kComponentsFingerprintKey,
                   std::to_string(components_fingerprint_));
  callback.Run(http::kOk, output);
}

void PrivetHandler::OnUpdateRequestTimeout(int update_request_id) {
  auto pred = [update_request_id](const UpdateRequestParameters& params) {
    return params.request_id != update_request_id;
  };
  auto last =
      std::partition(update_requests_.begin(), update_requests_.end(), pred);
  for (auto p = last; p != update_requests_.end(); ++p)
    ReplyToUpdateRequest(p->callback);
  update_requests_.erase(last, update_requests_.end());
}

}  // namespace privet
}  // namespace weave
