// Copyright 2018 The Cobalt Authors. 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 "cobalt/media_capture/media_recorder.h"

#include <algorithm>
#include <cmath>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/message_loop.h"
#include "base/string_piece.h"
#include "base/string_util_starboard.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/base/tokens.h"
#include "cobalt/dom/blob.h"
#include "cobalt/dom/dom_exception.h"
#include "cobalt/dom/dom_settings.h"
#include "cobalt/media_capture/blob_event.h"
#include "cobalt/media_capture/encoders/flac_audio_encoder.h"
#include "cobalt/media_capture/encoders/linear16_audio_encoder.h"
#include "cobalt/media_stream/audio_parameters.h"
#include "cobalt/media_stream/media_stream_audio_track.h"
#include "cobalt/media_stream/media_stream_track.h"
#include "cobalt/media_stream/media_track_settings.h"
#include "cobalt/script/array_buffer.h"

namespace {

// See https://tools.ietf.org/html/rfc2586 for MIME type
const char kLinear16MimeType[] = "audio/L16";

const int32 kMinimumTimeSliceInMilliseconds = 1;
const int32 kSchedulingLatencyBufferMilliseconds = 20;

using cobalt::media_capture::encoders::AudioEncoder;
using cobalt::media_capture::encoders::FlacAudioEncoder;
using cobalt::media_capture::encoders::Linear16AudioEncoder;

// Returns the number of bytes needed to store |time_span| duration
// of audio that has a bitrate of |bits_per_second|.
int64 GetRecommendedBufferSizeInBytes(base::TimeDelta time_span,
                                      int64 bits_per_second) {
  DCHECK_GE(time_span, base::TimeDelta::FromSeconds(0));
  // Increase buffer slightly to account for the fact that scheduling our
  // tasks might be a little bit noisy.
  double buffer_window_span_seconds = time_span.InSecondsF();
  int64 recommended_buffer_size = static_cast<int64>(
      std::ceil(buffer_window_span_seconds * bits_per_second / 8));
  DCHECK_GT(recommended_buffer_size, 0);
  return recommended_buffer_size;
}

scoped_ptr<AudioEncoder> CreateAudioEncoder(
    base::StringPiece requested_mime_type) {
  if (Linear16AudioEncoder::IsLinear16MIMEType(requested_mime_type)) {
    return scoped_ptr<AudioEncoder>(new Linear16AudioEncoder());
  }
  if (FlacAudioEncoder::IsFlacMIMEType(requested_mime_type)) {
    return scoped_ptr<AudioEncoder>(new FlacAudioEncoder());
  }
  return scoped_ptr<AudioEncoder>(nullptr);
}

}  // namespace

namespace cobalt {
namespace media_capture {

void MediaRecorder::Start(int32 timeslice,
                          script::ExceptionState* exception_state) {
  DCHECK(stream_);
  DCHECK(thread_checker_.CalledOnValidThread());
  // Following the spec at
  // https://www.w3.org/TR/mediastream-recording/#mediarecorder-methods:

  // Step #1, not needed for Cobalt.

  // Step #2, done by Cobalt bindings.

  // Step #3
  if (recording_state_ != kRecordingStateInactive) {
    dom::DOMException::Raise(dom::DOMException::kInvalidStateErr,
                             "Recording state must be inactive.",
                             exception_state);
    return;
  }

  // Step #4, not needed for Cobalt.

  // Step 5.
  recording_state_ = kRecordingStateRecording;

  // Step 5.1.
  DispatchEvent(new dom::Event(base::Tokens::start()));

  // Steps 5.2-5.3, not needed for Cobalt.

  // Step #5.4, create a new Blob, and start collecting data.

  // If timeslice is not undefined, then once a minimum of timeslice
  // milliseconds of data have been collected, or some minimum time slice
  // imposed by the UA, whichever is greater, start gathering data into a new
  // Blob blob, and queue a task, using the DOM manipulation task source, that
  // fires a blob event named |dataavailable| at target.
  // Avoid rounding down to 0 milliseconds.
  int effective_time_slice_milliseconds =
      std::max(kMinimumTimeSliceInMilliseconds, timeslice);
  DCHECK_GT(effective_time_slice_milliseconds, 0);

  // This is the frequency we will callback to Javascript.
  timeslice_ =
      base::TimeDelta::FromMilliseconds(effective_time_slice_milliseconds);

  slice_origin_timestamp_ = base::TimeTicks::Now();

  script::Sequence<scoped_refptr<media_stream::MediaStreamTrack>>&
      audio_tracks = stream_->GetAudioTracks();

  size_t number_audio_tracks = audio_tracks.size();
  if (number_audio_tracks == 0) {
    LOG(WARNING) << "Audio Tracks are empty.";
    return;
  }
  LOG_IF(WARNING, number_audio_tracks > 1)
      << "Only recording the first audio track.";

  auto* first_audio_track =
      base::polymorphic_downcast<media_stream::MediaStreamAudioTrack*>(
          audio_tracks.begin()->get());
  DCHECK(first_audio_track);
  first_audio_track->AddSink(this);

  // Step #5.5 is implemented in |MediaRecorder::OnReadyStateChanged|.

  // Step #6, return undefined.
}

void MediaRecorder::Stop(script::ExceptionState* exception_state) {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (recording_state_ == kRecordingStateInactive) {
    dom::DOMException::Raise(dom::DOMException::kInvalidStateErr,
                             "Recording state must NOT be inactive.",
                             exception_state);
    return;
  }
  StopRecording();
}

void MediaRecorder::OnData(const ShellAudioBus& audio_bus,
                           base::TimeTicks reference_time) {
  // The source is always int16 data from the microphone.
  DCHECK_EQ(audio_bus.sample_type(), ShellAudioBus::kInt16);
  DCHECK_EQ(audio_bus.channels(), 1);
  DCHECK(audio_encoder_);
  audio_encoder_->Encode(audio_bus, reference_time);
}

void MediaRecorder::OnEncodedDataAvailable(const uint8* data, size_t data_size,
                                           base::TimeTicks timecode) {
  auto data_to_send =
      make_scoped_ptr(new std::vector<uint8>(data, data + data_size));
  javascript_message_loop_->PostTask(
      FROM_HERE, base::Bind(&MediaRecorder::CalculateLastInSliceAndWriteData,
                            weak_this_, base::Passed(&data_to_send), timecode));
}

void MediaRecorder::OnSetFormat(const media_stream::AudioParameters& params) {
  if (!audio_encoder_) {
    audio_encoder_ = CreateAudioEncoder(mime_type_);
    audio_encoder_->AddListener(this);
  }
  DCHECK(audio_encoder_);
  audio_encoder_->OnSetFormat(params);

  int64 bits_per_second =
      audio_encoder_->GetEstimatedOutputBitsPerSecond(params);
  if (bits_per_second <= 0) {
    return;
  }

  // Add some padding to the end of the buffer to account for jitter in
  // scheduling, etc.
  // This allows us to potentially avoid unnecessary resizing.
  base::TimeDelta recommended_time_slice =
      timeslice_ +
      base::TimeDelta::FromMilliseconds(kSchedulingLatencyBufferMilliseconds);
  int64 buffer_size_hint =
      GetRecommendedBufferSizeInBytes(recommended_time_slice, bits_per_second);
  buffer_.reserve(static_cast<size_t>(buffer_size_hint));
}

void MediaRecorder::OnReadyStateChanged(
    media_stream::MediaStreamTrack::ReadyState new_state) {
  // Step 5.5 from start(), defined at:
  // https://www.w3.org/TR/mediastream-recording/#mediarecorder-methods
  if (new_state == media_stream::MediaStreamTrack::kReadyStateEnded) {
    audio_encoder_->Finish(base::TimeTicks::Now());
    audio_encoder_.reset();
    StopRecording();
    stream_ = nullptr;
  }
}

MediaRecorder::MediaRecorder(
    script::EnvironmentSettings* settings,
    const scoped_refptr<media_stream::MediaStream>& stream,
    const MediaRecorderOptions& options,
    script::ExceptionState* exception_state)
    : settings_(settings),
      stream_(stream),
      javascript_message_loop_(base::MessageLoopProxy::current()),
      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
      weak_this_(weak_ptr_factory_.GetWeakPtr()) {
  DCHECK(settings);
  // Per W3C spec, the default value of this is platform-specific,
  // so Linear16 was chosen. Spec url:
  // https://www.w3.org/TR/mediastream-recording/#dom-mediarecorder-mediarecorder

  if (options.has_mime_type()) {
    if (!IsTypeSupported(options.mime_type())) {
      dom::DOMException::Raise(dom::DOMException::kNotSupportedErr,
                               exception_state);
      return;
    }
  }

  std::string desired_mime_type =
      options.has_mime_type() ? options.mime_type() : kLinear16MimeType;

  mime_type_ = desired_mime_type;
  DCHECK(IsTypeSupported(mime_type_));
  blob_options_.set_type(mime_type_);
}

MediaRecorder::MediaRecorder(
    script::EnvironmentSettings* settings,
    const scoped_refptr<media_stream::MediaStream>& stream,
    script::ExceptionState* exception_state)
    : MediaRecorder(settings, stream, MediaRecorderOptions(), exception_state) {
}

MediaRecorder::~MediaRecorder() {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (recording_state_ != kRecordingStateInactive) {
    UnsubscribeFromTrack();
  }
}

void MediaRecorder::StopRecording() {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(stream_);
  DCHECK_NE(recording_state_, kRecordingStateInactive);

  recording_state_ = kRecordingStateInactive;
  UnsubscribeFromTrack();

  scoped_ptr<std::vector<uint8>> empty;
  base::TimeTicks now = base::TimeTicks::Now();
  WriteData(empty.Pass(), true, now);

  timeslice_ = base::TimeDelta::FromSeconds(0);
  DispatchEvent(new dom::Event(base::Tokens::stop()));
}

void MediaRecorder::UnsubscribeFromTrack() {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(stream_);
  script::Sequence<scoped_refptr<media_stream::MediaStreamTrack>>&
      audio_tracks = stream_->GetAudioTracks();
  size_t number_audio_tracks = audio_tracks.size();
  if (number_audio_tracks == 0) {
    LOG(WARNING) << "Audio Tracks are empty.";
    return;
  }
  auto* first_audio_track =
      base::polymorphic_downcast<media_stream::MediaStreamAudioTrack*>(
          audio_tracks.begin()->get());
  DCHECK(first_audio_track);

  first_audio_track->RemoveSink(this);
}

void MediaRecorder::DoOnDataCallback(base::TimeTicks timecode) {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (buffer_.empty()) {
    DLOG(WARNING) << "No data was recorded.";
    return;
  }

  DCHECK_LE(buffer_.size(), kuint32max);

  auto array_buffer = script::ArrayBuffer::New(
      base::polymorphic_downcast<dom::DOMSettings*>(settings_)
          ->global_environment(),
      buffer_.data(), buffer_.size());

  auto blob =
      make_scoped_refptr(new dom::Blob(settings_, array_buffer, blob_options_));

  DispatchEvent(new media_capture::BlobEvent(base::Tokens::dataavailable(),
                                             blob, timecode.ToInternalValue()));
}

void MediaRecorder::WriteData(scoped_ptr<std::vector<uint8>> data,
                              bool last_in_slice, base::TimeTicks timecode) {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (data) {
    buffer_.insert(buffer_.end(), data->begin(), data->end());
  }

  if (!last_in_slice) {
    return;
  }

  DoOnDataCallback(timecode);
  buffer_.clear();
}

void MediaRecorder::CalculateLastInSliceAndWriteData(
    scoped_ptr<std::vector<uint8>> data, base::TimeTicks timecode) {
  DCHECK(thread_checker_.CalledOnValidThread());

  base::TimeTicks now = base::TimeTicks::Now();
  bool last_in_slice = now > slice_origin_timestamp_ + timeslice_;

  if (last_in_slice) {
    DLOG(INFO) << "Slice finished.";
    // The next slice's timestamp is now.
    slice_origin_timestamp_ = now;
  }
  WriteData(data.Pass(), last_in_slice, timecode);
}

bool MediaRecorder::IsTypeSupported(const base::StringPiece mime_type) {
  return Linear16AudioEncoder::IsLinear16MIMEType(mime_type) ||
         FlacAudioEncoder::IsFlacMIMEType(mime_type);
}

}  // namespace media_capture
}  // namespace cobalt
