// 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](fidl::VectorPtr<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()
    : visible_stories_(fidl::VectorPtr<fidl::StringPtr>::New(0)) {}

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_.Clone());
}

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

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

}  // namespace modular
