// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "starboard/shared/starboard/player/player_internal.h"

#include "starboard/log.h"

using starboard::shared::starboard::player::InputBuffer;

namespace {

const SbTime kUpdateInterval = 5 * kSbTimeMillisecond;

SbMediaTime GetMediaTime(SbMediaTime media_pts,
                         SbTimeMonotonic media_pts_update_time) {
  SbTimeMonotonic elapsed = SbTimeGetMonotonicNow() - media_pts_update_time;
  return media_pts + elapsed * kSbMediaTimeSecond / kSbTimeSecond;
}

}  // namespace

SbPlayerPrivate::SbPlayerPrivate(
    SbMediaTime duration_pts,
    SbPlayerDeallocateSampleFunc sample_deallocate_func,
    SbPlayerDecoderStatusFunc decoder_status_func,
    SbPlayerStatusFunc player_status_func,
    void* context,
    starboard::scoped_ptr<PlayerWorker::Handler> player_worker_handler)
    : sample_deallocate_func_(sample_deallocate_func),
      context_(context),
      ticket_(SB_PLAYER_INITIAL_TICKET),
      duration_pts_(duration_pts),
      media_pts_(0),
      media_pts_update_time_(SbTimeGetMonotonicNow()),
      frame_width_(0),
      frame_height_(0),
      is_paused_(true),
      volume_(1.0),
      total_video_frames_(0),
      worker_(new PlayerWorker(this,
                               player_worker_handler.Pass(),
                               decoder_status_func,
                               player_status_func,
                               this,
                               kUpdateInterval,
                               context)) {}

void SbPlayerPrivate::Seek(SbMediaTime seek_to_pts, int ticket) {
  {
    starboard::ScopedLock lock(mutex_);
    SB_DCHECK(ticket_ != ticket);
    media_pts_ = seek_to_pts;
    media_pts_update_time_ = SbTimeGetMonotonicNow();
    ticket_ = ticket;
  }

  PlayerWorker::SeekEventData data = {seek_to_pts, ticket};
  worker_->EnqueueEvent(data);
}

void SbPlayerPrivate::WriteSample(
    SbMediaType sample_type,
    const void* sample_buffer,
    int sample_buffer_size,
    SbMediaTime sample_pts,
    const SbMediaVideoSampleInfo* video_sample_info,
    const SbDrmSampleInfo* sample_drm_info) {
  if (sample_type == kSbMediaTypeVideo) {
    ++total_video_frames_;
  }
  InputBuffer* input_buffer = new InputBuffer(
      sample_deallocate_func_, this, context_, sample_buffer,
      sample_buffer_size, sample_pts, video_sample_info, sample_drm_info);
  PlayerWorker::WriteSampleEventData data = {sample_type, input_buffer};
  worker_->EnqueueEvent(data);
}

void SbPlayerPrivate::WriteEndOfStream(SbMediaType stream_type) {
  PlayerWorker::WriteEndOfStreamEventData data = {stream_type};
  worker_->EnqueueEvent(data);
}

#if SB_IS(PLAYER_PUNCHED_OUT)
void SbPlayerPrivate::SetBounds(int x, int y, int width, int height) {
  PlayerWorker::SetBoundsEventData data = {x, y, width, height};
  worker_->EnqueueEvent(data);
  // TODO: Wait until a frame is rendered with the updated bounds.
}
#endif

void SbPlayerPrivate::GetInfo(SbPlayerInfo* out_player_info) {
  SB_DCHECK(out_player_info != NULL);

  starboard::ScopedLock lock(mutex_);
  out_player_info->duration_pts = duration_pts_;
  if (is_paused_) {
    out_player_info->current_media_pts = media_pts_;
  } else {
    out_player_info->current_media_pts =
        GetMediaTime(media_pts_, media_pts_update_time_);
  }
  out_player_info->frame_width = frame_width_;
  out_player_info->frame_height = frame_height_;
  out_player_info->is_paused = is_paused_;
  out_player_info->volume = volume_;
  out_player_info->total_video_frames = total_video_frames_;
  out_player_info->dropped_video_frames = 0;
  out_player_info->corrupted_video_frames = 0;
}

void SbPlayerPrivate::SetPause(bool pause) {
  PlayerWorker::SetPauseEventData data = {pause};
  worker_->EnqueueEvent(data);
}

void SbPlayerPrivate::SetVolume(double volume) {
  SB_NOTIMPLEMENTED();
}

void SbPlayerPrivate::UpdateMediaTime(SbMediaTime media_time, int ticket) {
  starboard::ScopedLock lock(mutex_);
  if (ticket_ != ticket) {
    return;
  }
  media_pts_ = media_time;
  media_pts_update_time_ = SbTimeGetMonotonicNow();
}
