// 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_manager.h"

#include <memory>
#include <set>
#include <string>

#include <base/bind.h>
#include <base/json/json_reader.h>
#include <base/json/json_writer.h>
#include <base/memory/weak_ptr.h>
#include <base/scoped_observer.h>
#include <base/strings/string_number_conversions.h>
#include <base/values.h>
#include <weave/provider/network.h>

#include "src/bind_lambda.h"
#include "src/device_registration_info.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/privet_handler.h"
#include "src/privet/publisher.h"
#include "src/streams.h"
#include "src/string_utils.h"

namespace weave {
namespace privet {

using provider::TaskRunner;
using provider::Network;
using provider::DnsServiceDiscovery;
using provider::HttpServer;
using provider::Wifi;

Manager::Manager(TaskRunner* task_runner) : task_runner_{task_runner} {}

Manager::~Manager() {}

void Manager::Start(Network* network,
                    DnsServiceDiscovery* dns_sd,
                    HttpServer* http_server,
                    Wifi* wifi,
                    DeviceRegistrationInfo* device,
                    CommandManager* command_manager,
                    StateManager* state_manager) {
  disable_security_ = device->GetSettings().disable_security;

  device_ = DeviceDelegate::CreateDefault(http_server->GetHttpPort(),
                                          http_server->GetHttpsPort());
  cloud_ = CloudDelegate::CreateDefault(task_runner_, device, command_manager,
                                        state_manager);
  cloud_observer_.Add(cloud_.get());
  security_.reset(new SecurityManager(
      device->GetSettings().secret, device->GetSettings().pairing_modes,
      device->GetSettings().embedded_code, disable_security_, task_runner_));
  security_->SetCertificateFingerprint(
      http_server->GetHttpsCertificateFingerprint());
  if (device->GetSettings().secret.empty()) {
    // TODO(vitalybuka): Post all Config::Transaction to avoid following.
    task_runner_->PostDelayedTask(
        FROM_HERE,
        base::Bind(&Manager::SaveDeviceSecret, weak_ptr_factory_.GetWeakPtr(),
                   base::Unretained(device->GetMutableConfig())),
        {});
  }
  network->AddConnectionChangedCallback(
      base::Bind(&Manager::OnConnectivityChanged, base::Unretained(this)));

  if (wifi && device->GetSettings().wifi_auto_setup_enabled) {
    VLOG(1) << "Enabling WiFi bootstrapping.";
    wifi_bootstrap_manager_.reset(new WifiBootstrapManager(
        device->GetMutableConfig(), task_runner_, network, wifi, cloud_.get()));
    wifi_bootstrap_manager_->Init();
  }

  if (dns_sd) {
    publisher_.reset(new Publisher(device_.get(), cloud_.get(),
                                   wifi_bootstrap_manager_.get(), dns_sd));
  }

  privet_handler_.reset(new PrivetHandler(cloud_.get(), device_.get(),
                                          security_.get(),
                                          wifi_bootstrap_manager_.get()));

  for (const auto& path : privet_handler_->GetHttpPaths()) {
    http_server->AddHttpRequestHandler(
        path, base::Bind(&Manager::PrivetRequestHandler,
                         weak_ptr_factory_.GetWeakPtr()));
  }

  for (const auto& path : privet_handler_->GetHttpsPaths()) {
    http_server->AddHttpsRequestHandler(
        path, base::Bind(&Manager::PrivetRequestHandler,
                         weak_ptr_factory_.GetWeakPtr()));
  }
}

std::string Manager::GetCurrentlyConnectedSsid() const {
  return wifi_bootstrap_manager_
             ? wifi_bootstrap_manager_->GetCurrentlyConnectedSsid()
             : "";
}

void Manager::AddOnPairingChangedCallbacks(
    const SecurityManager::PairingStartListener& on_start,
    const SecurityManager::PairingEndListener& on_end) {
  security_->RegisterPairingListeners(on_start, on_end);
}

void Manager::OnDeviceInfoChanged() {
  OnChanged();
}

void Manager::PrivetRequestHandler(
    std::unique_ptr<provider::HttpServer::Request> req) {
  std::shared_ptr<provider::HttpServer::Request> request{std::move(req)};

  std::string content_type =
      SplitAtFirst(request->GetFirstHeader(http::kContentType), ";", true)
          .first;

  return PrivetRequestHandlerWithData(request, content_type == http::kJson
                                                   ? request->GetData()
                                                   : std::string{});
}

void Manager::PrivetRequestHandlerWithData(
    const std::shared_ptr<provider::HttpServer::Request>& request,
    const std::string& data) {
  std::string auth_header = request->GetFirstHeader(http::kAuthorization);
  if (auth_header.empty() && disable_security_)
    auth_header = "Privet anonymous";

  base::DictionaryValue empty;
  auto value = base::JSONReader::Read(data);
  const base::DictionaryValue* dictionary = &empty;
  if (value)
    value->GetAsDictionary(&dictionary);

  VLOG(3) << "Input: " << *dictionary;

  privet_handler_->HandleRequest(
      request->GetPath(), auth_header, dictionary,
      base::Bind(&Manager::PrivetResponseHandler,
                 weak_ptr_factory_.GetWeakPtr(), request));
}

void Manager::PrivetResponseHandler(
    const std::shared_ptr<provider::HttpServer::Request>& request,
    int status,
    const base::DictionaryValue& output) {
  VLOG(3) << "status: " << status << ", Output: " << output;
  std::string data;
  base::JSONWriter::WriteWithOptions(
      output, base::JSONWriter::OPTIONS_PRETTY_PRINT, &data);
  request->SendReply(status, data, http::kJson);
}

void Manager::OnChanged() {
  VLOG(1) << "Manager::OnChanged";
  if (publisher_)
    publisher_->Update();
}

void Manager::OnConnectivityChanged() {
  OnChanged();
}

void Manager::SaveDeviceSecret(Config* config) {
  Config::Transaction transaction(config);
  transaction.set_secret(security_->GetSecret());
}

}  // namespace privet
}  // namespace weave
