// Copyright 2016 The Chromium OS 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 "power_manager/common/activity_logger.h"

#include <cmath>

#include <base/check.h>
#include <base/format_macros.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>

#include "power_manager/common/clock.h"

namespace power_manager {
namespace {

// Default LogCallback for BaseActivityLogger.
void LogMessage(const std::string& message) {
  LOG(INFO) << message;
}

}  // namespace

void BaseActivityLogger::SetLogCallbackForTest(LogCallback callback) {
  log_callback_ = callback;
}

base::TimeDelta BaseActivityLogger::GetStoppedTimerDelayForTest() const {
  return stopped_timer_.IsRunning() ? stopped_timer_.GetCurrentDelay()
                                    : base::TimeDelta();
}

base::TimeDelta BaseActivityLogger::GetOngoingTimerDelayForTest() const {
  return ongoing_timer_.IsRunning() ? ongoing_timer_.GetCurrentDelay()
                                    : base::TimeDelta();
}

bool BaseActivityLogger::TriggerStoppedTimerForTest() {
  if (!stopped_timer_.IsRunning())
    return false;
  stopped_timer_.FireNow();
  return true;
}

bool BaseActivityLogger::TriggerOngoingTimerForTest() {
  if (!ongoing_timer_.IsRunning())
    return false;
  ongoing_timer_.user_task().Run();
  return true;
}

BaseActivityLogger::BaseActivityLogger(const std::string& activity_name,
                                       base::TimeDelta stopped_delay,
                                       base::TimeDelta ongoing_interval)
    : log_callback_(base::Bind(&LogMessage)),
      clock_(new Clock()),
      activity_name_(activity_name),
      stopped_delay_(stopped_delay),
      ongoing_interval_(ongoing_interval) {}

BaseActivityLogger::~BaseActivityLogger() {}

std::string BaseActivityLogger::GetDelaySuffix(
    base::TimeTicks timestamp) const {
  const base::TimeDelta delay = clock_->GetCurrentTime() - timestamp;
  return base::StringPrintf("%0.f sec ago", round(delay.InSecondsF()));
}

PeriodicActivityLogger::PeriodicActivityLogger(const std::string& activity_name,
                                               base::TimeDelta stopped_delay,
                                               base::TimeDelta ongoing_interval)
    : BaseActivityLogger(activity_name, stopped_delay, ongoing_interval) {
  // This class is pointless without a stopped delay -- the caller should just
  // log every report directly themselves.
  CHECK(!stopped_delay.is_zero());
  // An ongoing interval less than or equal to the stopped delay would result in
  // the ongoing message being logged constantly.
  CHECK(ongoing_interval_.is_zero() || ongoing_interval_ > stopped_delay_);
}

PeriodicActivityLogger::~PeriodicActivityLogger() {}

void PeriodicActivityLogger::OnActivityReported() {
  last_report_time_ = clock_->GetCurrentTime();

  // Only log that activity started if we weren't waiting to log that it had
  // stopped.
  if (!stopped_timer_.IsRunning())
    log_callback_.Run(activity_name_ + " reported");

  // Extend the "stopped" timeout and start the "ongoing" timer if it isn't
  // already running.
  stopped_timer_.Start(FROM_HERE, stopped_delay_, this,
                       &PeriodicActivityLogger::LogStopped);
  if (!ongoing_interval_.is_zero() && !ongoing_timer_.IsRunning()) {
    ongoing_timer_.Start(FROM_HERE, ongoing_interval_, this,
                         &PeriodicActivityLogger::LogOngoing);
  }
}

void PeriodicActivityLogger::LogStopped() {
  log_callback_.Run(activity_name_ + " stopped; last reported " +
                    GetDelaySuffix(last_report_time_));
  ongoing_timer_.Stop();
}

void PeriodicActivityLogger::LogOngoing() {
  log_callback_.Run(activity_name_ + " ongoing; last reported " +
                    GetDelaySuffix(last_report_time_));
}

StartStopActivityLogger::StartStopActivityLogger(
    const std::string& activity_name,
    base::TimeDelta stopped_delay,
    base::TimeDelta ongoing_interval)
    : BaseActivityLogger(activity_name, stopped_delay, ongoing_interval) {}

StartStopActivityLogger::~StartStopActivityLogger() {}

void StartStopActivityLogger::OnActivityStarted() {
  stopped_time_ = base::TimeTicks();

  // Only log that activity started if we weren't waiting to log that it had
  // stopped. Otherwise, just stop the timer -- it'll be started again when
  // activity stops.
  if (!stopped_timer_.IsRunning())
    log_callback_.Run(activity_name_ + " started");
  else
    stopped_timer_.Stop();

  if (!ongoing_interval_.is_zero() && !ongoing_timer_.IsRunning()) {
    ongoing_timer_.Start(FROM_HERE, ongoing_interval_, this,
                         &StartStopActivityLogger::LogOngoing);
  }
}

void StartStopActivityLogger::OnActivityStopped() {
  if (stopped_time_ != base::TimeTicks()) {
    LOG(WARNING) << "Ignoring activity-stopped notification for "
                 << "already-stopped " << activity_name_;
    return;
  }

  stopped_time_ = clock_->GetCurrentTime();
  ongoing_timer_.Stop();

  if (stopped_delay_.is_zero()) {
    LogStopped();
  } else {
    stopped_timer_.Start(FROM_HERE, stopped_delay_, this,
                         &StartStopActivityLogger::LogStopped);
  }
}

void StartStopActivityLogger::LogStopped() {
  log_callback_.Run(
      activity_name_ + " stopped" +
      (stopped_delay_.is_zero() ? "" : " " + GetDelaySuffix(stopped_time_)));
}

void StartStopActivityLogger::LogOngoing() {
  log_callback_.Run(activity_name_ + " ongoing");
}

OngoingStateActivityLogger::OngoingStateActivityLogger(
    base::TimeDelta ongoing_interval)
    : BaseActivityLogger(std::string(), base::TimeDelta(), ongoing_interval) {}

OngoingStateActivityLogger::~OngoingStateActivityLogger() {}

void OngoingStateActivityLogger::OnStateChanged(const std::string& state) {
  state_ = state;
  if (state_.empty()) {
    ongoing_timer_.Stop();
  } else if (!ongoing_timer_.IsRunning()) {
    ongoing_timer_.Start(FROM_HERE, ongoing_interval_, this,
                         &OngoingStateActivityLogger::LogOngoing);
  }
}

void OngoingStateActivityLogger::LogOngoing() {
  DCHECK(!state_.empty());
  log_callback_.Run(state_);
}

}  // namespace power_manager
