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

#include "cobalt/speech/starboard_speech_recognizer.h"

#if defined(SB_USE_SB_SPEECH_RECOGNIZER)

#include "cobalt/base/tokens.h"
#include "cobalt/speech/speech_recognition_error.h"
#include "cobalt/speech/speech_recognition_event.h"
#include "starboard/common/log.h"
#include "starboard/types.h"

namespace cobalt {
namespace speech {

namespace {

using cobalt::speech::StarboardSpeechRecognizer;

void OnSpeechDetected(void* context, bool detected) {
  StarboardSpeechRecognizer* recognizer =
      static_cast<StarboardSpeechRecognizer*>(context);
  recognizer->OnRecognizerSpeechDetected(detected);
}

void OnError(void* context, SbSpeechRecognizerError error) {
  StarboardSpeechRecognizer* recognizer =
      static_cast<StarboardSpeechRecognizer*>(context);
  recognizer->OnRecognizerError(error);
}

void OnResults(void* context, SbSpeechResult* results, int results_size,
               bool is_final) {
  StarboardSpeechRecognizer* recognizer =
      static_cast<StarboardSpeechRecognizer*>(context);
  recognizer->OnRecognizerResults(results, results_size, is_final);
}

}  // namespace

StarboardSpeechRecognizer::StarboardSpeechRecognizer(
    const EventCallback& event_callback)
    : SpeechRecognizer(event_callback) {
  SbSpeechRecognizerHandler handler = {&OnSpeechDetected, &OnError, &OnResults,
                                       this};
  speech_recognizer_ = SbSpeechRecognizerCreate(&handler);

  if (!SbSpeechRecognizerIsValid(speech_recognizer_)) {
    scoped_refptr<dom::Event> error_event(new SpeechRecognitionError(
        kSpeechRecognitionErrorCodeServiceNotAllowed, ""));
    RunEventCallback(error_event);
  }
}

StarboardSpeechRecognizer::~StarboardSpeechRecognizer() {
  if (SbSpeechRecognizerIsValid(speech_recognizer_)) {
    SbSpeechRecognizerDestroy(speech_recognizer_);
  }
}

void StarboardSpeechRecognizer::Start(const SpeechRecognitionConfig& config) {
  SB_DCHECK(config.max_alternatives < INT_MAX);
  SbSpeechConfiguration configuration = {
      config.continuous, config.interim_results,
      static_cast<int>(config.max_alternatives)};
  if (SbSpeechRecognizerIsValid(speech_recognizer_)) {
    SbSpeechRecognizerStart(speech_recognizer_, &configuration);
  }
}

void StarboardSpeechRecognizer::Stop() {
  if (SbSpeechRecognizerIsValid(speech_recognizer_)) {
    SbSpeechRecognizerStop(speech_recognizer_);
  }
  // Clear the final results.
  final_results_.clear();
}

void StarboardSpeechRecognizer::OnRecognizerSpeechDetected(bool detected) {
  scoped_refptr<dom::Event> event(new dom::Event(
      detected ? base::Tokens::soundstart() : base::Tokens::soundend()));
  RunEventCallback(event);
}

void StarboardSpeechRecognizer::OnRecognizerError(
    SbSpeechRecognizerError error) {
  scoped_refptr<dom::Event> error_event;
  switch (error) {
    case kSbNoSpeechError:
      error_event =
          new SpeechRecognitionError(kSpeechRecognitionErrorCodeNoSpeech, "");
      break;
    case kSbAborted:
      error_event =
          new SpeechRecognitionError(kSpeechRecognitionErrorCodeAborted, "");
      break;
    case kSbAudioCaptureError:
      error_event = new SpeechRecognitionError(
          kSpeechRecognitionErrorCodeAudioCapture, "");
      break;
    case kSbNetworkError:
      error_event =
          new SpeechRecognitionError(kSpeechRecognitionErrorCodeNetwork, "");
      break;
    case kSbNotAllowed:
      error_event =
          new SpeechRecognitionError(kSpeechRecognitionErrorCodeNotAllowed, "");
      break;
    case kSbServiceNotAllowed:
      error_event = new SpeechRecognitionError(
          kSpeechRecognitionErrorCodeServiceNotAllowed, "");
      break;
    case kSbBadGrammar:
      error_event =
          new SpeechRecognitionError(kSpeechRecognitionErrorCodeBadGrammar, "");
      break;
    case kSbLanguageNotSupported:
      error_event = new SpeechRecognitionError(
          kSpeechRecognitionErrorCodeLanguageNotSupported, "");
      break;
  }
  SB_DCHECK(error_event);
  RunEventCallback(error_event);
}

void StarboardSpeechRecognizer::OnRecognizerResults(SbSpeechResult* results,
                                                    int results_size,
                                                    bool is_final) {
  SpeechRecognitionResultList::SpeechRecognitionResults recognition_results;
  SpeechRecognitionResult::SpeechRecognitionAlternatives alternatives;
  for (int i = 0; i < results_size; ++i) {
    scoped_refptr<SpeechRecognitionAlternative> alternative(
        new SpeechRecognitionAlternative(results[i].transcript,
                                         results[i].confidence));
    alternatives.push_back(alternative);
    // Platform implementation allocates memory of |transcript|.
    SbMemoryDeallocate(results[i].transcript);
  }
  scoped_refptr<SpeechRecognitionResult> recognition_result(
      new SpeechRecognitionResult(alternatives, is_final));
  recognition_results.push_back(recognition_result);

  // Gather all results for the SpeechRecognitionEvent, including all final
  // results we've previously accumulated, plus all (final or not) results that
  // we just received.
  SpeechRecognitionResults success_results;
  size_t total_size = final_results_.size() + recognition_results.size();
  success_results.reserve(total_size);
  success_results = final_results_;
  success_results.insert(success_results.end(), recognition_results.begin(),
                         recognition_results.end());

  size_t result_index = final_results_.size();
  // Update final results list with final results that we just received, so we
  // have them for the next event.
  for (size_t i = 0; i < recognition_results.size(); ++i) {
    if (recognition_results[i]->is_final()) {
      final_results_.push_back(recognition_results[i]);
    }
  }

  scoped_refptr<SpeechRecognitionResultList> recognition_list(
      new SpeechRecognitionResultList(success_results));
  scoped_refptr<SpeechRecognitionEvent> recognition_event(
      new SpeechRecognitionEvent(SpeechRecognitionEvent::kResult,
                                 static_cast<uint32>(result_index),
                                 recognition_list));
  RunEventCallback(recognition_event);
}

}  // namespace speech
}  // namespace cobalt

#endif  // defined(SB_USE_SB_SPEECH_RECOGNIZER)
