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

#ifndef COBALT_MEDIA_CAPTURE_MEDIA_RECORDER_H_
#define COBALT_MEDIA_CAPTURE_MEDIA_RECORDER_H_

#include <memory>
#include <string>
#include <vector>

#include "base/basictypes.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "cobalt/dom/blob_property_bag.h"
#include "cobalt/dom/event_target.h"
#include "cobalt/media_capture/encoders/audio_encoder.h"
#include "cobalt/media_capture/media_recorder_options.h"
#include "cobalt/media_capture/recording_state.h"
#include "cobalt/media_stream/audio_parameters.h"
#include "cobalt/media_stream/media_stream.h"
#include "cobalt/media_stream/media_stream_audio_sink.h"
#include "cobalt/script/environment_settings.h"
#include "cobalt/script/exception_state.h"
#include "cobalt/script/wrappable.h"

namespace cobalt {
namespace media_capture {

// This class represents a MediaRecorder, and implements the specification at:
// https://www.w3.org/TR/mediastream-recording/#mediarecorder-api
class MediaRecorder : public media_stream::MediaStreamAudioSink,
                      public encoders::AudioEncoder::Listener,
                      public dom::EventTarget {
 public:
  // Constructors.
  explicit MediaRecorder(script::EnvironmentSettings* settings,
                         const scoped_refptr<media_stream::MediaStream>& stream,
                         script::ExceptionState* exception_state);

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

  ~MediaRecorder() override;

  // Readonly attributes.
  const std::string& mime_type() const { return mime_type_; }

  // Functions
  static bool IsTypeSupported(const base::StringPiece mime_type);

  void Start(int32 timeslice, script::ExceptionState* exception_state);

  void Start(script::ExceptionState* exception_state) {
    Start(kint32max, exception_state);
  }

  void Stop(script::ExceptionState* exception_state);

  // EventHandlers.
  const EventListenerScriptValue* onstart() const {
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    return GetAttributeEventListener(base::Tokens::start());
  }

  void set_onstart(const EventListenerScriptValue& event_listener) {
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    SetAttributeEventListener(base::Tokens::start(), event_listener);
  }

  const EventListenerScriptValue* onstop() const {
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    return GetAttributeEventListener(base::Tokens::stop());
  }

  void set_onstop(const EventListenerScriptValue& event_listener) {
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    SetAttributeEventListener(base::Tokens::stop(), event_listener);
  }

  const EventListenerScriptValue* onerror() const {
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    return GetAttributeEventListener(base::Tokens::error());
  }

  void set_onerror(const EventListenerScriptValue& event_listener) {
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    SetAttributeEventListener(base::Tokens::error(), event_listener);
  }

  const EventListenerScriptValue* ondataavailable() const {
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    return GetAttributeEventListener(base::Tokens::dataavailable());
  }

  void set_ondataavailable(const EventListenerScriptValue& event_listener) {
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    SetAttributeEventListener(base::Tokens::dataavailable(), event_listener);
  }

  RecordingState state() { return recording_state_; }

  // MediaStreamAudioSink overrides.
  void OnData(const ShellAudioBus& audio_bus,
              base::TimeTicks reference_time) override;
  void OnSetFormat(const media_stream::AudioParameters& params) override;
  void OnReadyStateChanged(
      media_stream::MediaStreamTrack::ReadyState ready_state) override;

  DEFINE_WRAPPABLE_TYPE(MediaRecorder);

 private:
  MediaRecorder(const MediaRecorder&) = delete;
  MediaRecorder& operator=(const MediaRecorder&) = delete;

  void StopRecording();

  void UnsubscribeFromTrack();

  void DoOnDataCallback(base::TimeTicks timecode);
  void OnEncodedDataAvailable(const uint8* data, size_t data_size,
                              base::TimeTicks timecode) override;
  void WriteData(std::unique_ptr<std::vector<uint8>> data, bool last_in_slice,
                 base::TimeTicks timecode);
  void CalculateLastInSliceAndWriteData(
      std::unique_ptr<std::vector<uint8>> data, base::TimeTicks timecode);

  THREAD_CHECKER(thread_checker_);

  // |audio_encoder_| lives on the microphone thread.
  std::unique_ptr<encoders::AudioEncoder> audio_encoder_;
  std::vector<uint8> buffer_;

  RecordingState recording_state_ = kRecordingStateInactive;

  script::EnvironmentSettings* settings_;
  std::string mime_type_;
  dom::BlobPropertyBag blob_options_;
  scoped_refptr<media_stream::MediaStream> stream_;

  scoped_refptr<base::SingleThreadTaskRunner> javascript_message_loop_;
  base::TimeDelta timeslice_;
  // Only used to determine if |timeslice_| amount of time has
  // been passed since the slice was started.
  base::TimeTicks slice_origin_timestamp_;

  base::WeakPtrFactory<MediaRecorder> weak_ptr_factory_;
  base::WeakPtr<MediaRecorder> weak_this_;
};

}  // namespace media_capture
}  // namespace cobalt

#endif  // COBALT_MEDIA_CAPTURE_MEDIA_RECORDER_H_
