// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/renderer/tts_dispatcher.h"

#include <stddef.h>

#include "base/strings/utf_string_conversions.h"
#include "chrome/common/tts_messages.h"
#include "chrome/common/tts_utterance_request.h"
#include "content/public/renderer/render_thread.h"
#include "third_party/blink/public/platform/web_speech_synthesis_utterance.h"
#include "third_party/blink/public/platform/web_speech_synthesis_voice.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_vector.h"

using content::RenderThread;
using blink::WebSpeechSynthesizerClient;
using blink::WebSpeechSynthesisUtterance;
using blink::WebSpeechSynthesisVoice;
using blink::WebString;
using blink::WebVector;

int TtsDispatcher::next_utterance_id_ = 1;

TtsDispatcher::TtsDispatcher(WebSpeechSynthesizerClient* client)
    : synthesizer_client_(client) {
  RenderThread::Get()->AddObserver(this);
}

TtsDispatcher::~TtsDispatcher() {
  RenderThread::Get()->RemoveObserver(this);
}

bool TtsDispatcher::OnControlMessageReceived(const IPC::Message& message) {
  IPC_BEGIN_MESSAGE_MAP(TtsDispatcher, message)
    IPC_MESSAGE_HANDLER(TtsMsg_SetVoiceList, OnSetVoiceList)
    IPC_MESSAGE_HANDLER(TtsMsg_DidStartSpeaking, OnDidStartSpeaking)
    IPC_MESSAGE_HANDLER(TtsMsg_DidFinishSpeaking, OnDidFinishSpeaking)
    IPC_MESSAGE_HANDLER(TtsMsg_DidPauseSpeaking, OnDidPauseSpeaking)
    IPC_MESSAGE_HANDLER(TtsMsg_DidResumeSpeaking, OnDidResumeSpeaking)
    IPC_MESSAGE_HANDLER(TtsMsg_WordBoundary, OnWordBoundary)
    IPC_MESSAGE_HANDLER(TtsMsg_SentenceBoundary, OnSentenceBoundary)
    IPC_MESSAGE_HANDLER(TtsMsg_MarkerEvent, OnMarkerEvent)
    IPC_MESSAGE_HANDLER(TtsMsg_WasInterrupted, OnWasInterrupted)
    IPC_MESSAGE_HANDLER(TtsMsg_WasCancelled, OnWasCancelled)
    IPC_MESSAGE_HANDLER(TtsMsg_SpeakingErrorOccurred, OnSpeakingErrorOccurred)
  IPC_END_MESSAGE_MAP()

  // Always return false because there may be multiple TtsDispatchers
  // and we want them all to have a chance to handle this message.
  return false;
}

void TtsDispatcher::UpdateVoiceList() {
  RenderThread::Get()->Send(new TtsHostMsg_InitializeVoiceList());
}

void TtsDispatcher::Speak(const WebSpeechSynthesisUtterance& web_utterance) {
  int id = next_utterance_id_++;

  utterance_id_map_[id] = web_utterance;

  TtsUtteranceRequest utterance;
  utterance.id = id;
  utterance.text = web_utterance.GetText().Utf8();
  utterance.lang = web_utterance.Lang().Utf8();
  utterance.voice = web_utterance.Voice().Utf8();
  utterance.volume = web_utterance.Volume();
  utterance.rate = web_utterance.Rate();
  utterance.pitch = web_utterance.Pitch();
  RenderThread::Get()->Send(new TtsHostMsg_Speak(utterance));
}

void TtsDispatcher::Pause() {
  RenderThread::Get()->Send(new TtsHostMsg_Pause());
}

void TtsDispatcher::Resume() {
  RenderThread::Get()->Send(new TtsHostMsg_Resume());
}

void TtsDispatcher::Cancel() {
  RenderThread::Get()->Send(new TtsHostMsg_Cancel());
}

WebSpeechSynthesisUtterance TtsDispatcher::FindUtterance(int utterance_id) {
  const auto iter = utterance_id_map_.find(utterance_id);
  if (iter == utterance_id_map_.end())
    return WebSpeechSynthesisUtterance();
  return iter->second;
}

void TtsDispatcher::OnSetVoiceList(const std::vector<TtsVoice>& voices) {
  WebVector<WebSpeechSynthesisVoice> out_voices(voices.size());
  for (size_t i = 0; i < voices.size(); ++i) {
    out_voices[i] = WebSpeechSynthesisVoice();
    out_voices[i].SetVoiceURI(WebString::FromUTF8(voices[i].voice_uri));
    out_voices[i].SetName(WebString::FromUTF8(voices[i].name));
    out_voices[i].SetLanguage(WebString::FromUTF8(voices[i].lang));
    out_voices[i].SetIsLocalService(voices[i].local_service);
    out_voices[i].SetIsDefault(voices[i].is_default);
  }
  synthesizer_client_->SetVoiceList(out_voices);
}

void TtsDispatcher::OnDidStartSpeaking(int utterance_id) {
  if (utterance_id_map_.find(utterance_id) == utterance_id_map_.end())
    return;

  WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
  if (utterance.IsNull())
    return;

  synthesizer_client_->DidStartSpeaking(utterance);
}

void TtsDispatcher::OnDidFinishSpeaking(int utterance_id) {
  WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
  if (utterance.IsNull())
    return;

  synthesizer_client_->DidFinishSpeaking(utterance);
  utterance_id_map_.erase(utterance_id);
}

void TtsDispatcher::OnDidPauseSpeaking(int utterance_id) {
  WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
  if (utterance.IsNull())
    return;

  synthesizer_client_->DidPauseSpeaking(utterance);
}

void TtsDispatcher::OnDidResumeSpeaking(int utterance_id) {
  WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
  if (utterance.IsNull())
    return;

  synthesizer_client_->DidResumeSpeaking(utterance);
}

void TtsDispatcher::OnWordBoundary(int utterance_id,
                                   int char_index,
                                   int char_length) {
  CHECK(char_index >= 0);

  WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
  if (utterance.IsNull())
    return;

  // charLength is unsigned in the web speech API, so -1 cannot be used as a
  // sentinel value. Use 0 instead to match web standards.
  char_length = (char_length < 0) ? 0 : char_length;
  synthesizer_client_->WordBoundaryEventOccurred(
      utterance, static_cast<unsigned>(char_index),
      static_cast<unsigned>(char_length));
}

void TtsDispatcher::OnSentenceBoundary(int utterance_id,
                                       int char_index,
                                       int char_length) {
  CHECK(char_index >= 0);

  WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
  if (utterance.IsNull())
    return;

  // charLength is unsigned in the web speech API, so -1 cannot be used as a
  // sentinel value. Use 0 instead to match web standards.
  char_length = (char_length < 0) ? 0 : char_length;
  synthesizer_client_->SentenceBoundaryEventOccurred(
      utterance, static_cast<unsigned>(char_index),
      static_cast<unsigned>(char_length));
}

void TtsDispatcher::OnMarkerEvent(int utterance_id, int char_index) {
  // Not supported yet.
}

void TtsDispatcher::OnWasInterrupted(int utterance_id) {
  WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
  if (utterance.IsNull())
    return;

  // The web speech API doesn't support "interrupted".
  synthesizer_client_->DidFinishSpeaking(utterance);
  utterance_id_map_.erase(utterance_id);
}

void TtsDispatcher::OnWasCancelled(int utterance_id) {
  WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
  if (utterance.IsNull())
    return;

  // The web speech API doesn't support "cancelled".
  synthesizer_client_->DidFinishSpeaking(utterance);
  utterance_id_map_.erase(utterance_id);
}

void TtsDispatcher::OnSpeakingErrorOccurred(int utterance_id,
                                            const std::string& error_message) {
  WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
  if (utterance.IsNull())
    return;

  // The web speech API doesn't support an error message.
  synthesizer_client_->SpeakingErrorOccurred(utterance);
  utterance_id_map_.erase(utterance_id);
}
