// 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 static dev.cobalt.util.Log.TAG;

import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.speech.tts.TextToSpeech;
import android.view.accessibility.AccessibilityManager;
import dev.cobalt.util.Log;
import dev.cobalt.util.UsedByNative;
import java.util.ArrayList;
import java.util.List;

/**
 * Helper class to implement the SbSpeechSynthesis* Starboard API for Audio accessibility.
 *
 * <p>This class is intended to be a singleton in the system. It creates a single static Handler
 * thread in lieu of other synchronization options.
 */
class CobaltTextToSpeechHelper
    implements TextToSpeech.OnInitListener,
        AccessibilityManager.AccessibilityStateChangeListener,
        AccessibilityManager.TouchExplorationStateChangeListener {
  private final Context context;
  private final HandlerThread thread;
  private final Handler handler;

  // The TTS engine should be used only on the background thread.
  private TextToSpeech ttsEngine;

  private boolean wasScreenReaderEnabled;

  private enum State {
    PENDING,
    INITIALIZED,
    FAILED
  }

  // These are only accessed inside the Handler Thread
  private State state = State.PENDING;
  private long nextUtteranceId;
  private final List<String> pendingUtterances = new ArrayList<>();

  CobaltTextToSpeechHelper(Context context) {
    this.context = context;

    thread = new HandlerThread("CobaltTextToSpeechHelper");
    thread.start();
    handler = new Handler(thread.getLooper());

    AccessibilityManager accessibilityManager =
        (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
    wasScreenReaderEnabled = isScreenReaderEnabled();
    accessibilityManager.addAccessibilityStateChangeListener(this);
    accessibilityManager.addTouchExplorationStateChangeListener(this);
  }

  public void shutdown() {

    handler.post(
        new Runnable() {
          @Override
          public void run() {
            if (ttsEngine != null) {
              ttsEngine.shutdown();
            }
          }
        });
    thread.quitSafely();

    AccessibilityManager accessibilityManager =
        (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
    accessibilityManager.removeAccessibilityStateChangeListener(this);
    accessibilityManager.removeTouchExplorationStateChangeListener(this);
  }

  /** Returns whether a screen reader is currently enabled */
  @SuppressWarnings("unused")
  @UsedByNative
  public boolean isScreenReaderEnabled() {
    AccessibilityManager am =
        (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
    final List<AccessibilityServiceInfo> screenReaders =
        am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_SPOKEN);
    return !screenReaders.isEmpty();
  }

  /** Implementation of TextToSpeech.OnInitListener */
  @Override
  public void onInit(final int status) {
    handler.post(
        new Runnable() {
          @Override
          public void run() {
            if (status != TextToSpeech.SUCCESS) {
              Log.e(TAG, "TextToSpeech.onInit failure: " + status);
              state = State.FAILED;
              return;
            }
            state = State.INITIALIZED;
            for (String utterance : pendingUtterances) {
              speak(utterance);
            }
            pendingUtterances.clear();
          }
        });
  }

  /**
   * Speaks the given text, enqueuing it if something is already speaking. Java-layer implementation
   * of Starboard's SbSpeechSynthesisSpeak.
   */
  @SuppressWarnings("unused")
  @UsedByNative
  void speak(final String text) {

    handler.post(
        new Runnable() {
          @Override
          public void run() {

            if (ttsEngine == null) {
              ttsEngine = new TextToSpeech(context, CobaltTextToSpeechHelper.this);
            }

            switch (state) {
              case PENDING:
                pendingUtterances.add(text);
                break;
              case INITIALIZED:
                int success =
                    ttsEngine.speak(
                        text, TextToSpeech.QUEUE_ADD, null, Long.toString(nextUtteranceId++));

                if (success != TextToSpeech.SUCCESS) {
                  Log.e(TAG, "TextToSpeech.speak error: " + success);
                  return;
                }
                break;
              case FAILED:
                break;
            }
          }
        });
  }

  /** Cancels all speaking. Java-layer implementation of Starboard's SbSpeechSynthesisCancel. */
  @SuppressWarnings("unused")
  @UsedByNative
  void cancel() {
    handler.post(
        new Runnable() {
          @Override
          public void run() {
            if (ttsEngine != null) {
              ttsEngine.stop();
            }
            pendingUtterances.clear();
          }
        });
  }

  @Override
  public void onAccessibilityStateChanged(boolean enabled) {
    // Note that this callback isn't perfect since it only tells us if accessibility was entirely
    // enabled/disabled, but it's better than nothing. For example, it won't be called if the screen
    // reader is enabled/disabled while text magnification remains enabled.
    finishIfScreenReaderChanged();
  }

  @Override
  public void onTouchExplorationStateChanged(boolean enabled) {
    // We also listen for talkback changes because it's the standard (but not only) screen reader,
    // and we can get a better signal than just listening for accessibility being enabled/disabled.
    finishIfScreenReaderChanged();
  }

  /**
   * Quit the app if screen reader settings changed so we respect the new setting the next time the
   * app is run. This should only happen while stopped in the background since the user has to leave
   * the app to change the setting.
   */
  private void finishIfScreenReaderChanged() {
    if (wasScreenReaderEnabled != isScreenReaderEnabled()) {
      wasScreenReaderEnabled = isScreenReaderEnabled();
      nativeSendTTSChangedEvent();
    }
  }

  private native void nativeSendTTSChangedEvent();
}
