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

package dev.cobalt.coat;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.speech.RecognitionListener;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import dev.cobalt.util.Holder;
import dev.cobalt.util.UsedByNative;
import java.util.ArrayList;

/**
 * This class uses Android's SpeechRecognizer to perform speech recognition. Using Android's
 * platform recognizer offers several benefits such as good quality and good local fallback when no
 * data connection is available.
 */
public class VoiceRecognizer {
  private final Context context;
  private final Holder<Activity> activityHolder;
  private final Handler mainHandler = new Handler(Looper.getMainLooper());
  private final AudioPermissionRequester audioPermissionRequester;
  private SpeechRecognizer speechRecognizer;

  // Native pointer to C++ SbSpeechRecognizerImpl.
  private long nativeSpeechRecognizerImpl;

  // Remember if we are using continuous recognition.
  private boolean continuous;
  private boolean interimResults;
  private int maxAlternatives;

  // Internal class to handle events from Android's SpeechRecognizer and route
  // them to native.
  class Listener implements RecognitionListener {
    @Override
    public void onBeginningOfSpeech() {
      nativeOnSpeechDetected(nativeSpeechRecognizerImpl, true);
    }

    @Override
    public void onBufferReceived(byte[] buffer) {}

    @Override
    public void onEndOfSpeech() {
      nativeOnSpeechDetected(nativeSpeechRecognizerImpl, false);
    }

    @Override
    public void onError(int error) {
      nativeOnError(nativeSpeechRecognizerImpl, error);
      reset();
    }

    @Override
    public void onEvent(int eventType, Bundle params) {}

    @Override
    public void onPartialResults(Bundle bundle) {
      handleResults(bundle, false);
    }

    @Override
    public void onReadyForSpeech(Bundle params) {}

    @Override
    public void onResults(Bundle bundle) {
      handleResults(bundle, true);
      reset();
    }

    @Override
    public void onRmsChanged(float rmsdB) {}

    private void handleResults(Bundle bundle, boolean isFinal) {
      ArrayList<String> list = bundle.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
      String[] results = list.toArray(new String[list.size()]);
      float[] scores = bundle.getFloatArray(SpeechRecognizer.CONFIDENCE_SCORES);
      nativeOnResults(nativeSpeechRecognizerImpl, results, scores, isFinal);
    }
  };

  public VoiceRecognizer(
      Context context,
      Holder<Activity> activityHolder,
      AudioPermissionRequester audioPermissionRequester) {
    this.context = context;
    this.activityHolder = activityHolder;
    this.audioPermissionRequester = audioPermissionRequester;
  }

  @SuppressWarnings("unused")
  @UsedByNative
  public void startRecognition(
      boolean continuous,
      boolean interimResults,
      int maxAlternatives,
      long nativeSpeechRecognizer) {
    this.continuous = continuous;
    this.interimResults = interimResults;
    this.maxAlternatives = maxAlternatives;
    this.nativeSpeechRecognizerImpl = nativeSpeechRecognizer;

    if (this.audioPermissionRequester.requestRecordAudioPermission(
        this.nativeSpeechRecognizerImpl)) {
      startRecognitionInternal();
    } else {
      mainHandler.post(
          new Runnable() {
            @Override
            public void run() {
              nativeOnError(
                  nativeSpeechRecognizerImpl, SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS);
            }
          });
    }
  }

  @SuppressWarnings("unused")
  @UsedByNative
  public void stopRecognition() {
    Runnable runnable =
        new Runnable() {
          @Override
          public void run() {
            if (Looper.myLooper() != Looper.getMainLooper()) {
              throw new RuntimeException("Must be called in main thread.");
            }
            if (speechRecognizer == null) {
              return;
            }
            reset();
          }
        };
    mainHandler.post(runnable);
  }

  private void startRecognitionInternal() {
    Runnable runnable =
        new Runnable() {
          @Override
          public void run() {
            if (Looper.myLooper() != Looper.getMainLooper()) {
              throw new RuntimeException("Must be called in main thread.");
            }
            speechRecognizer = SpeechRecognizer.createSpeechRecognizer(context);
            speechRecognizer.setRecognitionListener(new Listener());
            Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
            intent.putExtra(
                RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
            intent.putExtra("android.speech.extra.DICTATION_MODE", continuous);
            intent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, interimResults);
            intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, maxAlternatives);
            speechRecognizer.startListening(intent);
          }
        };
    mainHandler.post(runnable);
  }

  private void reset() {
    speechRecognizer.destroy();
    speechRecognizer = null;

    nativeSpeechRecognizerImpl = 0;
    continuous = false;
    interimResults = false;
    maxAlternatives = 1;
  }

  private native void nativeOnSpeechDetected(long nativeSpeechRecognizerImpl, boolean detected);

  private native void nativeOnError(long nativeSpeechRecognizerImpl, int error);

  private native void nativeOnResults(
      long nativeSpeechRecognizerImpl, String[] results, float[] confidences, boolean isFinal);
}
