// 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/bind.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
