// Copyright 2016 The Chromium 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 "media/blink/watch_time_reporter.h"

#include "base/power_monitor/power_monitor.h"
#include "media/base/watch_time_keys.h"

namespace media {

// The minimum width and height of videos to report watch time metrics for.
constexpr gfx::Size kMinimumVideoSize = gfx::Size(200, 140);

static bool IsOnBatteryPower() {
  if (base::PowerMonitor* pm = base::PowerMonitor::Get())
    return pm->IsOnBatteryPower();
  return false;
}

// Helper function for managing property changes. If the watch time timer is
// running it sets the pending value otherwise it sets the current value and
// then returns true if the component needs finalize.
enum class PropertyAction { kNoActionRequired, kFinalizeRequired };
template <typename T>
PropertyAction HandlePropertyChange(T new_value,
                                    bool is_timer_running,
                                    WatchTimeComponent<T>* component) {
  if (!component)
    return PropertyAction::kNoActionRequired;

  if (is_timer_running)
    component->SetPendingValue(new_value);
  else
    component->SetCurrentValue(new_value);

  return component->NeedsFinalize() ? PropertyAction::kFinalizeRequired
                                    : PropertyAction::kNoActionRequired;
}

WatchTimeReporter::WatchTimeReporter(
    mojom::PlaybackPropertiesPtr properties,
    const gfx::Size& initial_natural_size,
    GetMediaTimeCB get_media_time_cb,
    mojom::MediaMetricsProvider* provider,
    scoped_refptr<base::SequencedTaskRunner> task_runner,
    const base::TickClock* tick_clock)
    : WatchTimeReporter(std::move(properties),
                        false /* is_background */,
                        false /* is_muted */,
                        initial_natural_size,
                        std::move(get_media_time_cb),
                        provider,
                        task_runner,
                        tick_clock) {}

WatchTimeReporter::WatchTimeReporter(
    mojom::PlaybackPropertiesPtr properties,
    bool is_background,
    bool is_muted,
    const gfx::Size& initial_natural_size,
    GetMediaTimeCB get_media_time_cb,
    mojom::MediaMetricsProvider* provider,
    scoped_refptr<base::SequencedTaskRunner> task_runner,
    const base::TickClock* tick_clock)
    : properties_(std::move(properties)),
      is_background_(is_background),
      is_muted_(is_muted),
      initial_natural_size_(initial_natural_size),
      get_media_time_cb_(std::move(get_media_time_cb)),
      reporting_timer_(tick_clock) {
  DCHECK(get_media_time_cb_);
  DCHECK(properties_->has_audio || properties_->has_video);
  DCHECK_EQ(is_background, properties_->is_background);

  // The background reporter receives play/pause events instead of visibility
  // changes, so it must always be visible to function correctly.
  if (is_background_)
    DCHECK(is_visible_);

  // The muted reporter receives play/pause events instead of volume changes, so
  // its volume must always be audible to function correctly.
  if (is_muted_)
    DCHECK_EQ(volume_, 1.0);

  if (base::PowerMonitor* pm = base::PowerMonitor::Get())
    pm->AddObserver(this);

  provider->AcquireWatchTimeRecorder(properties_->Clone(),
                                     mojo::MakeRequest(&recorder_));

  reporting_timer_.SetTaskRunner(task_runner);

  base_component_ = CreateBaseComponent();
  power_component_ = CreatePowerComponent();
  if (!is_background_) {
    controls_component_ = CreateControlsComponent();
    if (properties_->has_video)
      display_type_component_ = CreateDisplayTypeComponent();
  }

  // If this is a sub-reporter or we shouldn't report watch time, we're done. We
  // don't support muted+background reporting currently.
  if (is_background_ || is_muted_ || !ShouldReportWatchTime())
    return;

  // Background watch time is reported by creating an background only watch time
  // reporter which receives play when hidden and pause when shown. This avoids
  // unnecessary complexity inside the UpdateWatchTime() for handling this case.
  auto prop_copy = properties_.Clone();
  prop_copy->is_background = true;
  background_reporter_.reset(new WatchTimeReporter(
      std::move(prop_copy), true /* is_background */, false /* is_muted */,
      initial_natural_size_, get_media_time_cb_, provider, task_runner,
      tick_clock));

  // Muted watch time is only reported for audio+video playback.
  if (!properties_->has_video || !properties_->has_audio)
    return;

  // Similar to the above, muted watch time is reported by creating a muted only
  // watch time reporter which receives play when muted and pause when audible.
  prop_copy = properties_.Clone();
  prop_copy->is_muted = true;
  muted_reporter_.reset(new WatchTimeReporter(
      std::move(prop_copy), false /* is_background */, true /* is_muted */,
      initial_natural_size_, get_media_time_cb_, provider, task_runner,
      tick_clock));
}

WatchTimeReporter::~WatchTimeReporter() {
  background_reporter_.reset();
  muted_reporter_.reset();

  // This is our last chance, so finalize now if there's anything remaining.
  in_shutdown_ = true;
  MaybeFinalizeWatchTime(FinalizeTime::IMMEDIATELY);
  if (base::PowerMonitor* pm = base::PowerMonitor::Get())
    pm->RemoveObserver(this);
}

void WatchTimeReporter::OnPlaying() {
  if (background_reporter_ && !is_visible_)
    background_reporter_->OnPlaying();
  if (muted_reporter_ && !volume_)
    muted_reporter_->OnPlaying();

  is_playing_ = true;
  is_seeking_ = false;
  MaybeStartReportingTimer(get_media_time_cb_.Run());
}

void WatchTimeReporter::OnPaused() {
  if (background_reporter_)
    background_reporter_->OnPaused();
  if (muted_reporter_)
    muted_reporter_->OnPaused();

  is_playing_ = false;
  MaybeFinalizeWatchTime(FinalizeTime::ON_NEXT_UPDATE);
}

void WatchTimeReporter::OnSeeking() {
  if (background_reporter_)
    background_reporter_->OnSeeking();
  if (muted_reporter_)
    muted_reporter_->OnSeeking();

  // Seek is a special case that does not have hysteresis, when this is called
  // the seek is imminent, so finalize the previous playback immediately.
  is_seeking_ = true;
  MaybeFinalizeWatchTime(FinalizeTime::IMMEDIATELY);
}

void WatchTimeReporter::OnVolumeChange(double volume) {
  if (background_reporter_)
    background_reporter_->OnVolumeChange(volume);

  // The muted reporter should never receive volume changes.
  DCHECK(!is_muted_);

  const double old_volume = volume_;
  volume_ = volume;

  // We're only interesting in transitions in and out of the muted state.
  if (!old_volume && volume) {
    if (muted_reporter_)
      muted_reporter_->OnPaused();
    MaybeStartReportingTimer(get_media_time_cb_.Run());
  } else if (old_volume && !volume_) {
    if (muted_reporter_ && is_playing_)
      muted_reporter_->OnPlaying();
    MaybeFinalizeWatchTime(FinalizeTime::ON_NEXT_UPDATE);
  }
}

void WatchTimeReporter::OnShown() {
  // The background reporter should never receive visibility changes.
  DCHECK(!is_background_);

  if (background_reporter_)
    background_reporter_->OnPaused();
  if (muted_reporter_)
    muted_reporter_->OnShown();

  is_visible_ = true;
  MaybeStartReportingTimer(get_media_time_cb_.Run());
}

void WatchTimeReporter::OnHidden() {
  // The background reporter should never receive visibility changes.
  DCHECK(!is_background_);

  if (background_reporter_ && is_playing_)
    background_reporter_->OnPlaying();
  if (muted_reporter_)
    muted_reporter_->OnHidden();

  is_visible_ = false;
  MaybeFinalizeWatchTime(FinalizeTime::ON_NEXT_UPDATE);
}

void WatchTimeReporter::OnError(PipelineStatus status) {
  // Since playback should have stopped by this point, go ahead and send the
  // error directly instead of on the next timer tick. It won't be recorded
  // until finalization anyways.
  recorder_->OnError(status);
  if (background_reporter_)
    background_reporter_->OnError(status);
  if (muted_reporter_)
    muted_reporter_->OnError(status);
}

void WatchTimeReporter::OnUnderflow() {
  if (background_reporter_)
    background_reporter_->OnUnderflow();
  if (muted_reporter_)
    muted_reporter_->OnUnderflow();

  if (!reporting_timer_.IsRunning())
    return;

  // In the event of a pending finalize, we don't want to count underflow events
  // that occurred after the finalize time. Yet if the finalize is canceled we
  // want to ensure they are all recorded.
  pending_underflow_events_.push_back(get_media_time_cb_.Run());
}

void WatchTimeReporter::OnNativeControlsEnabled() {
  OnNativeControlsChanged(true);
}

void WatchTimeReporter::OnNativeControlsDisabled() {
  OnNativeControlsChanged(false);
}

void WatchTimeReporter::OnDisplayTypeInline() {
  OnDisplayTypeChanged(DisplayType::kInline);
}

void WatchTimeReporter::OnDisplayTypeFullscreen() {
  OnDisplayTypeChanged(DisplayType::kFullscreen);
}

void WatchTimeReporter::OnDisplayTypePictureInPicture() {
  OnDisplayTypeChanged(DisplayType::kPictureInPicture);
}

void WatchTimeReporter::UpdateSecondaryProperties(
    mojom::SecondaryPlaybackPropertiesPtr secondary_properties) {
  // Flush any unrecorded watch time before updating the secondary properties to
  // ensure the UKM record is finalized with up-to-date watch time information.
  if (reporting_timer_.IsRunning())
    RecordWatchTime();

  recorder_->UpdateSecondaryProperties(secondary_properties.Clone());
  if (background_reporter_) {
    background_reporter_->UpdateSecondaryProperties(
        secondary_properties.Clone());
  }
  if (muted_reporter_)
    muted_reporter_->UpdateSecondaryProperties(std::move(secondary_properties));
}

void WatchTimeReporter::SetAutoplayInitiated(bool autoplay_initiated) {
  recorder_->SetAutoplayInitiated(autoplay_initiated);
  if (background_reporter_)
    background_reporter_->SetAutoplayInitiated(autoplay_initiated);
  if (muted_reporter_)
    muted_reporter_->SetAutoplayInitiated(autoplay_initiated);
}

void WatchTimeReporter::OnDurationChanged(base::TimeDelta duration) {
  recorder_->OnDurationChanged(duration);
  if (background_reporter_)
    background_reporter_->OnDurationChanged(duration);
  if (muted_reporter_)
    muted_reporter_->OnDurationChanged(duration);
}

void WatchTimeReporter::OnPowerStateChange(bool on_battery_power) {
  if (HandlePropertyChange<bool>(on_battery_power, reporting_timer_.IsRunning(),
                                 power_component_.get()) ==
      PropertyAction::kFinalizeRequired) {
    RestartTimerForHysteresis();
  }
}

void WatchTimeReporter::OnNativeControlsChanged(bool has_native_controls) {
  if (muted_reporter_)
    muted_reporter_->OnNativeControlsChanged(has_native_controls);

  if (HandlePropertyChange<bool>(
          has_native_controls, reporting_timer_.IsRunning(),
          controls_component_.get()) == PropertyAction::kFinalizeRequired) {
    RestartTimerForHysteresis();
  }
}

void WatchTimeReporter::OnDisplayTypeChanged(DisplayType display_type) {
  if (muted_reporter_)
    muted_reporter_->OnDisplayTypeChanged(display_type);

  if (HandlePropertyChange<DisplayType>(
          display_type, reporting_timer_.IsRunning(),
          display_type_component_.get()) == PropertyAction::kFinalizeRequired) {
    RestartTimerForHysteresis();
  }
}

bool WatchTimeReporter::ShouldReportWatchTime() const {
  // Report listen time or watch time for videos of sufficient size.
  return properties_->has_video
             ? (initial_natural_size_.height() >= kMinimumVideoSize.height() &&
                initial_natural_size_.width() >= kMinimumVideoSize.width())
             : properties_->has_audio;
}

bool WatchTimeReporter::ShouldReportingTimerRun() const {
  // TODO(dalecurtis): We should only consider |volume_| when there is actually
  // an audio track; requires updating lots of tests to fix.
  return ShouldReportWatchTime() && is_playing_ && volume_ && is_visible_ &&
         !in_shutdown_ && !is_seeking_;
}

void WatchTimeReporter::MaybeStartReportingTimer(
    base::TimeDelta start_timestamp) {
  DCHECK_NE(start_timestamp, kInfiniteDuration);
  DCHECK_GE(start_timestamp, base::TimeDelta());

  // Don't start the timer if our state indicates we shouldn't; this check is
  // important since the various event handlers do not have to care about the
  // state of other events.
  const bool should_start = ShouldReportingTimerRun();
  if (reporting_timer_.IsRunning()) {
    base_component_->SetPendingValue(should_start);
    return;
  }

  base_component_->SetCurrentValue(should_start);
  if (!should_start)
    return;

  underflow_count_ = 0;
  pending_underflow_events_.clear();

  base_component_->OnReportingStarted(start_timestamp);
  power_component_->OnReportingStarted(start_timestamp);

  if (controls_component_)
    controls_component_->OnReportingStarted(start_timestamp);
  if (display_type_component_)
    display_type_component_->OnReportingStarted(start_timestamp);

  reporting_timer_.Start(FROM_HERE, reporting_interval_, this,
                         &WatchTimeReporter::UpdateWatchTime);
}

void WatchTimeReporter::MaybeFinalizeWatchTime(FinalizeTime finalize_time) {
  if (HandlePropertyChange<bool>(
          ShouldReportingTimerRun(), reporting_timer_.IsRunning(),
          base_component_.get()) == PropertyAction::kNoActionRequired) {
    return;
  }

  if (finalize_time == FinalizeTime::IMMEDIATELY) {
    UpdateWatchTime();
    return;
  }

  // Always restart the timer when finalizing, so that we allow for the full
  // length of |kReportingInterval| to elapse for hysteresis purposes.
  DCHECK_EQ(finalize_time, FinalizeTime::ON_NEXT_UPDATE);
  RestartTimerForHysteresis();
}

void WatchTimeReporter::RestartTimerForHysteresis() {
  // Restart the reporting timer so the full hysteresis is afforded.
  DCHECK(reporting_timer_.IsRunning());
  reporting_timer_.Start(FROM_HERE, reporting_interval_, this,
                         &WatchTimeReporter::UpdateWatchTime);
}

void WatchTimeReporter::RecordWatchTime() {
  // If we're finalizing, use the media time at time of finalization.
  const base::TimeDelta current_timestamp =
      base_component_->NeedsFinalize() ? base_component_->end_timestamp()
                                       : get_media_time_cb_.Run();

  // Pass along any underflow events which have occurred since the last report.
  if (!pending_underflow_events_.empty()) {
    if (!base_component_->NeedsFinalize()) {
      // The maximum value here per period is ~5 events, so int cast is okay.
      underflow_count_ += static_cast<int>(pending_underflow_events_.size());
    } else {
      // Only count underflow events prior to finalize.
      for (auto& ts : pending_underflow_events_) {
        if (ts <= base_component_->end_timestamp())
          underflow_count_++;
      }
    }

    recorder_->UpdateUnderflowCount(underflow_count_);
    pending_underflow_events_.clear();
  }

  // Record watch time for all components.
  base_component_->RecordWatchTime(current_timestamp);
  power_component_->RecordWatchTime(current_timestamp);
  if (display_type_component_)
    display_type_component_->RecordWatchTime(current_timestamp);
  if (controls_component_)
    controls_component_->RecordWatchTime(current_timestamp);
}

void WatchTimeReporter::UpdateWatchTime() {
  DCHECK(ShouldReportWatchTime());

  // First record watch time.
  RecordWatchTime();

  // Second, process any pending finalize events.
  std::vector<WatchTimeKey> keys_to_finalize;
  if (power_component_->NeedsFinalize())
    power_component_->Finalize(&keys_to_finalize);
  if (display_type_component_ && display_type_component_->NeedsFinalize())
    display_type_component_->Finalize(&keys_to_finalize);
  if (controls_component_ && controls_component_->NeedsFinalize())
    controls_component_->Finalize(&keys_to_finalize);

  // Then finalize the base component.
  if (!base_component_->NeedsFinalize()) {
    if (!keys_to_finalize.empty())
      recorder_->FinalizeWatchTime(keys_to_finalize);
    return;
  }

  // Always send finalize, even if we don't currently have any data, it's
  // harmless to send since nothing will be logged if we've already finalized.
  base_component_->Finalize(&keys_to_finalize);
  recorder_->FinalizeWatchTime({});

  // Stop the timer if this is supposed to be our last tick.
  underflow_count_ = 0;
  reporting_timer_.Stop();
}

#define NORMAL_KEY(key)                                                     \
  ((properties_->has_video && properties_->has_audio)                       \
       ? (is_background_ ? WatchTimeKey::kAudioVideoBackground##key         \
                         : (is_muted_ ? WatchTimeKey::kAudioVideoMuted##key \
                                      : WatchTimeKey::kAudioVideo##key))    \
       : properties_->has_video                                             \
             ? (is_background_ ? WatchTimeKey::kVideoBackground##key        \
                               : WatchTimeKey::kVideo##key)                 \
             : (is_background_ ? WatchTimeKey::kAudioBackground##key        \
                               : WatchTimeKey::kAudio##key))

std::unique_ptr<WatchTimeComponent<bool>>
WatchTimeReporter::CreateBaseComponent() {
  std::vector<WatchTimeKey> keys_to_finalize;
  keys_to_finalize.emplace_back(NORMAL_KEY(All));
  if (properties_->is_mse)
    keys_to_finalize.emplace_back(NORMAL_KEY(Mse));
  else
    keys_to_finalize.emplace_back(NORMAL_KEY(Src));

  if (properties_->is_eme)
    keys_to_finalize.emplace_back(NORMAL_KEY(Eme));

  if (properties_->is_embedded_media_experience)
    keys_to_finalize.emplace_back(NORMAL_KEY(EmbeddedExperience));

  return std::make_unique<WatchTimeComponent<bool>>(
      false, std::move(keys_to_finalize),
      WatchTimeComponent<bool>::ValueToKeyCB(), get_media_time_cb_,
      recorder_.get());
}

std::unique_ptr<WatchTimeComponent<bool>>
WatchTimeReporter::CreatePowerComponent() {
  std::vector<WatchTimeKey> keys_to_finalize{NORMAL_KEY(Battery),
                                             NORMAL_KEY(Ac)};

  return std::make_unique<WatchTimeComponent<bool>>(
      IsOnBatteryPower(), std::move(keys_to_finalize),
      base::BindRepeating(&WatchTimeReporter::GetPowerKey,
                          base::Unretained(this)),
      get_media_time_cb_, recorder_.get());
}

WatchTimeKey WatchTimeReporter::GetPowerKey(bool is_on_battery_power) {
  return is_on_battery_power ? NORMAL_KEY(Battery) : NORMAL_KEY(Ac);
}
#undef NORMAL_KEY

#define FOREGROUND_KEY(key)                                 \
  ((properties_->has_video && properties_->has_audio)       \
       ? (is_muted_ ? WatchTimeKey::kAudioVideoMuted##key   \
                    : WatchTimeKey::kAudioVideo##key)       \
       : properties_->has_audio ? WatchTimeKey::kAudio##key \
                                : WatchTimeKey::kVideo##key)

std::unique_ptr<WatchTimeComponent<bool>>
WatchTimeReporter::CreateControlsComponent() {
  DCHECK(!is_background_);

  std::vector<WatchTimeKey> keys_to_finalize{FOREGROUND_KEY(NativeControlsOn),
                                             FOREGROUND_KEY(NativeControlsOff)};

  return std::make_unique<WatchTimeComponent<bool>>(
      false, std::move(keys_to_finalize),
      base::BindRepeating(&WatchTimeReporter::GetControlsKey,
                          base::Unretained(this)),
      get_media_time_cb_, recorder_.get());
}

WatchTimeKey WatchTimeReporter::GetControlsKey(bool has_native_controls) {
  return has_native_controls ? FOREGROUND_KEY(NativeControlsOn)
                             : FOREGROUND_KEY(NativeControlsOff);
}

#undef FOREGROUND_KEY

#define DISPLAY_TYPE_KEY(key)                                                \
  (properties_->has_audio ? (is_muted_ ? WatchTimeKey::kAudioVideoMuted##key \
                                       : WatchTimeKey::kAudioVideo##key)     \
                          : WatchTimeKey::kVideo##key)

std::unique_ptr<WatchTimeComponent<WatchTimeReporter::DisplayType>>
WatchTimeReporter::CreateDisplayTypeComponent() {
  DCHECK(properties_->has_video);
  DCHECK(!is_background_);

  std::vector<WatchTimeKey> keys_to_finalize{
      DISPLAY_TYPE_KEY(DisplayInline), DISPLAY_TYPE_KEY(DisplayFullscreen),
      DISPLAY_TYPE_KEY(DisplayPictureInPicture)};

  return std::make_unique<WatchTimeComponent<DisplayType>>(
      DisplayType::kInline, std::move(keys_to_finalize),
      base::BindRepeating(&WatchTimeReporter::GetDisplayTypeKey,
                          base::Unretained(this)),
      get_media_time_cb_, recorder_.get());
}

WatchTimeKey WatchTimeReporter::GetDisplayTypeKey(DisplayType display_type) {
  switch (display_type) {
    case DisplayType::kInline:
      return DISPLAY_TYPE_KEY(DisplayInline);
    case DisplayType::kFullscreen:
      return DISPLAY_TYPE_KEY(DisplayFullscreen);
    case DisplayType::kPictureInPicture:
      return DISPLAY_TYPE_KEY(DisplayPictureInPicture);
  }
}

#undef DISPLAY_TYPE_KEY

}  // namespace media
