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

#include "cobalt/dom/dom_exception.h"
#include "cobalt/dom/testing/mock_event_listener.h"
#include "cobalt/media_capture/media_recorder_options.h"
#include "cobalt/media_stream/media_stream.h"
#include "cobalt/media_stream/media_stream_audio_source.h"
#include "cobalt/media_stream/media_stream_audio_track.h"
#include "cobalt/media_stream/testing/mock_media_stream_audio_track.h"
#include "cobalt/script/testing/fake_script_value.h"
#include "cobalt/script/testing/mock_exception_state.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::_;
using ::testing::Eq;
using ::testing::Pointee;
using ::testing::Property;
using ::testing::SaveArg;
using ::testing::StrictMock;
using cobalt::dom::EventListener;
using cobalt::dom::testing::MockEventListener;
using cobalt::script::testing::MockExceptionState;
using cobalt::script::testing::FakeScriptValue;

namespace cobalt {
namespace media_stream {

class FakeMediaStreamAudioSource : public MediaStreamAudioSource {
 public:
  MOCK_METHOD0(EnsureSourceIsStarted, bool());
  MOCK_METHOD0(EnsureSourceIsStopped, void());

  void DeliverDataToTracks(
      const MediaStreamAudioTrack::ShellAudioBus& audio_bus,
      base::TimeTicks reference_time) {
    MediaStreamAudioSource::DeliverDataToTracks(audio_bus, reference_time);
  }

  void SetFormat(const media_stream::AudioParameters& params) {
    MediaStreamAudioSource::SetFormat(params);
  }
};

}  // namespace media_stream

namespace media_capture {

class MediaRecorderTest : public ::testing::Test {
 protected:
  MediaRecorderTest() {
    auto audio_track = make_scoped_refptr(
        new StrictMock<media_stream::MockMediaStreamAudioTrack>());
    media_stream::MediaStream::TrackSequences sequences;
    sequences.push_back(audio_track);
    audio_track->Start(base::Bind(&base::DoNothing));
    auto stream = make_scoped_refptr(new media_stream::MediaStream(sequences));
    media_source_ = new StrictMock<media_stream::FakeMediaStreamAudioSource>();
    EXPECT_CALL(*media_source_, EnsureSourceIsStarted());
    EXPECT_CALL(*media_source_, EnsureSourceIsStopped());
    media_source_->ConnectToTrack(audio_track);
    media_recorder_ =
        new MediaRecorder(nullptr, stream, MediaRecorderOptions());
  }

 protected:
  scoped_refptr<media_capture::MediaRecorder> media_recorder_;
  scoped_refptr<StrictMock<media_stream::FakeMediaStreamAudioSource>>
      media_source_;
  StrictMock<MockExceptionState> exception_state_;
};

TEST_F(MediaRecorderTest, CanSupportMimeType) {
  EXPECT_TRUE(MediaRecorder::IsTypeSupported("audio/L16"));
  EXPECT_TRUE(MediaRecorder::IsTypeSupported("audio/l16"));
  EXPECT_TRUE(
      MediaRecorder::IsTypeSupported("audio/l16;endianness=little-endian"));

  EXPECT_FALSE(MediaRecorder::IsTypeSupported("audio/pcm"));
  EXPECT_FALSE(MediaRecorder::IsTypeSupported("audio/webm"));
  EXPECT_FALSE(MediaRecorder::IsTypeSupported("pcm"));
  EXPECT_FALSE(MediaRecorder::IsTypeSupported("L16"));
  EXPECT_FALSE(MediaRecorder::IsTypeSupported("L16"));
}

TEST_F(MediaRecorderTest, StartStopStartStop) {
  media_recorder_->Start(&exception_state_);
  media_recorder_->Stop(&exception_state_);
  media_recorder_->Start(&exception_state_);
  media_recorder_->Stop(&exception_state_);
}

TEST_F(MediaRecorderTest, ExceptionOnStartingTwiceWithoutStop) {
  scoped_refptr<script::ScriptException> exception;

  EXPECT_CALL(exception_state_, SetException(_))
      .WillOnce(SaveArg<0>(&exception));

  media_recorder_->Start(&exception_state_);
  media_recorder_->Start(&exception_state_);

  ASSERT_TRUE(exception.get());
  dom::DOMException& dom_exception(
      *base::polymorphic_downcast<dom::DOMException*>(exception.get()));
  EXPECT_EQ(dom::DOMException::kInvalidStateErr, dom_exception.code());
  EXPECT_EQ(dom_exception.message(), "Recording state must be inactive.");
}

TEST_F(MediaRecorderTest, ExceptionOnStoppingTwiceWithoutStartingInBetween) {
  scoped_refptr<script::ScriptException> exception;

  EXPECT_CALL(exception_state_, SetException(_))
      .WillOnce(SaveArg<0>(&exception));

  media_recorder_->Start(&exception_state_);
  media_recorder_->Stop(&exception_state_);
  media_recorder_->Stop(&exception_state_);

  ASSERT_TRUE(exception.get());
  dom::DOMException& dom_exception(
      *base::polymorphic_downcast<dom::DOMException*>(exception.get()));
  EXPECT_EQ(dom::DOMException::kInvalidStateErr, dom_exception.code());
  EXPECT_EQ(dom_exception.message(), "Recording state must NOT be inactive.");
}

TEST_F(MediaRecorderTest, RecordL16Frames) {
  scoped_ptr<MockEventListener> listener = MockEventListener::Create();
  FakeScriptValue<EventListener> script_object(listener.get());
  media_recorder_->set_ondataavailable(script_object);
  EXPECT_CALL(*listener,
              HandleEvent(Eq(media_recorder_),
                          Pointee(Property(&dom::Event::type,
                                           base::Tokens::dataavailable())),
                          _));

  media_recorder_->Start(&exception_state_);

  const int kSampleRate = 16000;
  media_stream::AudioParameters params(1, kSampleRate, 16);
  media_recorder_->OnSetFormat(params);

  std::vector<int16> frames;
  frames.push_back(1);
  frames.push_back(-1);
  frames.push_back(-32768);
  frames.push_back(32767);
  frames.push_back(1000);
  frames.push_back(0);
  media_stream::MediaStreamAudioTrack::ShellAudioBus audio_bus(1, frames.size(),
                                                               frames.data());
  base::TimeTicks current_time = base::TimeTicks::Now();
  media_recorder_->OnData(audio_bus, current_time);
  current_time += base::TimeDelta::FromSecondsD(frames.size() / kSampleRate);
  media_recorder_->OnData(audio_bus, current_time);
  current_time += base::TimeDelta::FromSecondsD(frames.size() / kSampleRate);
  media_recorder_->OnData(audio_bus, current_time);

  media_recorder_->Stop(&exception_state_);
}

TEST_F(MediaRecorderTest, StartEvent) {
  scoped_ptr<MockEventListener> listener = MockEventListener::Create();
  FakeScriptValue<EventListener> script_object(listener.get());
  media_recorder_->set_onstart(script_object);
  EXPECT_CALL(
      *listener,
      HandleEvent(Eq(media_recorder_),
                  Pointee(Property(&dom::Event::type, base::Tokens::start())),
                  _));

  media_recorder_->Start(&exception_state_);
}

TEST_F(MediaRecorderTest, StopEvent) {
  scoped_ptr<MockEventListener> listener = MockEventListener::Create();
  FakeScriptValue<EventListener> script_object(listener.get());
  media_recorder_->Start(&exception_state_);
  media_recorder_->set_onstop(script_object);

  EXPECT_CALL(
      *listener,
      HandleEvent(Eq(media_recorder_),
                  Pointee(Property(&dom::Event::type, base::Tokens::stop())),
                  _));

  media_recorder_->Stop(&exception_state_);
}

TEST_F(MediaRecorderTest, ReleaseRecorderBeforeStoppingSource) {
  // This test ensures that media recorder can be destroyed
  // before the audio source is destroyed. It should not crash.
  media_recorder_ = nullptr;
}

}  // namespace media_capture
}  // namespace cobalt
