// Copyright 2017 The Fuchsia 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 "peridot/bin/sessionmgr/device_map_impl.h"

#include <limits.h>
#include <unistd.h>

#include <lib/fidl/cpp/binding_set.h>
#include <lib/fidl/cpp/interface_ptr.h>
#include <lib/fidl/cpp/optional.h>
#include <lib/fxl/time/time_point.h>

#include "peridot/bin/sessionmgr/storage/constants_and_utils.h"
#include "peridot/lib/fidl/json_xdr.h"
#include "peridot/lib/ledger_client/operations.h"

namespace modular {

namespace {

using ReadDeviceDataCall = ReadDataCall<fuchsia::modular::DeviceMapEntry>;
using ReadAllDeviceDataCall = ReadAllDataCall<fuchsia::modular::DeviceMapEntry>;
using WriteDeviceDataCall = WriteDataCall<fuchsia::modular::DeviceMapEntry>;

// Reads old versions of device data, which are missing a timestamp.
void XdrDeviceMapEntry_v1(XdrContext* const xdr,
                          fuchsia::modular::DeviceMapEntry* const data) {
  xdr->Field("name", &data->name);
  xdr->Field("device_id", &data->device_id);
  xdr->Field("profile", &data->profile);
  xdr->Field("hostname", &data->hostname);

  // The time below is 26 Sep 2017 17:44:40 GMT, just to mark the entry as old.
  // Since this filter is not the latest, it is only ever used FROM_JSON, never
  // TO_JSON.
  data->last_change_timestamp = 1506447879;
}

void XdrDeviceMapEntry_v2(XdrContext* const xdr,
                          fuchsia::modular::DeviceMapEntry* const data) {
  xdr->Field("name", &data->name);
  xdr->Field("device_id", &data->device_id);
  xdr->Field("profile", &data->profile);
  xdr->Field("hostname", &data->hostname);
  xdr->Field("last_change_timestamp", &data->last_change_timestamp);
}

void XdrDeviceMapEntry_v3(XdrContext* const xdr,
                          fuchsia::modular::DeviceMapEntry* const data) {
  if (!xdr->Version(3)) {
    return;
  }
  xdr->Field("name", &data->name);
  xdr->Field("device_id", &data->device_id);
  xdr->Field("profile", &data->profile);
  xdr->Field("hostname", &data->hostname);
  xdr->Field("last_change_timestamp", &data->last_change_timestamp);
}

constexpr XdrFilterType<fuchsia::modular::DeviceMapEntry> XdrDeviceMapEntry[] =
    {
        XdrDeviceMapEntry_v3,
        XdrDeviceMapEntry_v2,
        XdrDeviceMapEntry_v1,
        nullptr,
};

std::string LoadHostname() {
  char host_name_buffer[HOST_NAME_MAX + 1];
  int result = gethostname(host_name_buffer, sizeof(host_name_buffer));

  if (result < 0) {
    FXL_LOG(ERROR) << "unable to get hostname. errno " << errno;
    return "fuchsia";
  }

  return host_name_buffer;
}

}  // namespace

DeviceMapImpl::DeviceMapImpl(const std::string& device_name,
                             const std::string& device_id,
                             const std::string& device_profile,
                             LedgerClient* const ledger_client,
                             LedgerPageId page_id)
    : PageClient("DeviceMapImpl", ledger_client, std::move(page_id),
                 kDeviceKeyPrefix) {
  current_device_id_ = device_id;

  // TODO(jimbe) Load the fuchsia::modular::DeviceMapEntry for the current
  // device from the Ledger.
  fuchsia::modular::DeviceMapEntry device;
  device.name = device_name;
  device.device_id = device_id;
  device.profile = device_profile;
  device.hostname = LoadHostname();

  devices_[device_id] = std::move(device);
  SaveCurrentDevice();
}

DeviceMapImpl::~DeviceMapImpl() = default;

void DeviceMapImpl::Connect(
    fidl::InterfaceRequest<fuchsia::modular::DeviceMap> request) {
  bindings_.AddBinding(this, std::move(request));
}

void DeviceMapImpl::Query(QueryCallback callback) {
  operation_queue_.Add(new ReadAllDeviceDataCall(page(), kDeviceKeyPrefix,
                                                 XdrDeviceMapEntry, callback));
}

void DeviceMapImpl::GetCurrentDevice(GetCurrentDeviceCallback callback) {
  callback(devices_[current_device_id_]);
}

void DeviceMapImpl::SetCurrentDeviceProfile(::fidl::StringPtr profile) {
  devices_[current_device_id_].profile = profile;
  Notify(current_device_id_);
  SaveCurrentDevice();
}

void DeviceMapImpl::SaveCurrentDevice() {
  auto& device = devices_[current_device_id_];
  device.last_change_timestamp = time(nullptr);

  operation_queue_.Add(new WriteDeviceDataCall(
      page(), MakeDeviceKey(current_device_id_), XdrDeviceMapEntry,
      fidl::MakeOptional(device), [] {}));
}

void DeviceMapImpl::WatchDeviceMap(
    fidl::InterfaceHandle<fuchsia::modular::DeviceMapWatcher> watcher) {
  auto watcher_ptr = watcher.Bind();
  for (const auto& item : devices_) {
    const auto& device = item.second;
    watcher_ptr->OnDeviceMapChange(device);
  }
  change_watchers_.AddInterfacePtr(std::move(watcher_ptr));
}

void DeviceMapImpl::Notify(const std::string& device_id) {
  const fuchsia::modular::DeviceMapEntry& device = devices_[current_device_id_];
  for (auto& watcher : change_watchers_.ptrs()) {
    (*watcher)->OnDeviceMapChange(device);
  }
}

void DeviceMapImpl::OnPageChange(const std::string& key,
                                 const std::string& value) {
  FXL_LOG(INFO) << "Updated Device: " << key << " value=" << value;

  fuchsia::modular::DeviceMapEntry device;
  if (!XdrRead(value, &device, XdrDeviceMapEntry)) {
    FXL_DCHECK(false);
    return;
  }

  fidl::StringPtr device_id = device.device_id;
  devices_[device_id] = std::move(device);
  Notify(device_id);
}

void DeviceMapImpl::OnPageDelete(const std::string& key) {
  // This shouldn't happen.
  FXL_LOG(ERROR) << "Deleted Device: " << key;
}

}  // namespace modular
