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

#include <lib/fidl/cpp/array.h>
#include <lib/fsl/vmo/strings.h>
#include <lib/fxl/time/time_point.h>

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

namespace modular {

namespace {

// Serialization and deserialization of fuchsia::modular::FocusInfo to and from
// JSON.
void XdrFocusInfo_v1(XdrContext* const xdr,
                     fuchsia::modular::FocusInfo* const data) {
  xdr->Field("device_id", &data->device_id);
  xdr->Field("focused_story_id", &data->focused_story_id);
  xdr->Field("last_focus_timestamp", &data->last_focus_change_timestamp);
}

void XdrFocusInfo_v2(XdrContext* const xdr,
                     fuchsia::modular::FocusInfo* const data) {
  if (!xdr->Version(2)) {
    return;
  }
  xdr->Field("device_id", &data->device_id);
  xdr->Field("focused_story_id", &data->focused_story_id);
  xdr->Field("last_focus_timestamp", &data->last_focus_change_timestamp);
}

constexpr XdrFilterType<fuchsia::modular::FocusInfo> XdrFocusInfo[] = {
    XdrFocusInfo_v2,
    XdrFocusInfo_v1,
    nullptr,
};

}  // namespace

FocusHandler::FocusHandler(fidl::StringPtr device_id,
                           LedgerClient* const ledger_client,
                           LedgerPageId page_id)
    : PageClient("FocusHandler", ledger_client, std::move(page_id),
                 kFocusKeyPrefix),
      device_id_(device_id) {}

FocusHandler::~FocusHandler() = default;

void FocusHandler::AddProviderBinding(
    fidl::InterfaceRequest<fuchsia::modular::FocusProvider> request) {
  provider_bindings_.AddBinding(this, std::move(request));
}

void FocusHandler::AddControllerBinding(
    fidl::InterfaceRequest<fuchsia::modular::FocusController> request) {
  controller_bindings_.AddBinding(this, std::move(request));
}

// |fuchsia::modular::FocusProvider|
void FocusHandler::Query(QueryCallback callback) {
  operation_queue_.Add(new ReadAllDataCall<fuchsia::modular::FocusInfo>(
      page(), kFocusKeyPrefix, XdrFocusInfo,
      [callback](std::vector<fuchsia::modular::FocusInfo> infos) {
        callback(std::move(infos));
      }));
}

// |fuchsia::modular::FocusProvider|
void FocusHandler::Watch(
    fidl::InterfaceHandle<fuchsia::modular::FocusWatcher> watcher) {
  change_watchers_.push_back(watcher.Bind());
}

// |fuchsia::modular::FocusProvider|
void FocusHandler::Request(fidl::StringPtr story_id) {
  for (const auto& watcher : request_watchers_) {
    watcher->OnFocusRequest(story_id);
  }
}

// |fuchsia::modular::FocusController|
void FocusHandler::Set(fidl::StringPtr story_id) {
  fuchsia::modular::FocusInfoPtr data = fuchsia::modular::FocusInfo::New();
  data->device_id = device_id_;
  data->focused_story_id = story_id;
  data->last_focus_change_timestamp = time(nullptr);

  operation_queue_.Add(new WriteDataCall<fuchsia::modular::FocusInfo>(
      page(), MakeFocusKey(device_id_), XdrFocusInfo, std::move(data), [] {}));
}

// |fuchsia::modular::FocusController|
void FocusHandler::WatchRequest(
    fidl::InterfaceHandle<fuchsia::modular::FocusRequestWatcher> watcher) {
  request_watchers_.push_back(watcher.Bind());
}

// |PageClient|
void FocusHandler::OnPageChange(const std::string& /*key*/,
                                const std::string& value) {
  auto focus_info = fuchsia::modular::FocusInfo::New();
  if (!XdrRead(value, &focus_info, XdrFocusInfo)) {
    return;
  }

  for (const auto& watcher : change_watchers_) {
    watcher->OnFocusChange(CloneOptional(focus_info));
  }
}

VisibleStoriesHandler::VisibleStoriesHandler() {}

VisibleStoriesHandler::~VisibleStoriesHandler() = default;

void VisibleStoriesHandler::AddProviderBinding(
    fidl::InterfaceRequest<fuchsia::modular::VisibleStoriesProvider> request) {
  provider_bindings_.AddBinding(this, std::move(request));
}

void VisibleStoriesHandler::AddControllerBinding(
    fidl::InterfaceRequest<fuchsia::modular::VisibleStoriesController>
        request) {
  controller_bindings_.AddBinding(this, std::move(request));
}

void VisibleStoriesHandler::Query(QueryCallback callback) {
  callback(visible_stories_);
}

void VisibleStoriesHandler::Watch(
    fidl::InterfaceHandle<fuchsia::modular::VisibleStoriesWatcher> watcher) {
  change_watchers_.push_back(watcher.Bind());
}

void VisibleStoriesHandler::Set(fidl::VectorPtr<std::string> story_ids) {
  visible_stories_ = std::move(story_ids);
  for (const auto& watcher : change_watchers_) {
    watcher->OnVisibleStoriesChange(visible_stories_.Clone());
  }
}

}  // namespace modular
