/*
 * Copyright (C) 2012 Google Inc.
 *
 * 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 com.googlecode.eyesfree.utils;

import android.content.Context;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.v4.view.AccessibilityDelegateCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.support.v4.view.accessibility.AccessibilityNodeProviderCompat;
import android.support.v4.view.accessibility.AccessibilityRecordCompat;
import android.text.TextUtils;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;

import java.util.LinkedList;
import java.util.List;

public abstract class TouchExplorationHelper<T> extends AccessibilityNodeProviderCompat
        implements View.OnHoverListener {
    /** Virtual node identifier value for invalid nodes. */
    public static final int INVALID_ID = Integer.MIN_VALUE;

    private final Rect mTempScreenRect = new Rect();
    private final Rect mTempParentRect = new Rect();
    private final Rect mTempVisibleRect = new Rect();
    private final int[] mTempGlobalRect = new int[2];

    private final AccessibilityManager mManager;

    private View mParentView;
    private int mFocusedItemId = INVALID_ID;
    private T mCurrentItem = null;

    /**
     * Constructs a new touch exploration helper.
     *
     * @param context The parent context.
     */
    public TouchExplorationHelper(Context context, View parentView) {
        mManager = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
        mParentView = parentView;
    }

    /**
     * @return The current accessibility focused item, or {@code null} if no
     *         item is focused.
     */
    public T getFocusedItem() {
        return getItemForId(mFocusedItemId);
    }

    /**
     * Clears the current accessibility focused item.
     */
    public void clearFocusedItem() {
        final int itemId = mFocusedItemId;
        if (itemId == INVALID_ID) {
            return;
        }

        performAction(itemId, AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
    }

    /**
     * Requests accessibility focus be placed on the specified item.
     *
     * @param item The item to place focus on.
     */
    public void setFocusedItem(T item) {
        final int itemId = getIdForItem(item);
        if (itemId == INVALID_ID) {
            return;
        }

        performAction(itemId, AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS, null);
    }

    /**
     * Invalidates cached information about the parent view.
     * <p>
     * You <b>must</b> call this method after adding or removing items from the
     * parent view.
     * </p>
     */
    public void invalidateParent() {
        mParentView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
    }

    /**
     * Invalidates cached information for a particular item.
     * <p>
     * You <b>must</b> call this method when any of the properties set in
     * {@link #populateNodeForItem(Object, AccessibilityNodeInfoCompat)} have
     * changed.
     * </p>
     *
     * @param item
     */
    public void invalidateItem(T item) {
        sendEventForItem(item, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
    }

    /**
     * Populates an event of the specified type with information about an item
     * and attempts to send it up through the view hierarchy.
     *
     * @param item The item for which to send an event.
     * @param eventType The type of event to send.
     * @return {@code true} if the event was sent successfully.
     */
    public boolean sendEventForItem(T item, int eventType) {
        if (!mManager.isEnabled()) {
            return false;
        }

        final AccessibilityEvent event = getEventForItem(item, eventType);
        final ViewGroup group = (ViewGroup) mParentView.getParent();

        return group.requestSendAccessibilityEvent(mParentView, event);
    }

    @Override
    public AccessibilityNodeInfoCompat createAccessibilityNodeInfo(int virtualViewId) {
        if (virtualViewId == View.NO_ID) {
            return getNodeForParent();
        }

        final T item = getItemForId(virtualViewId);
        if (item == null) {
            return null;
        }

        final AccessibilityNodeInfoCompat node = AccessibilityNodeInfoCompat.obtain();
        populateNodeForItemInternal(item, node);
        return node;
    }

    @Override
    public boolean performAction(int virtualViewId, int action, Bundle arguments) {
        if (virtualViewId == View.NO_ID) {
            return ViewCompat.performAccessibilityAction(mParentView, action, arguments);
        }

        final T item = getItemForId(virtualViewId);
        if (item == null) {
            return false;
        }

        boolean handled = false;

        switch (action) {
            case AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS:
                if (mFocusedItemId != virtualViewId) {
                    mFocusedItemId = virtualViewId;
                    sendEventForItem(item, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
                    handled = true;
                }
                break;
            case AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS:
                if (mFocusedItemId == virtualViewId) {
                    mFocusedItemId = INVALID_ID;
                    sendEventForItem(item, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
                    handled = true;
                }
                break;
        }

        handled |= performActionForItem(item, action, arguments);

        return handled;
    }

    @Override
    public boolean onHover(View view, MotionEvent event) {
        if (!mManager.isTouchExplorationEnabled()) {
            return false;
        }

        switch (event.getAction()) {
            case MotionEvent.ACTION_HOVER_ENTER:
            case MotionEvent.ACTION_HOVER_MOVE:
                final T item = getItemAt(event.getX(), event.getY());
                setCurrentItem(item);
                return true;
            case MotionEvent.ACTION_HOVER_EXIT:
                setCurrentItem(null);
                return true;
        }

        return false;
    }

    private void setCurrentItem(T item) {
        if (mCurrentItem == item) {
            return;
        }

        if (mCurrentItem != null) {
            sendEventForItem(mCurrentItem, AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
        }

        mCurrentItem = item;

        if (mCurrentItem != null) {
            sendEventForItem(mCurrentItem, AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
        }
    }

    private AccessibilityEvent getEventForItem(T item, int eventType) {
        final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
        final AccessibilityRecordCompat record = new AccessibilityRecordCompat(event);
        final int virtualDescendantId = getIdForItem(item);

        // Ensure the client has good defaults.
        event.setEnabled(true);

        // Allow the client to populate the event.
        populateEventForItem(item, event);

        if (event.getText().isEmpty() && TextUtils.isEmpty(event.getContentDescription())) {
            throw new RuntimeException(
                    "You must add text or a content description in populateEventForItem()");
        }

        // Don't allow the client to override these properties.
        event.setClassName(item.getClass().getName());
        event.setPackageName(mParentView.getContext().getPackageName());
        record.setSource(mParentView, virtualDescendantId);

        return event;
    }

    private AccessibilityNodeInfoCompat getNodeForParent() {
        final AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(mParentView);
        ViewCompat.onInitializeAccessibilityNodeInfo(mParentView, info);

        final LinkedList<T> items = new LinkedList<T>();
        getVisibleItems(items);

        for (T item : items) {
            final int virtualDescendantId = getIdForItem(item);
            info.addChild(mParentView, virtualDescendantId);
        }

        return info;
    }

    private AccessibilityNodeInfoCompat populateNodeForItemInternal(
            T item, AccessibilityNodeInfoCompat node) {
        final int virtualDescendantId = getIdForItem(item);

        // Ensure the client has good defaults.
        node.setEnabled(true);

        // Allow the client to populate the node.
        populateNodeForItem(item, node);

        if (TextUtils.isEmpty(node.getText()) && TextUtils.isEmpty(node.getContentDescription())) {
            throw new RuntimeException(
                    "You must add text or a content description in populateNodeForItem()");
        }

        // Don't allow the client to override these properties.
        node.setPackageName(mParentView.getContext().getPackageName());
        node.setClassName(item.getClass().getName());
        node.setParent(mParentView);
        node.setSource(mParentView, virtualDescendantId);

        if (mFocusedItemId == virtualDescendantId) {
            node.addAction(AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
        } else {
            node.addAction(AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS);
        }

        node.getBoundsInParent(mTempParentRect);
        if (mTempParentRect.isEmpty()) {
            throw new RuntimeException("You must set parent bounds in populateNodeForItem()");
        }

        // Set the visibility based on the parent bound.
        if (intersectVisibleToUser(mTempParentRect)) {
            node.setVisibleToUser(true);
            node.setBoundsInParent(mTempParentRect);
        }

        // Calculate screen-relative bound.
        mParentView.getLocationOnScreen(mTempGlobalRect);
        final int offsetX = mTempGlobalRect[0];
        final int offsetY = mTempGlobalRect[1];
        mTempScreenRect.set(mTempParentRect);
        mTempScreenRect.offset(offsetX, offsetY);
        node.setBoundsInScreen(mTempScreenRect);

        return node;
    }

    /**
     * Computes whether the specified {@link Rect} intersects with the visible
     * portion of its parent {@link View}. Modifies {@code localRect} to
     * contain only the visible portion.
     *
     * @param localRect A rectangle in local (parent) coordinates.
     * @return Whether the specified {@link Rect} is visible on the screen.
     */
    private boolean intersectVisibleToUser(Rect localRect) {
        // Missing or empty bounds mean this view is not visible.
        if ((localRect == null) || localRect.isEmpty()) {
            return false;
        }

        // Attached to invisible window means this view is not visible.
        if (mParentView.getWindowVisibility() != View.VISIBLE) {
            return false;
        }

        // An invisible predecessor or one with alpha zero means
        // that this view is not visible to the user.
        Object current = this;
        while (current instanceof View) {
            final View view = (View) current;
            // We have attach info so this view is attached and there is no
            // need to check whether we reach to ViewRootImpl on the way up.
            if ((view.getAlpha() <= 0) || (view.getVisibility() != View.VISIBLE)) {
                return false;
            }
            current = view.getParent();
        }

        // If no portion of the parent is visible, this view is not visible.
        if (!mParentView.getLocalVisibleRect(mTempVisibleRect)) {
            return false;
        }

        // Check if the view intersects the visible portion of the parent.
        return localRect.intersect(mTempVisibleRect);
    }

    public AccessibilityDelegateCompat getAccessibilityDelegate() {
        return mDelegate;
    }

    private final AccessibilityDelegateCompat mDelegate = new AccessibilityDelegateCompat() {
        @Override
        public void onInitializeAccessibilityEvent(View view, AccessibilityEvent event) {
            super.onInitializeAccessibilityEvent(view, event);
            event.setClassName(view.getClass().getName());
        }

        @Override
        public void onInitializeAccessibilityNodeInfo(View view, AccessibilityNodeInfoCompat info) {
            super.onInitializeAccessibilityNodeInfo(view, info);
            info.setClassName(view.getClass().getName());
        }

        @Override
        public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View host) {
            return TouchExplorationHelper.this;
        }
    };

    /**
     * Performs an accessibility action on the specified item. See
     * {@link AccessibilityNodeInfoCompat#performAction(int, Bundle)}.
     * <p>
     * The helper class automatically handles focus management resulting from
     * {@link AccessibilityNodeInfoCompat#ACTION_ACCESSIBILITY_FOCUS} and
     * {@link AccessibilityNodeInfoCompat#ACTION_CLEAR_ACCESSIBILITY_FOCUS}, so
     * typically a developer only needs to handle actions added manually in the
     * {{@link #populateNodeForItem(Object, AccessibilityNodeInfoCompat)}
     * method.
     * </p>
     *
     * @param item The item on which to perform the action.
     * @param action The accessibility action to perform.
     * @param arguments Arguments for the action, or optionally {@code null}.
     * @return {@code true} if the action was performed successfully.
     */
    protected abstract boolean performActionForItem(T item, int action, Bundle arguments);

    /**
     * Populates an event with information about the specified item.
     * <p>
     * At a minimum, a developer must populate the event text by doing one of
     * the following:
     * <ul>
     * <li>appending text to {@link AccessibilityEvent#getText()}</li>
     * <li>populating a description with
     * {@link AccessibilityEvent#setContentDescription(CharSequence)}</li>
     * </ul>
     * </p>
     *
     * @param item The item for which to populate the event.
     * @param event The event to populate.
     */
    protected abstract void populateEventForItem(T item, AccessibilityEvent event);

    /**
     * Populates a node with information about the specified item.
     * <p>
     * At a minimum, a developer must:
     * <ul>
     * <li>populate the event text using
     * {@link AccessibilityNodeInfoCompat#setText(CharSequence)} or
     * {@link AccessibilityNodeInfoCompat#setContentDescription(CharSequence)}
     * </li>
     * <li>set the item's parent-relative bounds using
     * {@link AccessibilityNodeInfoCompat#setBoundsInParent(Rect)}
     * </ul>
     *
     * @param item The item for which to populate the node.
     * @param node The node to populate.
     */
    protected abstract void populateNodeForItem(T item, AccessibilityNodeInfoCompat node);

    /**
     * Populates a list with the parent view's visible items.
     * <p>
     * The result of this method is cached until the developer calls
     * {@link #invalidateParent()}.
     * </p>
     *
     * @param items The list to populate with visible items.
     */
    protected abstract void getVisibleItems(List<T> items);

    /**
     * Returns the item under the specified parent-relative coordinates.
     *
     * @param x The parent-relative x coordinate.
     * @param y The parent-relative y coordinate.
     * @return The item under coordinates (x,y).
     */
    protected abstract T getItemAt(float x, float y);

    /**
     * Returns the unique identifier for an item. If the specified item does not
     * exist, returns {@link #INVALID_ID}.
     * <p>
     * This result of this method must be consistent with
     * {@link #getItemForId(int)}.
     * </p>
     *
     * @param item The item whose identifier to return.
     * @return A unique identifier, or {@link #INVALID_ID}.
     */
    protected abstract int getIdForItem(T item);

    /**
     * Returns the item for a unique identifier. If the specified item does not
     * exist, returns {@code null}.
     *
     * @param id The identifier for the item to return.
     * @return An item, or {@code null}.
     */
    protected abstract T getItemForId(int id);
}
