// Copyright 2018 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 "garnet/bin/mediaplayer/test/mediaplayer_test_util_view.h"

#include <fcntl.h>
#include <hid/usages.h>
#include <zx/eventpair.h>
#include "garnet/bin/mediaplayer/graph/formatting.h"
#include "garnet/bin/mediaplayer/test/mediaplayer_test_util_params.h"
#include "lib/fidl/cpp/clone.h"
#include "lib/fidl/cpp/optional.h"
#include "lib/fsl/io/fd.h"
#include "lib/fxl/logging.h"
#include "lib/media/timeline/timeline.h"
#include "lib/media/timeline/type_converters.h"
#include "lib/url/gurl.h"

namespace media_player {
namespace test {

namespace {
constexpr uint32_t kVideoChildKey = 0u;

constexpr int32_t kDefaultWidth = 640;
constexpr int32_t kDefaultHeight = 100;

constexpr float kBackgroundElevation = 0.f;
constexpr float kVideoElevation = 1.0f;
constexpr float kProgressBarElevation = 1.0f;
constexpr float kProgressBarSliderElevation = 2.0f;

constexpr float kControlsGap = 12.0f;
constexpr float kControlsHeight = 36.0f;

// Determines whether the rectangle contains the point x,y.
bool Contains(const fuchsia::math::RectF& rect, float x, float y) {
  return rect.x <= x && rect.y <= y && rect.x + rect.width >= x &&
         rect.y + rect.height >= y;
}

int64_t rand_less_than(int64_t limit) {
  return (static_cast<int64_t>(std::rand()) * RAND_MAX + std::rand()) % limit;
}

}  // namespace

MediaPlayerTestUtilView::MediaPlayerTestUtilView(
    scenic::ViewContext view_context, fit::function<void(int)> quit_callback,
    const MediaPlayerTestUtilParams& params)
    : scenic::V1BaseView(std::move(view_context), "Media Player"),
      quit_callback_(std::move(quit_callback)),
      params_(params),
      background_node_(session()),
      progress_bar_node_(session()),
      progress_bar_slider_node_(session()) {
  FXL_DCHECK(quit_callback_);
  FXL_DCHECK(params_.is_valid());
  FXL_DCHECK(!params_.urls().empty());

  scenic::Material background_material(session());
  background_material.SetColor(0x00, 0x00, 0x00, 0xff);
  background_node_.SetMaterial(background_material);
  parent_node().AddChild(background_node_);

  scenic::Material progress_bar_material(session());
  progress_bar_material.SetColor(0x23, 0x23, 0x23, 0xff);
  progress_bar_node_.SetMaterial(progress_bar_material);
  parent_node().AddChild(progress_bar_node_);

  scenic::Material progress_bar_slider_material(session());
  progress_bar_slider_material.SetColor(0x00, 0x00, 0xff, 0xff);
  progress_bar_slider_node_.SetMaterial(progress_bar_slider_material);
  parent_node().AddChild(progress_bar_slider_node_);

  // We start with a non-zero size so we get a progress bar regardless of
  // whether we get video.
  video_size_.width = 0;
  video_size_.height = 0;
  pixel_aspect_ratio_.width = 1;
  pixel_aspect_ratio_.height = 1;

  // Create a player from all that stuff.
  player_ = startup_context()
                ->ConnectToEnvironmentService<fuchsia::mediaplayer::Player>();

  // Create the video view.
  zx::eventpair view_owner_token, view_token;
  if (zx::eventpair::create(0u, &view_owner_token, &view_token) != ZX_OK)
    FXL_NOTREACHED() << "failed to create tokens.";
  player_->CreateView2(std::move(view_token));

  zx::eventpair video_host_import_token;
  video_host_node_.reset(new scenic::EntityNode(session()));
  video_host_node_->ExportAsRequest(&video_host_import_token);
  parent_node().AddChild(*video_host_node_);
  GetViewContainer()->AddChild2(kVideoChildKey, std::move(view_owner_token),
                                std::move(video_host_import_token));

  commands_.Init(player_.get());

  player_.events().OnStatusChanged =
      [this](fuchsia::mediaplayer::PlayerStatus status) {
        HandleStatusChanged(status);
      };

  // Seed the random number generator.
  std::srand(std::time(nullptr));

  if (params_.experiment()) {
    RunExperiment();
  } else if (params_.test_seek()) {
    TestSeek();
  } else {
    // Get the player primed now.
    commands_.SetUrl(params_.urls().front());
    commands_.Pause();
    commands_.WaitForViewReady();

    if (params_.auto_play()) {
      commands_.Play();
    }

    ScheduleNextUrl();
  }

  commands_.Execute();
}

void MediaPlayerTestUtilView::RunExperiment() {
  // Add experimental code here.
  // In general, no implementation for this method should be submitted.
}

void MediaPlayerTestUtilView::TestSeek() {
  commands_.SetUrl(params_.urls().front());
  commands_.WaitForViewReady();

  // Need to load content before deciding where to seek.
  commands_.WaitForContentLoaded();

  commands_.Invoke([this]() { ContinueTestSeek(); });
}

void MediaPlayerTestUtilView::ContinueTestSeek() {
  if (duration_ns_ == 0) {
    // We have no duration yet. Just start over at zero.
    commands_.Seek(0);
    commands_.Play();
    commands_.WaitForEndOfStream();
    commands_.Invoke([this]() { ContinueTestSeek(); });
    FXL_LOG(INFO) << "Seek interval: beginning to end";
    return;
  }

  // For the start position, generate a number in the range [0..duration_ns_]
  // with a 10% chance of being zero.
  int64_t seek_interval_start =
      rand_less_than(duration_ns_ + duration_ns_ / 10);
  if (seek_interval_start >= duration_ns_) {
    seek_interval_start = 0;
  }

  // For the end position, choose a position between start and 10% past the
  // duration. If this value is greater than the duration, the interval
  // effectively ends at the end of the file.
  int64_t seek_interval_end =
      seek_interval_start +
      rand_less_than((duration_ns_ + duration_ns_ / 10) - seek_interval_start);

  commands_.Seek(seek_interval_start);
  commands_.Play();
  if (seek_interval_end >= duration_ns_) {
    FXL_LOG(INFO) << "Seek interval: " << AsNs(seek_interval_start)
                  << " to end";
    commands_.WaitForEndOfStream();
  } else {
    FXL_LOG(INFO) << "Seek interval: " << AsNs(seek_interval_start) << " to "
                  << AsNs(seek_interval_end);
    commands_.WaitForSeekCompletion();
    commands_.WaitForPosition(seek_interval_end);
  }

  commands_.Invoke([this]() { ContinueTestSeek(); });
}

void MediaPlayerTestUtilView::ScheduleNextUrl() {
  if (++next_url_index_ == params_.urls().size()) {
    if (!params_.loop()) {
      // No more files, not looping.
      return;
    }

    next_url_index_ = 0;
  }

  commands_.WaitForEndOfStream();

  if (params_.urls().size() > 1) {
    commands_.SetUrl(params_.urls()[next_url_index_]);
  } else {
    // Just one file...seek to the beginning.
    commands_.Seek(0);
  }

  commands_.Play();

  commands_.Invoke([this]() { ScheduleNextUrl(); });
}

MediaPlayerTestUtilView::~MediaPlayerTestUtilView() {}

bool MediaPlayerTestUtilView::OnInputEvent(
    fuchsia::ui::input::InputEvent event) {
  bool handled = false;
  if (event.is_pointer()) {
    const auto& pointer = event.pointer();
    if (pointer.phase == fuchsia::ui::input::PointerEventPhase::DOWN) {
      if (duration_ns_ != 0 && Contains(controls_rect_, pointer.x, pointer.y)) {
        // User poked the progress bar...seek.
        player_->Seek((pointer.x - controls_rect_.x) * duration_ns_ /
                      controls_rect_.width);
        if (state_ != State::kPlaying) {
          player_->Play();
        }
      } else {
        // User poked elsewhere.
        TogglePlayPause();
      }

      handled = true;
    }
  } else if (event.is_keyboard()) {
    auto& keyboard = event.keyboard();
    if (keyboard.phase == fuchsia::ui::input::KeyboardEventPhase::PRESSED) {
      switch (keyboard.hid_usage) {
        case HID_USAGE_KEY_SPACE:
          TogglePlayPause();
          handled = true;
          break;
        case HID_USAGE_KEY_Q:
          quit_callback_(0);
          handled = true;
          break;
        default:
          break;
      }
    }
  }

  return handled;
}

void MediaPlayerTestUtilView::OnPropertiesChanged(
    ::fuchsia::ui::viewsv1::ViewProperties old_properties) {
  Layout();
}

void MediaPlayerTestUtilView::Layout() {
  if (!has_logical_size())
    return;

  if (!scenic_ready_) {
    scenic_ready_ = true;
    commands_.NotifyViewReady();
  }

  // Make the background fill the space.
  scenic::Rectangle background_shape(session(), logical_size().width,
                                     logical_size().height);
  background_node_.SetShape(background_shape);
  background_node_.SetTranslation(logical_size().width * .5f,
                                  logical_size().height * .5f,
                                  kBackgroundElevation);

  // Compute maximum size of video content after reserving space
  // for decorations.
  fuchsia::math::SizeF max_content_size;
  max_content_size.width = logical_size().width;
  max_content_size.height =
      logical_size().height - kControlsHeight - kControlsGap;

  // Shrink video to fit if needed.
  uint32_t video_width =
      (video_size_.width == 0 ? kDefaultWidth : video_size_.width) *
      pixel_aspect_ratio_.width;
  uint32_t video_height =
      (video_size_.height == 0 ? kDefaultHeight : video_size_.height) *
      pixel_aspect_ratio_.height;

  if (max_content_size.width * video_height <
      max_content_size.height * video_width) {
    content_rect_.width = max_content_size.width;
    content_rect_.height = video_height * max_content_size.width / video_width;
  } else {
    content_rect_.width = video_width * max_content_size.height / video_height;
    content_rect_.height = max_content_size.height;
  }

  // Position the video.
  content_rect_.x = (logical_size().width - content_rect_.width) / 2.0f;
  content_rect_.y = (logical_size().height - content_rect_.height -
                     kControlsHeight - kControlsGap) /
                    2.0f;

  // Position the controls.
  controls_rect_.x = content_rect_.x;
  controls_rect_.y = content_rect_.y + content_rect_.height + kControlsGap;
  controls_rect_.width = content_rect_.width;
  controls_rect_.height = kControlsHeight;

  // Put the progress bar under the content.
  scenic::Rectangle progress_bar_shape(session(), controls_rect_.width,
                                       controls_rect_.height);
  progress_bar_node_.SetShape(progress_bar_shape);
  progress_bar_node_.SetTranslation(
      controls_rect_.x + controls_rect_.width * 0.5f,
      controls_rect_.y + controls_rect_.height * 0.5f, kProgressBarElevation);

  // Put the progress bar slider on top of the progress bar.
  scenic::Rectangle progress_bar_slider_shape(session(), controls_rect_.width,
                                              controls_rect_.height);
  progress_bar_slider_node_.SetShape(progress_bar_slider_shape);
  progress_bar_slider_node_.SetTranslation(
      controls_rect_.x + controls_rect_.width * 0.5f,
      controls_rect_.y + controls_rect_.height * 0.5f,
      kProgressBarSliderElevation);

  // Ask the view to fill the space.
  ::fuchsia::ui::viewsv1::ViewProperties view_properties;
  view_properties.view_layout = ::fuchsia::ui::viewsv1::ViewLayout::New();
  view_properties.view_layout->size.width = content_rect_.width;
  view_properties.view_layout->size.height = content_rect_.height;
  GetViewContainer()->SetChildProperties(
      kVideoChildKey, fidl::MakeOptional(std::move(view_properties)));

  InvalidateScene();
}

void MediaPlayerTestUtilView::OnSceneInvalidated(
    fuchsia::images::PresentationInfo presentation_info) {
  if (!has_physical_size())
    return;

  // Position the video.
  if (video_host_node_) {
    // TODO(dalesat): Fix this when SCN-1041 is fixed. Should be:
    // video_host_node_->SetTranslation(
    //     content_rect_.x + content_rect_.width * 0.5f,
    //     content_rect_.y + content_rect_.height * 0.5f, kVideoElevation);
    video_host_node_->SetTranslation(content_rect_.x, content_rect_.y,
                                     kVideoElevation);
  }

  float progress_bar_slider_width =
      controls_rect_.width * normalized_progress();
  scenic::Rectangle progress_bar_slider_shape(
      session(), progress_bar_slider_width, controls_rect_.height);
  progress_bar_slider_node_.SetShape(progress_bar_slider_shape);
  progress_bar_slider_node_.SetTranslation(
      controls_rect_.x + progress_bar_slider_width * 0.5f,
      controls_rect_.y + controls_rect_.height * 0.5f,
      kProgressBarSliderElevation);

  if (state_ == State::kPlaying) {
    InvalidateScene();
  }
}

void MediaPlayerTestUtilView::OnChildAttached(
    uint32_t child_key, ::fuchsia::ui::viewsv1::ViewInfo child_view_info) {
  FXL_DCHECK(child_key == kVideoChildKey);

  parent_node().AddChild(*video_host_node_);
  Layout();
}

void MediaPlayerTestUtilView::OnChildUnavailable(uint32_t child_key) {
  FXL_DCHECK(child_key == kVideoChildKey);
  FXL_LOG(ERROR) << "Video view died unexpectedly";

  video_host_node_->Detach();
  video_host_node_.reset();

  GetViewContainer()->RemoveChild2(child_key, zx::eventpair());
  Layout();
}

void MediaPlayerTestUtilView::HandleStatusChanged(
    const fuchsia::mediaplayer::PlayerStatus& status) {
  // Process status received from the player.
  if (status.timeline_function) {
    timeline_function_ =
        fxl::To<media::TimelineFunction>(*status.timeline_function);
    state_ = status.end_of_stream
                 ? State::kEnded
                 : (timeline_function_.subject_delta() == 0) ? State::kPaused
                                                             : State::kPlaying;
  } else {
    state_ = State::kPaused;
  }

  commands_.NotifyStatusChanged(status);

  if (status.problem) {
    if (!problem_shown_) {
      FXL_LOG(ERROR) << "PROBLEM: " << status.problem->type << ", "
                     << status.problem->details;
      problem_shown_ = true;
    }
  } else {
    problem_shown_ = false;
  }

  if (status.video_size && status.pixel_aspect_ratio &&
      (video_size_ != *status.video_size ||
       pixel_aspect_ratio_ != *status.pixel_aspect_ratio)) {
    video_size_ = *status.video_size;
    pixel_aspect_ratio_ = *status.pixel_aspect_ratio;
    Layout();
  }

  duration_ns_ = status.duration_ns;
  metadata_ = fidl::Clone(status.metadata);

  InvalidateScene();
}

void MediaPlayerTestUtilView::TogglePlayPause() {
  switch (state_) {
    case State::kPaused:
      player_->Play();
      break;
    case State::kPlaying:
      player_->Pause();
      break;
    case State::kEnded:
      player_->Seek(0);
      player_->Play();
      break;
    default:
      break;
  }
}

int64_t MediaPlayerTestUtilView::progress_ns() const {
  if (duration_ns_ == 0) {
    return 0;
  }

  // Apply the timeline function to the current time.
  int64_t position = timeline_function_(media::Timeline::local_now());

  if (position < 0) {
    position = 0;
  }

  if (position > duration_ns_) {
    position = duration_ns_;
  }

  return position;
}

float MediaPlayerTestUtilView::normalized_progress() const {
  if (duration_ns_ == 0) {
    return 0.0f;
  }

  return progress_ns() / static_cast<float>(duration_ns_);
}

}  // namespace test
}  // namespace media_player
