// Copyright 2014 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 "privetd/privet_handler.h"

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/values.h>
#include <chromeos/http/http_request.h>
#include <chromeos/strings/string_utils.h>

#include "privetd/cloud_delegate.h"
#include "privetd/device_delegate.h"
#include "privetd/security_delegate.h"
#include "privetd/wifi_delegate.h"

namespace privetd {

namespace {

const char kInfoApiPath[] = "/privet/info";
const char kPairingStartApiPath[] = "/privet/v3/pairing/start";
const char kPairingConfirmApiPath[] = "/privet/v3/pairing/confirm";
const char kAuthApiPath[] = "/privet/v3/auth";
const char kSetupStartApiPath[] = "/privet/v3/setup/start";
const char kSetupStatusApiPath[] = "/privet/v3/setup/status";

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 kInfoIdKey[] = "id";
const char kInfoServicesKey[] = "services";
const char kInfoClassKey[] = "class";
const char kInfoModelIdKey[] = "modelId";

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

const char kInfoAuthenticationKey[] = "authentication";

const char kInfoWifiCapabilitiesKey[] = "capabilities";
const char kInfoWifiSsidKey[] = "ssid";
const char kInfoWifiHostedSsidKey[] = "hostedSsid";

const char kInfoUptimeKey[] = "uptime";
const char kInfoApiKey[] = "api";

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 kAuthTypeAnonymousValue[] = "anonymous";
const char kAuthTypePairingValue[] = "pairing";
const char kAuthTypeCloudValue[] = "cloud";

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 kAuthorizationHeaderPrefix[] = "Privet";
const char kErrorReasonKey[] = "reason";
const char kErrorMessageKey[] = "message";

const char kSetupStartSsidKey[] = "ssid";
const char kSetupStartPassKey[] = "passphrase";
const char kSetupStartTicketIdKey[] = "ticketId";
const char kSetupStartUserKey[] = "user";

const int kAccesssTokenExpirationSeconds = 3600;

// Threshold to reduce probability of expiration because of clock difference
// between device and client. Value is just a guess.
const int kAccesssTokenExpirationThresholdSeconds = 300;

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

template <typename T>
class EnumToStringMap {
 public:
  static std::string FindNameById(T id) {
    for (const Map& m : kMap) {
      if (m.id == id) {
        CHECK(m.name);
        return m.name;
      }
    }
    NOTREACHED();
    return std::string();
  }

  static bool FindIdByName(const std::string& name, T* id) {
    for (const Map& m : kMap) {
      if (m.name && m.name == name) {
        *id = m.id;
        return true;
      }
    }
    return false;
  }

 private:
  struct Map {
    const T id;
    const char* const name;
  };
  static const Map kMap[];
};

template <>
const EnumToStringMap<ConnectionState::Status>::Map
    EnumToStringMap<ConnectionState::Status>::kMap[] = {
        {ConnectionState::kDisabled, "disabled"},
        {ConnectionState::kUnconfigured, "unconfigured"},
        {ConnectionState::kConnecting, "connecting"},
        {ConnectionState::kOnline, "online"},
        {ConnectionState::kOffline, "offline"},
        {ConnectionState::kError, "error"},
};

template <>
const EnumToStringMap<SetupState::Status>::Map
    EnumToStringMap<SetupState::Status>::kMap[] = {
        {SetupState::kNone, nullptr},
        {SetupState::kInProgress, "inProgress"},
        {SetupState::kSuccess, "success"},
        {SetupState::kError, "error"},
};

template <>
const EnumToStringMap<Error>::Map EnumToStringMap<Error>::kMap[] = {
    {Error::kNone, nullptr},
    {Error::kInvalidFormat, "invalidFormat"},
    {Error::kMissingAuthorization, "missingAuthorization"},
    {Error::kInvalidAuthorization, "invalidAuthorization"},
    {Error::kInvalidAuthorizationScope, "invalidAuthorizationScope"},
    {Error::kCommitmentMismatch, "commitmentMismatch"},
    {Error::kUnknownSession, "unknownSession"},
    {Error::kInvalidAuthCode, "invalidAuthCode"},
    {Error::kInvalidAuthMode, "invalidAuthMode"},
    {Error::kInvalidRequestedScope, "invalidRequestedScope"},
    {Error::kAccessDenied, "accessDenied"},
    {Error::kInvalidParams, "invalidParams"},
    {Error::kSetupUnavailable, "setupUnavailable"},
    {Error::kDeviceBusy, "deviceBusy"},
    {Error::kInvalidTicket, "invalidTicket"},
    {Error::kServerError, "serverError"},
    {Error::kDeviceConfigError, "deviceConfigError"},
    {Error::kInvalidSsid, "invalidSsid"},
    {Error::kInvalidPassphrase, "invalidPassphrase"},
};

template <>
const EnumToStringMap<WifiType>::Map EnumToStringMap<WifiType>::kMap[] = {
    {WifiType::kWifi24, "2.4GHz"},
    {WifiType::kWifi50, "5.0GHz"},
};

template <>
const EnumToStringMap<PairingType>::Map EnumToStringMap<PairingType>::kMap[] = {
    {PairingType::kPinCode, "pinCode"},
    {PairingType::kEmbeddedCode, "embeddedCode"},
    {PairingType::kUltrasoundDsssBroadcaster, "ultrasoundDsssBroadcaster"},
    {PairingType::kAudibleDtmfBroadcaster, "audibleDtmfBroadcaster"},
};

template <>
const EnumToStringMap<CryptoType>::Map EnumToStringMap<CryptoType>::kMap[] = {
    {CryptoType::kNone, "none"},
    {CryptoType::kSpake_p224, "p224_spake2"},
    {CryptoType::kSpake_p256, "p256_spake2"},
};

template <>
const EnumToStringMap<AuthScope>::Map EnumToStringMap<AuthScope>::kMap[] = {
    {AuthScope::kNone, nullptr},
    {AuthScope::kGuest, "guest"},
    {AuthScope::kViewer, "viewer"},
    {AuthScope::kUser, "user"},
    {AuthScope::kOwner, "owner"},
};

template <typename T>
std::string EnumToString(T id) {
  return EnumToStringMap<T>::FindNameById(id);
}

template <typename T>
bool StringToEnum(const std::string& name, T* id) {
  return EnumToStringMap<T>::FindIdByName(name, id);
}

AuthScope AuthScopeFromString(const std::string& scope, AuthScope auto_scope) {
  if (scope == kAuthScopeAutoValue)
    return auto_scope;
  AuthScope scope_id = AuthScope::kNone;
  StringToEnum(scope, &scope_id);
  return scope_id;
}

std::string GetAuthTokenFromAuthHeader(const std::string& auth_header) {
  std::string name;
  std::string value;
  chromeos::string_utils::SplitAtFirst(auth_header, ' ', &name, &value);
  return value;
}

std::unique_ptr<base::DictionaryValue> CreateError(Error error,
                                                   const std::string& message) {
  if (error == Error::kNone)
    return nullptr;
  std::unique_ptr<base::DictionaryValue> output(new base::DictionaryValue);
  output->SetString(kErrorReasonKey, EnumToString(error));
  if (!message.empty())
    output->SetString(kErrorMessageKey, message);
  return output;
}

template <class T>
void SetState(const T& state, base::DictionaryValue* parent) {
  parent->SetString(kStatusKey, EnumToString(state.status));
  if (state.error == Error::kNone)
    return;
  parent->Set(kErrorKey,
              CreateError(state.error, state.error_message).release());
}

void ReturnErrorWithMessage(Error error,
                            const std::string& message,
                            const PrivetHandler::RequestCallback& callback) {
  std::unique_ptr<base::DictionaryValue> output = CreateError(error, message);
  callback.Run(chromeos::http::status_code::BadRequest, *output);
}

void ReturnError(Error error, const PrivetHandler::RequestCallback& callback) {
  ReturnErrorWithMessage(error, std::string(), callback);
}

void ReturnNotFound(const PrivetHandler::RequestCallback& callback) {
  callback.Run(chromeos::http::status_code::NotFound, base::DictionaryValue());
}

}  // namespace

PrivetHandler::PrivetHandler(CloudDelegate* cloud,
                             DeviceDelegate* device,
                             SecurityDelegate* security,
                             WifiDelegate* wifi)
    : cloud_(cloud), device_(device), security_(security), wifi_(wifi) {
  handlers_[kInfoApiPath] = std::make_pair(
      AuthScope::kGuest,
      base::Bind(&PrivetHandler::HandleInfo, base::Unretained(this)));
  handlers_[kPairingStartApiPath] = std::make_pair(
      AuthScope::kGuest,
      base::Bind(&PrivetHandler::HandlePairingStart, base::Unretained(this)));
  handlers_[kPairingConfirmApiPath] = std::make_pair(
      AuthScope::kGuest,
      base::Bind(&PrivetHandler::HandlePairingConfirm, base::Unretained(this)));
  handlers_[kAuthApiPath] = std::make_pair(
      AuthScope::kGuest,
      base::Bind(&PrivetHandler::HandleAuth, base::Unretained(this)));
  handlers_[kSetupStartApiPath] = std::make_pair(
      AuthScope::kOwner,
      base::Bind(&PrivetHandler::HandleSetupStart, base::Unretained(this)));
  handlers_[kSetupStatusApiPath] = std::make_pair(
      AuthScope::kOwner,
      base::Bind(&PrivetHandler::HandleSetupStatus, base::Unretained(this)));
}

PrivetHandler::~PrivetHandler() {
}

void PrivetHandler::HandleRequest(const std::string& api,
                                  const std::string& auth_header,
                                  const base::DictionaryValue* input,
                                  const RequestCallback& callback) {
  if (!input)
    return ReturnError(Error::kInvalidFormat, callback);
  auto handler = handlers_.find(api);
  if (handler == handlers_.end())
    return ReturnNotFound(callback);
  if (auth_header.empty())
    return ReturnError(Error::kMissingAuthorization, callback);
  std::string token = GetAuthTokenFromAuthHeader(auth_header);
  if (token.empty())
    return ReturnError(Error::kInvalidAuthorization, callback);
  AuthScope scope = AuthScope::kNone;
  if (token == kAuthTypeAnonymousValue) {
    scope = AuthScope::kGuest;
  } else {
    base::Time time;
    scope = security_->ParseAccessToken(token, &time);
    time += base::TimeDelta::FromSeconds(kAccesssTokenExpirationSeconds);
    time +=
        base::TimeDelta::FromSeconds(kAccesssTokenExpirationThresholdSeconds);
    if (time < base::Time::Now())
      scope = AuthScope::kNone;
  }
  if (scope == AuthScope::kNone)
    return ReturnError(Error::kInvalidAuthorization, callback);
  if (handler->second.first > scope)
    return ReturnError(Error::kInvalidAuthorizationScope, callback);
  handler->second.second.Run(*input, callback);
}

void PrivetHandler::HandleInfo(const base::DictionaryValue&,
                               const RequestCallback& callback) {
  base::DictionaryValue output;
  output.SetString(kInfoVersionKey, kInfoVersionValue);
  output.SetString(kInfoIdKey, device_->GetId());
  output.SetString(kNameKey, device_->GetName());

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

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

  std::string dev_class{device_->GetClass()};
  CHECK_EQ(2u, dev_class.size());
  output.SetString(kInfoClassKey, dev_class);
  std::string model_id{device_->GetModelId()};
  CHECK_EQ(3u, model_id.size());
  output.SetString(kInfoModelIdKey, model_id);
  output.Set(kInfoServicesKey, ToValue(device_->GetServices()).release());

  output.Set(kInfoAuthenticationKey, CreateInfoAuthSection().release());

  output.Set(kInfoEndpointsKey, CreateEndpointsSection().release());

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

  if (cloud_)
    output.Set(kGcdKey, CreateGcdSection().release());

  output.SetInteger(kInfoUptimeKey, device_->GetUptime().InSeconds());

  std::unique_ptr<base::ListValue> apis(new base::ListValue());
  for (const auto& key_value : handlers_)
    apis->AppendString(key_value.first);
  output.Set(kInfoApiKey, apis.release());

  callback.Run(chromeos::http::status_code::Ok, output);
}

void PrivetHandler::HandlePairingStart(const base::DictionaryValue& input,
                                       const RequestCallback& callback) {
  std::string pairing_str;
  input.GetString(kPairingKey, &pairing_str);

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

  PairingType pairing;
  std::vector<PairingType> modes = security_->GetPairingTypes();
  if (!StringToEnum(pairing_str, &pairing) ||
      std::find(modes.begin(), modes.end(), pairing) == modes.end()) {
    return ReturnError(Error::kInvalidParams, callback);
  }

  CryptoType crypto;
  std::vector<CryptoType> cryptos = security_->GetCryptoTypes();
  if (!StringToEnum(crypto_str, &crypto) ||
      std::find(cryptos.begin(), cryptos.end(), crypto) == cryptos.end()) {
    return ReturnError(Error::kInvalidParams, callback);
  }

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

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

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

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

  std::string fingerprint;
  std::string signature;
  Error error =
      security_->ConfirmPairing(id, commitment, &fingerprint, &signature);
  if (error != Error::kNone)
    return ReturnError(error, callback);

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

void PrivetHandler::HandleAuth(const base::DictionaryValue& input,
                               const RequestCallback& callback) {
  std::string auth_code_type;
  input.GetString(kAuthModeKey, &auth_code_type);

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

  AuthScope max_auth_scope = AuthScope::kNone;
  if (auth_code_type == kAuthTypeAnonymousValue) {
    max_auth_scope = AuthScope::kGuest;
  } else if (auth_code_type == kAuthTypePairingValue) {
    if (!security_->IsValidPairingCode(auth_code))
      return ReturnError(Error::kInvalidAuthCode, callback);
    max_auth_scope = AuthScope::kOwner;
  } else {
    return ReturnError(Error::kInvalidAuthMode, callback);
  }

  std::string requested_scope;
  input.GetString(kAuthRequestedScopeKey, &requested_scope);

  AuthScope requested_auth_scope =
      AuthScopeFromString(requested_scope, max_auth_scope);
  if (requested_auth_scope == AuthScope::kNone)
    return ReturnError(Error::kInvalidRequestedScope, callback);

  if (requested_auth_scope > max_auth_scope)
    return ReturnError(Error::kAccessDenied, callback);

  base::DictionaryValue output;
  output.SetString(
      kAuthAccessTokenKey,
      security_->CreateAccessToken(requested_auth_scope, base::Time::Now()));
  output.SetString(kAuthTokenTypeKey, kAuthorizationHeaderPrefix);
  output.SetInteger(kAuthExpiresInKey, kAccesssTokenExpirationSeconds);
  output.SetString(kAuthScopeKey, EnumToString(requested_auth_scope));
  callback.Run(chromeos::http::status_code::Ok, output);
}

void PrivetHandler::HandleSetupStart(const base::DictionaryValue& input,
                                     const RequestCallback& callback) {
  std::string param;
  if (input.GetString(kNameKey, &param))
    device_->SetName(param);
  if (input.GetString(kDescrptionKey, &param))
    device_->SetDescription(param);
  if (input.GetString(kLocationKey, &param))
    device_->SetLocation(param);

  std::string ssid;
  std::string passphrase;
  std::string ticket;
  std::string user;

  const base::DictionaryValue* wifi = nullptr;
  if (input.GetDictionary(kWifiKey, &wifi)) {
    if (!wifi_ || wifi_->GetTypes().empty())
      return ReturnError(Error::kSetupUnavailable, callback);
    wifi->GetString(kSetupStartSsidKey, &ssid);
    if (ssid.empty())
      return ReturnError(Error::kInvalidParams, callback);
    wifi->GetString(kSetupStartPassKey, &passphrase);
  }

  const base::DictionaryValue* registration = nullptr;
  if (input.GetDictionary(kGcdKey, &registration)) {
    if (!cloud_)
      return ReturnError(Error::kSetupUnavailable, callback);
    registration->GetString(kSetupStartTicketIdKey, &ticket);
    if (ticket.empty())
      return ReturnError(Error::kInvalidParams, callback);
    registration->GetString(kSetupStartUserKey, &user);
  }

  if (!ssid.empty() && !wifi_->ConfigureCredentials(ssid, passphrase))
    return ReturnError(Error::kDeviceBusy, callback);

  if (!ticket.empty() && !cloud_->Setup(ticket, user))
    return ReturnError(Error::kDeviceBusy, callback);

  return HandleSetupStatus(input, callback);
}

void PrivetHandler::HandleSetupStatus(const base::DictionaryValue& input,
                                      const RequestCallback& callback) {
  base::DictionaryValue output;

  if (cloud_) {
    SetupState state = cloud_->GetSetupState();
    if (state.status != SetupState::kNone) {
      base::DictionaryValue* gcd = new base::DictionaryValue;
      output.Set(kGcdKey, gcd);
      SetState(state, gcd);
      if (state.status == SetupState::kSuccess)
        gcd->SetString(kInfoIdKey, cloud_->GetCloudId());
    }
  }

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

  callback.Run(chromeos::http::status_code::Ok, output);
}

std::unique_ptr<base::DictionaryValue> PrivetHandler::CreateEndpointsSection()
    const {
  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 std::move(endpoints);
}

std::unique_ptr<base::DictionaryValue> PrivetHandler::CreateInfoAuthSection()
    const {
  std::unique_ptr<base::DictionaryValue> auth(new base::DictionaryValue());

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

  std::unique_ptr<base::ListValue> auth_types(new base::ListValue());
  auth_types->AppendString(kAuthTypeAnonymousValue);
  auth_types->AppendString(kAuthTypePairingValue);
  if (cloud_ && cloud_->GetConnectionState().status == ConnectionState::kOnline)
    auth_types->AppendString(kAuthTypeCloudValue);
  auth->Set(kAuthModeKey, auth_types.release());

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

  return std::move(auth);
}

std::unique_ptr<base::DictionaryValue> PrivetHandler::CreateWifiSection()
    const {
  std::unique_ptr<base::DictionaryValue> wifi(new base::DictionaryValue());

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

  wifi->SetString(kInfoWifiSsidKey, wifi_->GetCurrentlyConnectedSsid());

  std::string hosted_ssid = wifi_->GetHostedSsid();
  ConnectionState state = wifi_->GetConnectionState();
  if (!hosted_ssid.empty()) {
    DCHECK(state.status != ConnectionState::kDisabled);
    DCHECK(state.status != ConnectionState::kOnline);
    wifi->SetString(kInfoWifiHostedSsidKey, hosted_ssid);
  }
  SetState(state, wifi.get());
  return std::move(wifi);
}

std::unique_ptr<base::DictionaryValue> PrivetHandler::CreateGcdSection() const {
  std::unique_ptr<base::DictionaryValue> gcd(new base::DictionaryValue());
  gcd->SetString(kInfoIdKey, cloud_->GetCloudId());
  SetState(cloud_->GetConnectionState(), gcd.get());
  return std::move(gcd);
}

}  // namespace privetd
