// Copyright 2010-2014, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package org.mozc.android.inputmethod.japanese.accessibility;

import org.mozc.android.inputmethod.japanese.keyboard.Flick.Direction;
import org.mozc.android.inputmethod.japanese.keyboard.Key;
import org.mozc.android.inputmethod.japanese.keyboard.KeyEntity;
import org.mozc.android.inputmethod.japanese.keyboard.KeyEventHandler;
import org.mozc.android.inputmethod.japanese.keyboard.KeyState;
import org.mozc.android.inputmethod.japanese.keyboard.KeyState.MetaState;
import org.mozc.android.inputmethod.japanese.keyboard.Keyboard;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.Input.TouchEvent;
import org.mozc.android.inputmethod.japanese.resources.R;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;

import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.support.v4.view.AccessibilityDelegateCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.accessibility.AccessibilityEventCompat;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.support.v4.view.accessibility.AccessibilityNodeProviderCompat;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.accessibility.AccessibilityEvent;

import java.util.Collections;
import java.util.Set;



/**
 * Delegate object for Keyboard view to support accessibility.
 */
public class KeyboardAccessibilityDelegate extends AccessibilityDelegateCompat {

  private final View view;
  private final KeyboardAccessibilityNodeProvider nodeProvider;
  private Optional<Key> lastHoverKey = Optional.absent();
  // Handler which is called back when key-input should be simulated.
  private Optional<KeyEventHandler> keyEventHandler = Optional.absent();
  // Handler for long-press callback.
  // Contains 0 or 1 delayed message.
  private final Handler handler;
  // "what" value of a Message.
  private static final int LONGPRESS_WHAT_VALUE = 1;
  // Delay for long-press detection (in ms).
  private final int longpressDelay;
  // True if the touch sequence is consumed by long-press.
  // In such case touch-up shouldn't send any key events.
  // Reset to false when new touch sequence is started.
  private boolean consumedByLongpress = false;

  private class LongTapHandler implements Handler.Callback {
    @Override
    public boolean handleMessage(Message msg) {
      if (lastHoverKey.isPresent()) {
        simulateLongPress(lastHoverKey.get());
      }
      return true;
    }
  }


  public KeyboardAccessibilityDelegate(View view) {
    this(view, new KeyboardAccessibilityNodeProvider(view),
         view.getContext().getResources().getInteger(
             R.integer.config_long_press_key_delay_accessibility));
  }

  @VisibleForTesting
  KeyboardAccessibilityDelegate(View view,
                                KeyboardAccessibilityNodeProvider nodeProvider,
                                int longpressDelay) {
    this.view = Preconditions.checkNotNull(view);
    this.nodeProvider = Preconditions.checkNotNull(nodeProvider);
    this.handler = new Handler(new LongTapHandler());
    this.longpressDelay = longpressDelay;
  }

  private Context getContext() {
    return view.getContext();
  }

  /**
   * Intercepts touch events before dispatch when touch exploration is turned on in ICS and
   * higher.
   *
   * @param event The motion event being dispatched.
   * @return {@code true} if the event is handled
   */
  public boolean dispatchTouchEvent(MotionEvent event) {
    // To avoid accidental key presses during touch exploration, always drop
    // touch events generated by the user.
    return false;
  }

  /**
   * Dispatched from {@code View#dispatchHoverEvent}.
   *
   * @return {@code true} if the event was handled by the view, false otherwise
   */
  public boolean dispatchHoverEvent(MotionEvent event) {
    Preconditions.checkNotNull(event);

    Optional<Key> optionalKey = nodeProvider.getKey((int) event.getX(), (int) event.getY());
    switch (event.getAction()) {
      case MotionEvent.ACTION_HOVER_ENTER:
        Preconditions.checkState(!lastHoverKey.isPresent());
        consumedByLongpress = false;
        if (optionalKey.isPresent()) {
          Key key = optionalKey.get();
          // Notify the user that we are entering new virtual view.
          nodeProvider.sendAccessibilityEventForKeyIfAccessibilityEnabled(
              key, AccessibilityEventCompat.TYPE_VIEW_HOVER_ENTER);
          // Make virtual view focus on the key.
          nodeProvider.performActionForKey(
              key, AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS);
          // Register singleton message for long-press.
          handler.removeMessages(LONGPRESS_WHAT_VALUE);
          handler.sendMessageDelayed(
              handler.obtainMessage(LONGPRESS_WHAT_VALUE, 0, 0, getContext()), longpressDelay);
        }
        lastHoverKey = optionalKey;
        break;
      case MotionEvent.ACTION_HOVER_EXIT:
        if (optionalKey.isPresent()) {
          Key key = optionalKey.get();
          simulateKeyInput(key);
          // Notify the user that we are exiting from the key.
          nodeProvider.sendAccessibilityEventForKeyIfAccessibilityEnabled(
              key, AccessibilityEventCompat.TYPE_VIEW_HOVER_EXIT);
          // Make virtual view unfocused.
          nodeProvider.performActionForKey(
              key, AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
        }
        lastHoverKey = Optional.absent();
        // Remove all the long-press messages.
        handler.removeMessages(LONGPRESS_WHAT_VALUE);
        break;
      case MotionEvent.ACTION_HOVER_MOVE:
        if (optionalKey.equals(lastHoverKey)) {
          // Hovering status is unchanged.
          break;
        }
        if (lastHoverKey.isPresent()) {
          // Notify the user that we are exiting from lastHoverKey.
          nodeProvider.sendAccessibilityEventForKeyIfAccessibilityEnabled(
              lastHoverKey.get(), AccessibilityEventCompat.TYPE_VIEW_HOVER_EXIT);
          // Make virtual view unfocused.
          nodeProvider.performActionForKey(
              lastHoverKey.get(), AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
        }
        if (optionalKey.isPresent()) {
          Key key = optionalKey.get();
          // Notify the user that we are entering new virtual view.
          nodeProvider.sendAccessibilityEventForKeyIfAccessibilityEnabled(
              key, AccessibilityEventCompat.TYPE_VIEW_HOVER_ENTER);
          // Make virtual view focus on the key.
          nodeProvider.performActionForKey(
              key, AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS);
          // Register singleton message for long-press.
          handler.removeMessages(LONGPRESS_WHAT_VALUE);
          handler.sendMessageDelayed(
              handler.obtainMessage(LONGPRESS_WHAT_VALUE, 0, 0, getContext()), longpressDelay);
        }
        lastHoverKey = optionalKey;
        break;
    }
    return optionalKey.isPresent();
  }

  private void simulateKeyInput(Key key) {
    Preconditions.checkNotNull(key);
    Optional<KeyState> keyState = key.getKeyState(Collections.<MetaState>emptySet());
    if (!keyState.isPresent()) {
      return;
    }
    int keyCode = keyState.get().getFlick(Direction.CENTER).getKeyEntity().getKeyCode();
    if (keyCode == KeyEntity.INVALID_KEY_CODE
        || !keyEventHandler.isPresent()
        || consumedByLongpress) {
      return;
    }
    keyEventHandler.get().sendKey(keyCode, Collections.<TouchEvent>emptyList());
  }

  private void simulateLongPress(Key key) {
    Preconditions.checkNotNull(key);
    Optional<KeyState> keyState = key.getKeyState(Collections.<MetaState>emptySet());
    if (!keyState.isPresent()) {
      return;
    }
    int longPressKeyCode = keyState.get().getFlick(Direction.CENTER)
                                   .getKeyEntity().getLongPressKeyCode();
    if (longPressKeyCode == KeyEntity.INVALID_KEY_CODE
        || !keyEventHandler.isPresent()
        || consumedByLongpress) {
      return;
    }
    keyEventHandler.get().sendKey(longPressKeyCode, Collections.<TouchEvent>emptyList());
    consumedByLongpress = true;
  }

  @Override
  public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View host) {
    return nodeProvider;
  }

  /**
   * Sets metastate of the keyboard.
   *
   * <p>Node provider's internal state is reset here.
   */
  public void setMetaState(Set<MetaState> metaState) {
    nodeProvider.setMetaState(Preconditions.checkNotNull(metaState));
  }

  /**
   * Sets the keyboard.
   *
   * <p>Node provider's internal state is reset here.
   */
  public void setKeyboard(Optional<Keyboard> keyboard) {
    nodeProvider.setKeyboard(Preconditions.checkNotNull(keyboard));
    if (AccessibilityUtil.isAccessibilityEnabled(getContext())) {
      Optional<String> contentDescription = keyboard.isPresent()
          ? keyboard.get().getContentDescription()
          : Optional.<String>absent();
      sendWindowStateChanged(contentDescription);
    }
  }


  /**
   * Sets whether here is password field or not..
   *
   * <p>Node provider's internal state is reset here.
   */
  public void setPasswordField(boolean isPasswordField) {
    boolean shouldObscureInput = shouldObscureInput(isPasswordField);
    nodeProvider.setObscureInput(shouldObscureInput);

    if (shouldObscureInput) {
      announceForAccessibility(getContext().getResources().getString(
          R.string.spoken_use_headphone_for_password));
    }
  }

  private void announceForAccessibility(String text) {
    AccessibilityEvent event = AccessibilityEvent.obtain();
    event.setPackageName(getClass().getPackage().getName());
    event.setClassName(getClass().getName());
    event.setEventTime(SystemClock.uptimeMillis());
    event.setEnabled(true);
    event.getText().add(Preconditions.checkNotNull(text));
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
      event.setEventType(AccessibilityEventCompat.TYPE_ANNOUNCEMENT);
    } else {
      event.setEventType(AccessibilityEvent.TYPE_VIEW_FOCUSED);
    }
    requestSendAccessibilityEventIfPossible(event);
  }

  /**
   * Sends a window state change event with the specified text.
   *
   * @param newContentDescription the text to send with the event as content description
   */
  private void sendWindowStateChanged(Optional<String> newContentDescription) {
    Preconditions.checkNotNull(newContentDescription);
    AccessibilityEvent stateChange = AccessibilityEvent.obtain(
        AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
    ViewCompat.onInitializeAccessibilityEvent(view, stateChange);
    stateChange.setContentDescription(newContentDescription.orNull());
    requestSendAccessibilityEventIfPossible(stateChange);
  }

  /**
   * Sends an AccessibilityEvent throuth {@code view}'s parent.
   * If the API Level is <14, does nothing.
   */
  private void requestSendAccessibilityEventIfPossible(AccessibilityEvent event) {
    Preconditions.checkNotNull(event);

    ViewParent viewParent = view.getParent();
    if ((viewParent == null) || !(viewParent instanceof ViewGroup)) {
        return;
    }
    // requestSendAccessibilityEvent is since API Level 14 (ICS).
    // No fallback is provided for older framework. Just ignore.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
      viewParent.requestSendAccessibilityEvent(view, event);
    }
  }

  /**
   * Returns whether raw password shouldn't be spoken.
   *
   * @return false is raw password should be spoken
   */
  private boolean shouldObscureInput(boolean isPasswordField) {
    // If accessibility is disabled, obscure input is not required.
    // This check should be done prior to isAccessibilitySpeakPasswordEnabled
    // since isAccessibilitySpeakPasswordEnabled is heavier.
    if (!AccessibilityUtil.isAccessibilityEnabled(getContext())) {
      return false;
    }

    // The user can optionally force speaking passwords.
    if (AccessibilityUtil.isAccessibilitySpeakPasswordEnabled()) {
      return false;
    }

    // Always speak if the user is listening through headphones.
    AudioManagerWrapper audioManager = AccessibilityUtil.getAudioManager(getContext());
    if (audioManager.isWiredHeadsetOn() || audioManager.isBluetoothA2dpOn()) {
        return false;
    }

    // Don't speak if the IME is connected to a password field.
    return isPasswordField;
  }

  public void setKeyEventHandler(Optional<KeyEventHandler> keyEventHandler) {
    this.keyEventHandler = Preconditions.checkNotNull(keyEventHandler);
  }
}
