// 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/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;
  base::Closure task = stopped_timer_.user_task();
  stopped_timer_.Stop();
  task.Run();
  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
