// Copyright 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "buffet/manager.h"

#include <map>
#include <set>
#include <string>

#include <base/bind.h>
#include <base/bind_helpers.h>
#include <base/files/file_enumerator.h>
#include <base/files/file_util.h>
#include <base/json/json_reader.h>
#include <base/json/json_writer.h>
#include <base/message_loop/message_loop.h>
#include <base/time/time.h>
#include <binderwrapper/binder_wrapper.h>
#include <cutils/properties.h>
#include <brillo/bind_lambda.h>
#include <brillo/errors/error.h>
#include <brillo/http/http_transport.h>
#include <brillo/http/http_utils.h>
#include <brillo/key_value_store.h>
#include <brillo/message_loops/message_loop.h>
#include <brillo/mime_utils.h>
#include <dbus/bus.h>
#include <dbus/object_path.h>
#include <dbus/values_util.h>
#include <weave/enum_to_string.h>

#include "brillo/weaved_system_properties.h"
#include "buffet/bluetooth_client.h"
#include "buffet/buffet_config.h"
#include "buffet/http_transport_client.h"
#include "buffet/mdns_client.h"
#include "buffet/shill_client.h"
#include "buffet/weave_error_conversion.h"
#include "buffet/webserv_client.h"
#include "common/binder_utils.h"

using brillo::dbus_utils::AsyncEventSequencer;
using NotificationListener =
    android::weave::IWeaveServiceManagerNotificationListener;

namespace buffet {

namespace {

const char kErrorDomain[] = "buffet";
const char kFileReadError[] = "file_read_error";
const char kBaseComponent[] = "base";
const char kRebootCommand[] = "base.reboot";

bool LoadFile(const base::FilePath& file_path,
              std::string* data,
              brillo::ErrorPtr* error) {
  if (!base::ReadFileToString(file_path, data)) {
    brillo::errors::system::AddSystemError(error, FROM_HERE, errno);
    brillo::Error::AddToPrintf(error, FROM_HERE, kErrorDomain, kFileReadError,
                               "Failed to read file '%s'",
                               file_path.value().c_str());
    return false;
  }
  return true;
}

void LoadTraitDefinitions(const BuffetConfig::Options& options,
                          weave::Device* device) {
  // Load component-specific device trait definitions.
  base::FilePath dir{options.definitions.Append("traits")};
  LOG(INFO) << "Looking for trait definitions in " << dir.value();
  base::FileEnumerator enumerator(dir, false, base::FileEnumerator::FILES,
                                  FILE_PATH_LITERAL("*.json"));
  std::vector<std::string> result;
  for (base::FilePath path = enumerator.Next(); !path.empty();
       path = enumerator.Next()) {
    LOG(INFO) << "Loading trait definition from " << path.value();
    std::string json;
    CHECK(LoadFile(path, &json, nullptr));
    device->AddTraitDefinitionsFromJson(json);
  }
}

// Updates the manager's state property if the new value is different from
// the current value. In this case also adds the appropriate notification ID
// to the array to record the state change for clients.
void UpdateValue(Manager* manager,
                 std::string Manager::* prop,
                 const std::string& new_value,
                 int notification,
                 std::vector<int>* notification_ids) {
  if (manager->*prop != new_value) {
    manager->*prop = new_value;
    notification_ids->push_back(notification);
  }
}

}  // anonymous namespace

class Manager::TaskRunner : public weave::provider::TaskRunner {
 public:
  void PostDelayedTask(const tracked_objects::Location& from_here,
                       const base::Closure& task,
                       base::TimeDelta delay) override {
    brillo::MessageLoop::current()->PostDelayedTask(from_here, task, delay);
  }
};

Manager::Manager(const Options& options,
                 const scoped_refptr<dbus::Bus>& bus)
    : options_{options}, bus_{bus} {}

Manager::~Manager() {
  android::BinderWrapper* binder_wrapper = android::BinderWrapper::Get();
  for (const auto& listener : notification_listeners_) {
    binder_wrapper->UnregisterForDeathNotifications(
        android::IInterface::asBinder(listener));
  }
  for (const auto& pair : services_) {
    binder_wrapper->UnregisterForDeathNotifications(
        android::IInterface::asBinder(pair.first));
  }
}

void Manager::Start() {
  power_manager_client_.Init();
  RestartWeave();
}

void Manager::RestartWeave() {
  Stop();

  task_runner_.reset(new TaskRunner{});
  config_.reset(new BuffetConfig{options_.config_options});
  http_client_.reset(new HttpTransportClient);
  shill_client_.reset(new ShillClient{bus_,
                                      options_.device_whitelist,
                                      !options_.xmpp_enabled});
  weave::provider::HttpServer* http_server{nullptr};
#ifdef BUFFET_USE_WIFI_BOOTSTRAPPING
  if (!options_.disable_privet) {
    mdns_client_ = MdnsClient::CreateInstance();
    web_serv_client_.reset(new WebServClient{
        brillo::MessageLoop::current(),
        base::Bind(&Manager::CreateDevice, weak_ptr_factory_.GetWeakPtr())});
    bluetooth_client_ = BluetoothClient::CreateInstance();
    http_server = web_serv_client_.get();

    if (options_.enable_ping) {
      auto ping_handler = base::Bind(
          [](std::unique_ptr<weave::provider::HttpServer::Request> request) {
            request->SendReply(brillo::http::status_code::Ok, "Hello, world!",
                               brillo::mime::text::kPlain);
          });
      http_server->AddHttpRequestHandler("/privet/ping", ping_handler);
      http_server->AddHttpsRequestHandler("/privet/ping", ping_handler);
    }
  }
#endif  // BUFFET_USE_WIFI_BOOTSTRAPPING

  if (!http_server)
    CreateDevice();
}

void Manager::CreateDevice() {
  if (device_)
    return;

  device_ = weave::Device::Create(config_.get(), task_runner_.get(),
                                  http_client_.get(), shill_client_.get(),
                                  mdns_client_.get(), web_serv_client_.get(),
                                  shill_client_.get(), bluetooth_client_.get());

  LoadTraitDefinitions(options_.config_options, device_.get());

  device_->AddSettingsChangedCallback(
      base::Bind(&Manager::OnConfigChanged, weak_ptr_factory_.GetWeakPtr()));

  device_->AddTraitDefsChangedCallback(
      base::Bind(&Manager::OnTraitDefsChanged,
                 weak_ptr_factory_.GetWeakPtr()));
  device_->AddStateChangedCallback(
      base::Bind(&Manager::OnComponentTreeChanged,
                 weak_ptr_factory_.GetWeakPtr()));
  device_->AddComponentTreeChangedCallback(
      base::Bind(&Manager::OnComponentTreeChanged,
                 weak_ptr_factory_.GetWeakPtr()));

  device_->AddGcdStateChangedCallback(
      base::Bind(&Manager::OnGcdStateChanged, weak_ptr_factory_.GetWeakPtr()));

  device_->AddPairingChangedCallbacks(
      base::Bind(&Manager::OnPairingStart, weak_ptr_factory_.GetWeakPtr()),
      base::Bind(&Manager::OnPairingEnd, weak_ptr_factory_.GetWeakPtr()));

  device_->AddCommandHandler(kBaseComponent, kRebootCommand,
                             base::Bind(&Manager::OnRebootDevice,
                                        weak_ptr_factory_.GetWeakPtr()));

  CreateServicesForClients();
}

void Manager::Stop() {
  device_.reset();
#ifdef BUFFET_USE_WIFI_BOOTSTRAPPING
  web_serv_client_.reset();
  mdns_client_.reset();
#endif  // BUFFET_USE_WIFI_BOOTSTRAPPING
  shill_client_.reset();
  http_client_.reset();
  config_.reset();
  task_runner_.reset();
}

void Manager::OnTraitDefsChanged() {
  NotifyServiceManagerChange({NotificationListener::TRAITS});
}

void Manager::OnComponentTreeChanged() {
  NotifyServiceManagerChange({NotificationListener::COMPONENTS});
}

void Manager::OnGcdStateChanged(weave::GcdState state) {
  state_ = weave::EnumToString(state);
  NotifyServiceManagerChange({NotificationListener::STATE});
  property_set(weaved::system_properties::kState, state_.c_str());
}

void Manager::OnConfigChanged(const weave::Settings& settings) {
  std::vector<int> ids;
  UpdateValue(this, &Manager::cloud_id_, settings.cloud_id,
              NotificationListener::CLOUD_ID, &ids);
  UpdateValue(this, &Manager::device_id_, settings.device_id,
              NotificationListener::DEVICE_ID, &ids);
  UpdateValue(this, &Manager::device_name_, settings.name,
              NotificationListener::DEVICE_NAME, &ids);
  UpdateValue(this, &Manager::device_description_, settings.description,
              NotificationListener::DEVICE_DESCRIPTION, &ids);
  UpdateValue(this, &Manager::device_location_, settings.location,
              NotificationListener::DEVICE_LOCATION, &ids);
  UpdateValue(this, &Manager::oem_name_, settings.oem_name,
              NotificationListener::OEM_NAME, &ids);
  UpdateValue(this, &Manager::model_id_, settings.model_id,
              NotificationListener::MODEL_ID, &ids);
  UpdateValue(this, &Manager::model_name_, settings.model_name,
              NotificationListener::MODEL_NAME, &ids);
  NotifyServiceManagerChange(ids);
}

void Manager::OnPairingStart(const std::string& session_id,
                             weave::PairingType pairing_type,
                             const std::vector<uint8_t>& code) {
  // For now, just overwrite the exposed PairInfo with the most recent pairing
  // attempt.
  std::vector<int> ids;
  UpdateValue(this, &Manager::pairing_session_id_, session_id,
              NotificationListener::PAIRING_SESSION_ID, &ids);
  UpdateValue(this, &Manager::pairing_mode_, EnumToString(pairing_type),
              NotificationListener::PAIRING_MODE, &ids);
  std::string pairing_code{code.begin(), code.end()};
  UpdateValue(this, &Manager::pairing_code_, pairing_code,
              NotificationListener::PAIRING_CODE, &ids);
  NotifyServiceManagerChange(ids);
}

void Manager::OnPairingEnd(const std::string& session_id) {
  if (pairing_session_id_ != session_id)
    return;
  std::vector<int> ids;
  UpdateValue(this, &Manager::pairing_session_id_, "",
              NotificationListener::PAIRING_SESSION_ID, &ids);
  UpdateValue(this, &Manager::pairing_mode_, "",
              NotificationListener::PAIRING_MODE, &ids);
  UpdateValue(this, &Manager::pairing_code_, "",
              NotificationListener::PAIRING_CODE, &ids);
  NotifyServiceManagerChange(ids);
}

void Manager::OnRebootDevice(const std::weak_ptr<weave::Command>& cmd) {
  auto command = cmd.lock();
  if (!command || !command->Complete({}, nullptr))
    return;

  task_runner_->PostDelayedTask(
      FROM_HERE,
      base::Bind(&Manager::RebootDeviceNow, weak_ptr_factory_.GetWeakPtr()),
      base::TimeDelta::FromSeconds(2));
}

void Manager::RebootDeviceNow() {
  power_manager_client_.Reboot(android::RebootReason::DEFAULT);
}

android::binder::Status Manager::connect(
    const android::sp<android::weave::IWeaveClient>& client) {
  pending_clients_.push_back(client);
  if (device_)
    CreateServicesForClients();
  return android::binder::Status::ok();
}

android::binder::Status Manager::registerNotificationListener(
    const WeaveServiceManagerNotificationListener& listener) {
  notification_listeners_.insert(listener);
  android::BinderWrapper::Get()->RegisterForDeathNotifications(
      android::IInterface::asBinder(listener),
      base::Bind(&Manager::OnNotificationListenerDestroyed,
                 weak_ptr_factory_.GetWeakPtr(), listener));
  return android::binder::Status::ok();
}

android::binder::Status Manager::getCloudId(android::String16* id) {
  *id = weaved::binder_utils::ToString16(cloud_id_);
  return android::binder::Status::ok();
}

android::binder::Status Manager::getDeviceId(android::String16* id) {
  *id = weaved::binder_utils::ToString16(device_id_);
  return android::binder::Status::ok();
}

android::binder::Status Manager::getDeviceName(android::String16* name) {
  *name = weaved::binder_utils::ToString16(device_name_);
  return android::binder::Status::ok();
}

android::binder::Status Manager::getDeviceDescription(
    android::String16* description) {
  *description = weaved::binder_utils::ToString16(device_description_);
  return android::binder::Status::ok();
}

android::binder::Status Manager::getDeviceLocation(
    android::String16* location) {
  *location = weaved::binder_utils::ToString16(device_location_);
  return android::binder::Status::ok();
}

android::binder::Status Manager::getOemName(android::String16* name) {
  *name = weaved::binder_utils::ToString16(oem_name_);
  return android::binder::Status::ok();
}

android::binder::Status Manager::getModelName(android::String16* name) {
  *name = weaved::binder_utils::ToString16(model_name_);
  return android::binder::Status::ok();
}

android::binder::Status Manager::getModelId(android::String16* id) {
  *id = weaved::binder_utils::ToString16(model_id_);
  return android::binder::Status::ok();
}

android::binder::Status Manager::getPairingSessionId(android::String16* id) {
  *id = weaved::binder_utils::ToString16(pairing_session_id_);
  return android::binder::Status::ok();
}

android::binder::Status Manager::getPairingMode(android::String16* mode) {
  *mode = weaved::binder_utils::ToString16(pairing_mode_);
  return android::binder::Status::ok();
}

android::binder::Status Manager::getPairingCode(android::String16* code) {
  *code = weaved::binder_utils::ToString16(pairing_code_);
  return android::binder::Status::ok();
}

android::binder::Status Manager::getState(android::String16* state) {
  *state = weaved::binder_utils::ToString16(state_);
  return android::binder::Status::ok();
}

android::binder::Status Manager::getTraits(android::String16* traits) {
  *traits = weaved::binder_utils::ToString16(device_->GetTraits());
  return android::binder::Status::ok();
}

android::binder::Status Manager::getComponents(android::String16* components) {
  *components = weaved::binder_utils::ToString16(device_->GetComponents());
  return android::binder::Status::ok();
}

void Manager::CreateServicesForClients() {
  CHECK(device_);
  // For safety, iterate over a copy of |pending_clients_| and clear the
  // original vector before performing the iterations.
  std::vector<android::sp<android::weave::IWeaveClient>> pending_clients_copy;
  std::swap(pending_clients_copy, pending_clients_);
  for (const auto& client : pending_clients_copy) {
    android::sp<BinderWeaveService> service =
        new BinderWeaveService{device_.get(), client};
    services_.emplace(client, service);
    client->onServiceConnected(service);
    android::BinderWrapper::Get()->RegisterForDeathNotifications(
        android::IInterface::asBinder(client),
        base::Bind(&Manager::OnClientDisconnected,
                   weak_ptr_factory_.GetWeakPtr(),
                   client));
  }
}

void Manager::OnClientDisconnected(
    const android::sp<android::weave::IWeaveClient>& client) {
  services_.erase(client);
}

void Manager::OnNotificationListenerDestroyed(
    const WeaveServiceManagerNotificationListener& notification_listener) {
  notification_listeners_.erase(notification_listener);
}

void Manager::NotifyServiceManagerChange(
    const std::vector<int>& notification_ids) {
  if (notification_ids.empty())
    return;
  for (const auto& listener : notification_listeners_)
    listener->notifyServiceManagerChange(notification_ids);
}

}  // namespace buffet
