// Copyright 2019 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 "src/ui/bin/headless_root_presenter/activity_notifier.h"

#include <fuchsia/ui/activity/cpp/fidl.h>
#include <fuchsia/ui/input/cpp/fidl.h>
#include <lib/async/cpp/task.h>
#include <lib/async/cpp/time.h>
#include <lib/async/dispatcher.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/time.h>
#include <zircon/status.h>

#include <optional>

namespace root_presenter {

using fuchsia::ui::activity::DiscreteActivity;
using fuchsia::ui::activity::GenericActivity;
using fuchsia::ui::input::InputEvent;
using fuchsia::ui::input::MediaButtonsEvent;

ActivityNotifierImpl::ActivityNotifierImpl(async_dispatcher_t* dispatcher, zx::duration interval,
                                           sys::ComponentContext& context)
    : dispatcher_(dispatcher), interval_(interval) {
  activity_tracker_service_ = context.svc()->Connect<fuchsia::ui::activity::Tracker>();
  activity_tracker_service_.set_error_handler([this](zx_status_t error) {
    FX_LOGS(ERROR) << "Activity service died (" << zx_status_get_string(error) << "), no longer "
                   << "sending activity events.";
    activity_tracker_service_ = nullptr;
  });
}

void ActivityNotifierImpl::ReceiveInputEvent(const InputEvent& event) {
  if (auto activity = ActivityForInputEvent(event)) {
    MaybeEnqueueActivity(*std::move(activity));
  }
}

void ActivityNotifierImpl::ReceiveMediaButtonsEvent(const MediaButtonsEvent& event) {
  if (auto activity = ActivityForMediaButtonsEvent(event)) {
    MaybeEnqueueActivity(*std::move(activity));
  }
}

void ActivityNotifierImpl::MaybeEnqueueActivity(fuchsia::ui::activity::DiscreteActivity activity) {
  if (pending_activity_ || !activity_tracker_service_) {
    return;
  }
  pending_activity_ = std::move(activity);
  if (!notify_task_.is_pending()) {
    notify_task_.Post(dispatcher_);
  }
}

void ActivityNotifierImpl::NotifyForPendingActivity() {
  if (pending_activity_ && activity_tracker_service_) {
    auto now = async::Now(dispatcher_);
    activity_tracker_service_->ReportDiscreteActivity(
        std::move(*pending_activity_), now.get(), [this]() {
          notify_task_.PostDelayed(dispatcher_, interval_);
          pending_activity_ = std::nullopt;
        });
  } else {
    // |notify_task_| is intentionally not re-scheduled if no input was received recently. It
    // will be scheduled again on the next call to |ReceiveInput|.
    pending_activity_ = std::nullopt;
  }
}

std::optional<DiscreteActivity> ActivityNotifierImpl::ActivityForInputEvent(
    const InputEvent& event) {
  switch (event.Which()) {
    case InputEvent::Tag::kKeyboard:
    case InputEvent::Tag::kPointer: {
      GenericActivity generic;
      return DiscreteActivity::WithGeneric(std::move(generic));
    }
    case InputEvent::Tag::kFocus:
    default: {
      return std::nullopt;
    }
  }
}

std::optional<DiscreteActivity> ActivityNotifierImpl::ActivityForMediaButtonsEvent(
    const MediaButtonsEvent& event) {
  GenericActivity generic;
  return DiscreteActivity::WithGeneric(std::move(generic));
}

}  // namespace root_presenter
