// 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";

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() {
  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()));

  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);
}

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
