// 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/filter/filter_based_player_worker_handler.h"

#include "starboard/log.h"
#include "starboard/shared/starboard/application.h"
#include "starboard/shared/starboard/drm/drm_system_internal.h"
#include "starboard/shared/starboard/player/filter/audio_decoder_internal.h"
#include "starboard/shared/starboard/player/filter/video_decoder_internal.h"
#include "starboard/shared/starboard/player/input_buffer_internal.h"
#include "starboard/shared/starboard/player/video_frame_internal.h"
#include "starboard/time.h"

namespace starboard {
namespace shared {
namespace starboard {
namespace player {
namespace filter {

FilterBasedPlayerWorkerHandler::FilterBasedPlayerWorkerHandler(
    SbMediaVideoCodec video_codec,
    SbMediaAudioCodec audio_codec,
    SbDrmSystem drm_system,
    const SbMediaAudioHeader& audio_header)
    : player_worker_(NULL),
      player_(kSbPlayerInvalid),
      update_media_time_cb_(NULL),
      get_player_state_cb_(NULL),
      update_player_state_cb_(NULL),
      video_codec_(video_codec),
      audio_codec_(audio_codec),
      drm_system_(drm_system),
      audio_header_(audio_header),
      paused_(false) {}

void FilterBasedPlayerWorkerHandler::Setup(
    PlayerWorker* player_worker,
    SbPlayer player,
    UpdateMediaTimeCB update_media_time_cb,
    GetPlayerStateCB get_player_state_cb,
    UpdatePlayerStateCB update_player_state_cb) {
  // This function should only be called once.
  SB_DCHECK(player_worker_ == NULL);

  // All parameters has to be valid.
  SB_DCHECK(player_worker);
  SB_DCHECK(SbPlayerIsValid(player));
  SB_DCHECK(update_media_time_cb);
  SB_DCHECK(get_player_state_cb);
  SB_DCHECK(update_player_state_cb);

  player_worker_ = player_worker;
  player_ = player;
  update_media_time_cb_ = update_media_time_cb;
  get_player_state_cb_ = get_player_state_cb;
  update_player_state_cb_ = update_player_state_cb;
}

bool FilterBasedPlayerWorkerHandler::ProcessInitEvent() {
  scoped_ptr<AudioDecoder> audio_decoder(
      AudioDecoder::Create(audio_codec_, audio_header_));
  scoped_ptr<VideoDecoder> video_decoder(VideoDecoder::Create(video_codec_));

  if (!audio_decoder || !video_decoder) {
    return false;
  }

  audio_renderer_.reset(new AudioRenderer(audio_decoder.Pass(), audio_header_));
  video_renderer_.reset(new VideoRenderer(video_decoder.Pass()));
  if (audio_renderer_->is_valid() && video_renderer_->is_valid()) {
    return true;
  }

  audio_renderer_.reset(NULL);
  video_renderer_.reset(NULL);
  return false;
}

bool FilterBasedPlayerWorkerHandler::ProcessSeekEvent(
    const SeekEventData& data) {
  SbMediaTime seek_to_pts = data.seek_to_pts;
  if (seek_to_pts < 0) {
    SB_DLOG(ERROR) << "Try to seek to negative timestamp " << seek_to_pts;
    seek_to_pts = 0;
  }

  audio_renderer_->Pause();
  audio_renderer_->Seek(seek_to_pts);
  video_renderer_->Seek(seek_to_pts);
  return true;
}

bool FilterBasedPlayerWorkerHandler::ProcessWriteSampleEvent(
    const WriteSampleEventData& data,
    bool* written) {
  SB_DCHECK(written != NULL);

  *written = true;

  if (data.sample_type == kSbMediaTypeAudio) {
    if (audio_renderer_->IsEndOfStreamWritten()) {
      SB_LOG(WARNING) << "Try to write audio sample after EOS is reached";
    } else {
      if (!audio_renderer_->CanAcceptMoreData()) {
        *written = false;
        return true;
      }

      if (data.input_buffer->drm_info()) {
        if (!SbDrmSystemIsValid(drm_system_)) {
          return false;
        }
        if (drm_system_->Decrypt(data.input_buffer) ==
            SbDrmSystemPrivate::kRetry) {
          *written = false;
          return true;
        }
      }
      audio_renderer_->WriteSample(*data.input_buffer);
    }
  } else {
    SB_DCHECK(data.sample_type == kSbMediaTypeVideo);
    if (video_renderer_->IsEndOfStreamWritten()) {
      SB_LOG(WARNING) << "Try to write video sample after EOS is reached";
    } else {
      if (!video_renderer_->CanAcceptMoreData()) {
        *written = false;
        return true;
      }
      if (data.input_buffer->drm_info()) {
        if (!SbDrmSystemIsValid(drm_system_)) {
          return false;
        }
        if (drm_system_->Decrypt(data.input_buffer) ==
            SbDrmSystemPrivate::kRetry) {
          *written = false;
          return true;
        }
      }
      video_renderer_->WriteSample(*data.input_buffer);
    }
  }

  return true;
}

bool FilterBasedPlayerWorkerHandler::ProcessWriteEndOfStreamEvent(
    const WriteEndOfStreamEventData& data) {
  if (data.stream_type == kSbMediaTypeAudio) {
    if (audio_renderer_->IsEndOfStreamWritten()) {
      SB_LOG(WARNING) << "Try to write audio EOS after EOS is enqueued";
    } else {
      SB_LOG(INFO) << "Audio EOS enqueued";
      audio_renderer_->WriteEndOfStream();
    }
  } else {
    if (video_renderer_->IsEndOfStreamWritten()) {
      SB_LOG(WARNING) << "Try to write video EOS after EOS is enqueued";
    } else {
      SB_LOG(INFO) << "Video EOS enqueued";
      video_renderer_->WriteEndOfStream();
    }
  }

  return true;
}

bool FilterBasedPlayerWorkerHandler::ProcessSetPauseEvent(
    const SetPauseEventData& data) {
  paused_ = data.pause;

  if (data.pause) {
    audio_renderer_->Pause();
    SB_DLOG(INFO) << "Playback paused.";
  } else {
    audio_renderer_->Play();
    SB_DLOG(INFO) << "Playback started.";
  }

  return true;
}

bool FilterBasedPlayerWorkerHandler::ProcessUpdateEvent(
    const SetBoundsEventData& data) {
  if ((*player_worker_.*get_player_state_cb_)() == kSbPlayerStatePrerolling) {
    if (!audio_renderer_->IsSeekingInProgress() &&
        !video_renderer_->IsSeekingInProgress()) {
      (*player_worker_.*update_player_state_cb_)(kSbPlayerStatePresenting);
      if (!paused_) {
        audio_renderer_->Play();
      }
    }
  }

  if ((*player_worker_.*get_player_state_cb_)() == kSbPlayerStatePresenting) {
    if (audio_renderer_->IsEndOfStreamPlayed() &&
        video_renderer_->IsEndOfStreamPlayed()) {
      (*player_worker_.*update_player_state_cb_)(kSbPlayerStateEndOfStream);
    }

    scoped_refptr<VideoFrame> frame =
        video_renderer_->GetCurrentFrame(audio_renderer_->GetCurrentTime());

#if SB_IS(PLAYER_PUNCHED_OUT)
    shared::starboard::Application::Get()->HandleFrame(
        player_, frame, data.x, data.y, data.width, data.height);
#endif  // SB_IS(PLAYER_PUNCHED_OUT)

    (*player_worker_.*update_media_time_cb_)(audio_renderer_->GetCurrentTime());
  }

  return true;
}

void FilterBasedPlayerWorkerHandler::ProcessStopEvent() {
  audio_renderer_.reset();
  video_renderer_.reset();

#if SB_IS(PLAYER_PUNCHED_OUT)
  // Clear the video frame as we terminate.
  shared::starboard::Application::Get()->HandleFrame(
      player_, VideoFrame::CreateEOSFrame(), 0, 0, 0, 0);
#endif  // SB_IS(PLAYER_PUNCHED_OUT)
}

}  // namespace filter
}  // namespace player
}  // namespace starboard
}  // namespace shared
}  // namespace starboard
