// 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/sys/activity/activity_tracker_connection.h"

#include <fuchsia/ui/activity/cpp/fidl.h>
#include <lib/async/cpp/time.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/assert.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include <zircon/types.h>

namespace activity {

ActivityTrackerConnection::ActivityTrackerConnection(
    StateMachineDriver* state_machine_driver, async_dispatcher_t* dispatcher,
    fidl::InterfaceRequest<fuchsia::ui::activity::Tracker> request)
    : state_machine_driver_(state_machine_driver),
      dispatcher_(dispatcher),
      binding_(this, std::move(request), dispatcher) {}

ActivityTrackerConnection::~ActivityTrackerConnection() { Stop(); }

void ActivityTrackerConnection::Stop() {
  for (const auto& id : ongoing_activities_) {
    zx_status_t status =
        state_machine_driver_->EndOngoingActivity(id, async::Now(dispatcher_), []() {});
    // Assert here since failing silently may result in a leaked activity which would stall the
    // state machine from timing out.
    ZX_ASSERT_MSG(status == ZX_OK, "Failed to clean up activity %d: %s", id,
                  zx_status_get_string(status));
  }
  ongoing_activities_.clear();
}

void ActivityTrackerConnection::ReportDiscreteActivity(
    fuchsia::ui::activity::DiscreteActivity activity, zx_time_t time,
    ReportDiscreteActivityCallback callback) {
  if (time < last_activity_time_.get()) {
    FX_LOGS(ERROR) << "activity-service: Received out-of-order events from client.";
    binding_.Close(ZX_ERR_OUT_OF_RANGE);
    return;
  }
  last_activity_time_ = zx::time(time);
  zx_status_t status =
      state_machine_driver_->ReceiveDiscreteActivity(activity, zx::time(time), std::move(callback));
  if (status != ZX_OK) {
    if (status == ZX_ERR_OUT_OF_RANGE) {
      FX_LOGS(WARNING) << "activity-service: Ignoring activity due to stale timestamp (" << time
                       << ")";
    } else {
      FX_LOGS(ERROR) << "activity-service: Failed to receive activity: "
                     << zx_status_get_string(status);
      binding_.Close(status);
    }
  }
}

void ActivityTrackerConnection::StartOngoingActivity(
    OngoingActivityId id, fuchsia::ui::activity::OngoingActivity activity, zx_time_t time,
    StartOngoingActivityCallback callback) {
  if (ongoing_activities_.find(id) != ongoing_activities_.end()) {
    FX_LOGS(ERROR) << "activity-service: activity already started: " << id;
    binding_.Close(ZX_ERR_ALREADY_EXISTS);
    return;
  }
  if (time < last_activity_time_.get()) {
    FX_LOGS(ERROR) << "activity-service: Received out-of-order events from client.";
    binding_.Close(ZX_ERR_OUT_OF_RANGE);
    return;
  }
  last_activity_time_ = zx::time(time);
  zx_status_t status =
      state_machine_driver_->StartOngoingActivity(id, zx::time(time), std::move(callback));
  if (status == ZX_OK) {
    ongoing_activities_.insert(id);
  } else {
    if (status == ZX_ERR_OUT_OF_RANGE) {
      FX_LOGS(WARNING) << "activity-service: Ignoring activity due to stale timestamp (" << time
                       << ")";
      // Ignore the activity (don't close the binding or send an error to the client)
    } else {
      FX_LOGS(ERROR) << "activity-service: Failed to start activity: "
                     << zx_status_get_string(status);
      binding_.Close(status);
    }
  }
}

void ActivityTrackerConnection::EndOngoingActivity(OngoingActivityId id, zx_time_t time,
                                                   EndOngoingActivityCallback callback) {
  if (time < last_activity_time_.get()) {
    FX_LOGS(ERROR) << "activity-service: Received out-of-order events from client.";
    binding_.Close(ZX_ERR_OUT_OF_RANGE);
    return;
  }
  last_activity_time_ = zx::time(time);
  auto iter = ongoing_activities_.find(id);
  if (iter == ongoing_activities_.end()) {
    FX_LOGS(ERROR) << "activity-service: Invalid activity ID: " << id;
    binding_.Close(ZX_ERR_NOT_FOUND);
    return;
  }
  zx_status_t status =
      state_machine_driver_->EndOngoingActivity(id, zx::time(time), std::move(callback));
  if (status == ZX_OK) {
    ongoing_activities_.erase(iter);
  } else {
    if (status == ZX_ERR_OUT_OF_RANGE) {
      FX_LOGS(WARNING) << "activity-service: Ignoring activity due to stale timestamp (" << time
                       << ")";
      // Ignore the activity (don't close the binding or send an error to the client)
    } else {
      FX_LOGS(ERROR) << "activity-service: Failed to end activity: "
                     << zx_status_get_string(status);
      binding_.Close(status);
    }
  }
}

}  // namespace activity
