/*
 * 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 "cobalt/speech/microphone_manager.h"

#include "cobalt/speech/speech_recognition_error.h"

namespace cobalt {
namespace speech {

namespace {
// Size of an audio buffer.
const int kBufferSizeInBytes = 8 * 1024;
// The frequency which we read the data from devices.
const float kMicReadRateInHertz = 60.0f;
}  // namespace

MicrophoneManager::MicrophoneManager(
    const DataReceivedCallback& data_received,
    const CompletionCallback& completion, const ErrorCallback& error,
    const MicrophoneCreator& microphone_creator)
    : data_received_callback_(data_received),
      completion_callback_(completion),
      error_callback_(error),
      microphone_creator_(microphone_creator),
      state_(kStopped),
      thread_("microphone_thread") {
  thread_.StartWithOptions(base::Thread::Options(MessageLoop::TYPE_IO, 0));
}

MicrophoneManager::~MicrophoneManager() {
  thread_.message_loop()->PostTask(
      FROM_HERE,
      base::Bind(&MicrophoneManager::DestroyInternal, base::Unretained(this)));
}

void MicrophoneManager::Open() {
  thread_.message_loop()->PostTask(
      FROM_HERE,
      base::Bind(&MicrophoneManager::OpenInternal, base::Unretained(this)));
}

void MicrophoneManager::Close() {
  thread_.message_loop()->PostTask(
      FROM_HERE,
      base::Bind(&MicrophoneManager::CloseInternal, base::Unretained(this)));
}

bool MicrophoneManager::CreateIfNecessary() {
  DCHECK(thread_.message_loop_proxy()->BelongsToCurrentThread());

  if (microphone_) {
    return true;
  }

  microphone_ = microphone_creator_.Run(kBufferSizeInBytes);
  if (microphone_ && microphone_->IsValid()) {
    state_ = kStopped;
    return true;
  } else {
    DLOG(WARNING) << "Microphone creation failed.";
    microphone_.reset();
    state_ = kError;
    error_callback_.Run(new SpeechRecognitionError(
        SpeechRecognitionError::kAudioCapture, "No microphone available."));
    return false;
  }
}

void MicrophoneManager::OpenInternal() {
  DCHECK(thread_.message_loop_proxy()->BelongsToCurrentThread());

  // Try to create a valid microphone if necessary.
  if (state_ == kStarted || !CreateIfNecessary()) {
    return;
  }

  DCHECK(microphone_);
  if (!microphone_->Open()) {
    state_ = kError;
    error_callback_.Run(new SpeechRecognitionError(
        SpeechRecognitionError::kAborted, "Microphone open failed."));
    return;
  }

  poll_mic_events_timer_.emplace();
  // Setup a timer to poll for input events.
  poll_mic_events_timer_->Start(
      FROM_HERE, base::TimeDelta::FromMicroseconds(static_cast<int64>(
                     base::Time::kMicrosecondsPerSecond / kMicReadRateInHertz)),
      this, &MicrophoneManager::Read);
  state_ = kStarted;
}

void MicrophoneManager::CloseInternal() {
  DCHECK(thread_.message_loop_proxy()->BelongsToCurrentThread());

  if (state_ == kStopped) {
    return;
  }

  if (poll_mic_events_timer_) {
    poll_mic_events_timer_->Stop();
  }

  if (microphone_) {
    if (!microphone_->Close()) {
      state_ = kError;
      error_callback_.Run(new SpeechRecognitionError(
          SpeechRecognitionError::kAborted, "Microphone close failed."));
      return;
    }
    completion_callback_.Run();
    state_ = kStopped;
  }
}

void MicrophoneManager::Read() {
  DCHECK(thread_.message_loop_proxy()->BelongsToCurrentThread());

  DCHECK(state_ == kStarted);
  DCHECK(microphone_);
  DCHECK(microphone_->MinMicrophoneReadInBytes() <= kBufferSizeInBytes);

  int16_t samples[kBufferSizeInBytes / sizeof(int16_t)];
  int read_bytes =
      microphone_->Read(reinterpret_cast<char*>(samples), kBufferSizeInBytes);
  // If |read_bytes| is zero, nothing should happen.
  if (read_bytes > 0 && read_bytes % sizeof(int16_t) == 0) {
    size_t frames = read_bytes / sizeof(int16_t);
    scoped_ptr<ShellAudioBus> output_audio_bus(new ShellAudioBus(
        1, frames, ShellAudioBus::kInt16, ShellAudioBus::kInterleaved));
    output_audio_bus->Assign(ShellAudioBus(1, frames, samples));
    data_received_callback_.Run(output_audio_bus.Pass());
  } else if (read_bytes != 0) {
    state_ = kError;
    error_callback_.Run(new SpeechRecognitionError(
        SpeechRecognitionError::kAborted, "Microphone read failed."));
    poll_mic_events_timer_->Stop();
  }
}

void MicrophoneManager::DestroyInternal() {
  DCHECK(thread_.message_loop_proxy()->BelongsToCurrentThread());

  microphone_.reset();
  state_ = kStopped;
  poll_mic_events_timer_ = base::nullopt;
}

}  // namespace speech
}  // namespace cobalt
