// 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(::std::string 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
