// Copyright (c) 2012 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/browser/speech/speech_input_extension_api.h"

#include "base/bind.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/speech/speech_input_extension_manager.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"

using content::BrowserThread;

namespace {

const char kLanguageKey[] = "language";
const char kGrammarKey[] = "grammar";
const char kFilterProfanitiesKey[] = "filterProfanities";

const char kDefaultGrammar[] = "builtin:dictation";
const bool kDefaultFilterProfanities = true;

}  // anonymous namespace

SpeechInputAsyncFunction::SpeechInputAsyncFunction(
    int start_state,
    int transition_state,
    int end_state,
    int transition_notification)
    : start_state_(start_state),
      transition_state_(transition_state),
      end_state_(end_state),
      transition_notification_(transition_notification),
      expecting_transition_(false),
      failed_(false) {
  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_FAILED,
      content::Source<Profile>(profile()));
}

SpeechInputAsyncFunction::~SpeechInputAsyncFunction() {}

void SpeechInputAsyncFunction::Run() {
  if (failed_) {
    registrar_.RemoveAll();
    SendResponse(false);
    return;
  }

  SpeechInputExtensionManager::State state =
      SpeechInputExtensionManager::GetForProfile(profile())->state();

  // RunImpl should be always called once independently of the state we're in,
  // otherwise we might miss requestDenied error situations.
  if (!expecting_transition_) {
    SpeechInputExtensionManager::State state_before_call = state;

    // Register before RunImpl to ensure it's received if generated.
    if (state_before_call == start_state_) {
      registrar_.Add(this, transition_notification_,
          content::Source<Profile>(profile()));
      AddRef(); // Balanced in Observe().
    }

    if (!RunImpl()) {
      registrar_.RemoveAll();
      SendResponse(false);
      return;
    }

    // RunImpl should always return false and set the appropriate error code
    // when called in a state different to the start one.
    DCHECK_EQ(state_before_call, start_state_);

    state = SpeechInputExtensionManager::GetForProfile(profile())->state();
    DCHECK_EQ(state, transition_state_);
    expecting_transition_ = true;
  }

  if (state == transition_state_)
    return;

  DCHECK_EQ(state, end_state_);
  registrar_.RemoveAll();
  SendResponse(true);
}

void SpeechInputAsyncFunction::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  DCHECK_EQ(profile(), content::Source<Profile>(source).ptr());

  if (type == chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_FAILED) {
    SpeechInputExtensionManager::ExtensionError* error_details =
        content::Details<SpeechInputExtensionManager::ExtensionError>(
            details).ptr();
    if (error_details->extension_id_ != extension_id())
      return;

    error_ = error_details->error_;
    failed_ = true;
  } else {
    DCHECK_EQ(type, transition_notification_);
    if (*content::Details<std::string>(details).ptr() != extension_id())
      return;
    DCHECK(expecting_transition_);
  }

  Run();
  Release(); // Balanced in Run().
}

StartSpeechInputFunction::StartSpeechInputFunction()
    : SpeechInputAsyncFunction(SpeechInputExtensionManager::kIdle,
          SpeechInputExtensionManager::kStarting,
          SpeechInputExtensionManager::kRecording,
          chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_RECORDING_STARTED) {
}

bool StartSpeechInputFunction::RunImpl() {
  std::string language;
  std::string grammar = kDefaultGrammar;
  bool filter_profanities = kDefaultFilterProfanities;

  if (!args_->empty()) {
    DictionaryValue *options;
    if (!args_->GetDictionary(0, &options))
      return false;
    DCHECK(options);

    if (options->HasKey(kLanguageKey))
      options->GetString(kLanguageKey, &language);
    if (options->HasKey(kGrammarKey))
      options->GetString(kGrammarKey, &grammar);

    if (options->HasKey(kFilterProfanitiesKey)) {
      options->GetBoolean(kFilterProfanitiesKey,
          &filter_profanities);
    }
  }

  // Use the application locale if the language is empty or not provided.
  if (language.empty()) {
    language = g_browser_process->GetApplicationLocale();
    VLOG(1) << "Language not specified. Using application locale " << language;
  }

  return SpeechInputExtensionManager::GetForProfile(profile())->Start(
      extension_id(), language, grammar, filter_profanities, &error_);
}

StopSpeechInputFunction::StopSpeechInputFunction()
    : SpeechInputAsyncFunction(SpeechInputExtensionManager::kRecording,
          SpeechInputExtensionManager::kStopping,
          SpeechInputExtensionManager::kIdle,
          chrome::NOTIFICATION_EXTENSION_SPEECH_INPUT_RECORDING_STOPPED) {
}

bool StopSpeechInputFunction::RunImpl() {
  return SpeechInputExtensionManager::GetForProfile(
      profile())->Stop(extension_id(), &error_);
}

void IsRecordingSpeechInputFunction::SetIsRecordingResult(bool result) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  SetResult(Value::CreateBooleanValue(result));
  SendResponse(true);
}

void IsRecordingSpeechInputFunction::Run() {
  SpeechInputExtensionManager::GetForProfile(profile())->IsRecording(
      base::Bind(&IsRecordingSpeechInputFunction::SetIsRecordingResult, this));
}

bool IsRecordingSpeechInputFunction::RunImpl() {
  // The operation needs to be asynchronous because of thread requirements.
  // This method does nothing, but it needs to be implemented anyway.
  return true;
}
