/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * 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.android.globalsearch;

import android.app.SearchManager;
import android.app.SearchManager.DialogCursorProtocol;
import android.database.AbstractCursor;
import android.database.CursorIndexOutOfBoundsException;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
import android.view.KeyEvent;

import java.util.ArrayList;
import java.util.List;

/**
 * This is the Cursor that we return from SuggestionProvider.  It relies on its
 * {@link SuggestionBacker} for results and notifications of changes to the results.
 *
 * The backer is attached via {@link #attachBacker(SuggestionBacker)} once it is ready.
 *
 * Important: a local consistent copy of the suggestions is stored in the cursor.  The only safe
 * place to update this copy is in {@link #requery}.
 */
public class SuggestionCursor extends AbstractCursor implements SuggestionBacker.Listener {
    // set to true to enable the more verbose debug logging for this file
    private static final boolean DBG = false;

    // set to true along with DBG to be even more verbose
    private static final boolean SPEW = false;

    // set to true to dump a full list of the suggestions each time the cursor is requeried
    private static final boolean DUMP_SUGGESTIONS = false;

    private static final String TAG = SuggestionCursor.class.getSimpleName();

    // The extra used to tell a cursor to close itself. This is a hack to work around
    // the fact that cross-process cursors currently don't get closed by Cursor.close(),
    // http://b/issue?id=2015069
    private static final String EXTRA_CURSOR_RESPOND_CLOSE_CURSOR = "cursor_respond_close_cursor";

    // the same as the string in suggestActionMsgColumn in res/xml/searchable.xml
    private static final String SUGGEST_COLUMN_ACTION_MSG_CALL = "suggest_action_msg_call";

    private static final String[] COLUMNS = {
            "_id",
            SearchManager.SUGGEST_COLUMN_FORMAT,
            SearchManager.SUGGEST_COLUMN_TEXT_1,
            SearchManager.SUGGEST_COLUMN_TEXT_2,
            SearchManager.SUGGEST_COLUMN_ICON_1,
            SearchManager.SUGGEST_COLUMN_ICON_2,
            SearchManager.SUGGEST_COLUMN_QUERY,
            SearchManager.SUGGEST_COLUMN_INTENT_ACTION,
            SearchManager.SUGGEST_COLUMN_INTENT_DATA,
            SUGGEST_COLUMN_ACTION_MSG_CALL,
            SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA,
            SearchManager.SUGGEST_COLUMN_INTENT_COMPONENT_NAME,
            SearchManager.SUGGEST_COLUMN_SHORTCUT_ID,
            SearchManager.SUGGEST_COLUMN_BACKGROUND_COLOR
            };

    // Indices into COLUMNS
    private static final int _ID = 0;
    private static final int FORMAT = 1;
    private static final int TEXT_1 = 2;
    private static final int TEXT_2 = 3;
    private static final int ICON_1 = 4;
    private static final int ICON_2 = 5;
    private static final int QUERY = 6;
    private static final int INTENT_ACTION = 7;
    private static final int INTENT_DATA = 8;
    private static final int ACTION_MSG_CALL = 9;
    private static final int INTENT_EXTRA_DATA = 10;
    private static final int INTENT_COMPONENT_NAME = 11;
    private static final int SHORTCUT_ID = 12;
    private static final int BACKGROUND_COLOR = 13;

    private boolean mOnMoreCalled = false;

    private final String mQuery;
    private final DelayedExecutor mDelayedExecutor;
    private boolean mIncludeSources;
    private CursorListener mListener;

    private SuggestionBacker mBacker;
    private long mNextNotify = 0;

    // we keep a consistent snapshot locally
    private ArrayList<SuggestionData> mData = new ArrayList<SuggestionData>(10);

    /**
     * We won't call {@link AbstractCursor#onChange} more than once per window.
     */
    private static final int CURSOR_NOTIFY_WINDOW_MS = 100;

    /**
     * Interface for receiving notification from the cursor.
     */
    public interface CursorListener {
        /**
         * Called when the cursor has been closed.
         */
        void onClose();

        /**
         * Called when an item is clicked.
         *
         * @param pos The index of the suggestion that was clicked.
         * @param displayedSuggestions The suggestions that have been displayed to the user.
         * @param actionKey action key used to click the suggestion, or KeyEvent.KEYCODE_UNKNOWN.
         * @param actionMsg action message for the action key used, or {@code null}.
         */
        void onItemClicked(int pos, List<SuggestionData> displayedSuggestions,
                int actionKey, String actionMsg);

        /**
         * Called the first time "more" becomes visible
         */
        void onMoreVisible();

        /**
         * Called when the user starts a search without using a suggestion.
         *
         * @param query Search query.
         * @param displayedSuggestions The suggestions that have been displayed to the user.
         */
        void onSearch(String query, List<SuggestionData> displayedSuggestions);
    }

    /**
     * @param delayedExecutor used to post messages.
     * @param query The query that was sent.
     */
    public SuggestionCursor(DelayedExecutor delayedExecutor, String query) {
        mQuery = query;
        mDelayedExecutor = delayedExecutor;
        mIncludeSources = false;
    }

    /**
     * Set the suggestion backer, triggering the initial snapshot.
     *
     * @param backer The backer.
     */
    public void attachBacker(SuggestionBacker backer) {
        mBacker = backer;
        mBacker.snapshotSuggestions(mData, mIncludeSources);
        onNewResults();
    }

    /**
     * Prefills the results from this cursor with the results from another.  This is used when no
     * other results are initially available to provide a smoother experience.
     *
     * @param other The other cursor to get the results from.
     */
    public void prefill(SuggestionCursor other) {
        if (!mData.isEmpty()) {
            throw new IllegalStateException("prefilled when we aleady have results");
        }
        mData.clear();
        mData.addAll(other.mData);
    }

    @Override
    public String[] getColumnNames() {
        return COLUMNS;
    }

    @Override
    public int getCount() {
        return mData.size();
    }

    /**
     * Handles out-of-band messages from the search dialog.
     */
    @Override
    public Bundle respond(Bundle extras) {
        if (DBG) Log.d(TAG, "respond(" + extras + ")");

        // Hack to work around http://b/issue?id=2015069,
        // "CursorToBulkCursorAdaptor.close() does not call mCursor.close()"
        if (extras.getBoolean(EXTRA_CURSOR_RESPOND_CLOSE_CURSOR)) {
            close();
            return Bundle.EMPTY;
        }

        final int method = extras.getInt(SearchManager.DialogCursorProtocol.METHOD, -1);

        if (method == -1) {
            Log.w(TAG, "received unexpectd respond: no DialogCursorProtocol.METHOD specified.");
            return Bundle.EMPTY;
        }

        switch (method) {
            case DialogCursorProtocol.POST_REFRESH:
                return respondPostRefresh(extras);
            case DialogCursorProtocol.CLICK:
                return respondClick(extras);
            case DialogCursorProtocol.THRESH_HIT:
                return respondThreshHit(extras);
            case DialogCursorProtocol.SEARCH:
                return respondSearch(extras);
            default:
                Log.e(TAG, "unexpected DialogCursorProtocol.METHOD " + method);
                return Bundle.EMPTY;
        }
    }

    /**
     * Handle receiving and sending back information associated with
     * {@link DialogCursorProtocol#POST_REFRESH}.
     *
     * @param request The bundle sent.
     * @return The response bundle.
     */
    private Bundle respondPostRefresh(Bundle request) {
        Bundle response = new Bundle(2);
        response.putBoolean(
                DialogCursorProtocol.POST_REFRESH_RECEIVE_ISPENDING, isResultsPending());

        if (isShowingMore() && !mOnMoreCalled) {
            // tell the dialog we want to be notified when "more results" is first displayed
            response.putInt(
                    DialogCursorProtocol.POST_REFRESH_RECEIVE_DISPLAY_NOTIFY,
                    getMoreResultsPosition());
        }
        return response;
    }

    private boolean isResultsPending() {
        // asssume results are pending until we get the backer
        return mBacker == null ? true : mBacker.isResultsPending();
    }

    private boolean isShowingMore() {
        return mBacker != null && mBacker.isShowingMore();
    }

    private int getMoreResultsPosition() {
        return mBacker == null ?
                mData.size() :
                mBacker.getMoreResultPosition();
    }

    /**
     * Handle receiving and sending back information associated with
     * {@link DialogCursorProtocol#CLICK}.
     *
     * @param request The bundle sent.
     * @return The response bundle.
     */
    private Bundle respondClick(Bundle request) {
        final int pos = request.getInt(DialogCursorProtocol.CLICK_SEND_POSITION, -1);
        int maxDisplayed = request.getInt(DialogCursorProtocol.CLICK_SEND_MAX_DISPLAY_POS, -1);
        int actionKey =
                request.getInt(DialogCursorProtocol.CLICK_SEND_ACTION_KEY, KeyEvent.KEYCODE_UNKNOWN);
        String actionMsg = request.getString(DialogCursorProtocol.CLICK_SEND_ACTION_MSG);
        if (DBG) Log.d(TAG, "respondClick(), pos=" + pos + ", maxDisplayed=" + maxDisplayed);

        if (pos == -1) {
            Log.w(TAG, "DialogCursorProtocol.CLICK didn't come with extra CLICK_SEND_POSITION");
            return Bundle.EMPTY;
        }

        List<SuggestionData> displayedSuggestions = getDisplayedSuggestions(maxDisplayed);

        if (mListener != null && pos >= 0 && pos <= maxDisplayed) {
            mListener.onItemClicked(pos, displayedSuggestions, actionKey, actionMsg);
        }

        // if they click on the "more results item"
        if (pos == getMoreResultsPosition()) {
            // toggle the expansion of the additional sources
            mIncludeSources = !mIncludeSources;
            onNewResults();

            if (mIncludeSources) {
                // if we have switched to expanding,
                // tell the search dialog to select the position of the "more" entry so that
                // the additional corpus entries will become visible without having to
                // manually scroll
                final Bundle response = new Bundle();
                response.putInt(DialogCursorProtocol.CLICK_RECEIVE_SELECTED_POS, pos);
                return response;
            }
        }
        return Bundle.EMPTY;
    }

    private List<SuggestionData> getDisplayedSuggestions(int maxDisplayed) {
        // avoid exceptions from List.subList()
        final int numSuggestions = mData.size();
        if (maxDisplayed < -1) maxDisplayed = -1;
        if (maxDisplayed >= numSuggestions) maxDisplayed = numSuggestions - 1;
        return mData.subList(0, maxDisplayed + 1);
    }

    /**
     * Handle receiving and sending back information associated with
     * {@link DialogCursorProtocol#THRESH_HIT}.
     *
     * We use this to get notified when "more" is first scrolled onto screen.
     *
     * @param request The bundle sent.
     * @return The response bundle.
     */
    private Bundle respondThreshHit(Bundle request) {
        mOnMoreCalled = true;
        if (mListener != null) mListener.onMoreVisible();
        return Bundle.EMPTY;
    }

    /**
     * Handles {@link DialogCursorProtocol#SEARCH}. This is used to notify GlobalSearch
     * that a search was started without using a suggestion.
     */
    private Bundle respondSearch(Bundle request) {
        String query = request.getString(DialogCursorProtocol.SEARCH_SEND_QUERY);
        if (query == null) {
            Log.w(TAG, "Got " + DialogCursorProtocol.SEARCH + " without "
                    + DialogCursorProtocol.SEARCH_SEND_QUERY);
            return Bundle.EMPTY;
        }
        int maxDisplayed = request.getInt(DialogCursorProtocol.SEARCH_SEND_MAX_DISPLAY_POS, -1);
        if (DBG) Log.d(TAG, "respondSearch(), query=" + query + ", maxDisplayed=" + maxDisplayed);
        if (mListener != null) {
            List<SuggestionData> displayedSuggestions = getDisplayedSuggestions(maxDisplayed);
            mListener.onSearch(query, displayedSuggestions);
        }
        return Bundle.EMPTY;
    }

    @Override
    public void close() {
        if (DBG) Log.d(TAG, "close()");
        super.close();
        if (mListener != null) {
            mListener.onClose();
        }
    }

    @Override
    protected void finalize() {
        if (!mClosed) {
            Log.w(TAG, "SuggestionCursor finalized without being closed. Someone is leaking.");
            close();
        }
        super.finalize();
    }

    /**
     * We don't copy over a fresh copy of the data, instead, we notify the cursor that the
     * data has changed, and wait to for {@link #requery} to be called.  This way, any
     * adapter backed by this cursor will have a consistent view of the data, and {@link #requery}
     * us when ready.
     *
     * Calls {@link AbstractCursor#onChange} only if there isn't already one planned to be called
     * within {@link #CURSOR_NOTIFY_WINDOW_MS}.
     *
     * {@inheritDoc}
     */
    public synchronized void onNewResults() {
        if (DBG) Log.d(TAG, "onNewResults()");
        if (!isClosed()) {
            long now = SystemClock.uptimeMillis();
            if (now < mNextNotify) {
                if (DBG) Log.d(TAG, "-avoided a notify!");
                return;
            }
            mNextNotify = now + CURSOR_NOTIFY_WINDOW_MS;

            if (DBG) Log.d(TAG, "-posting onChange(false)");
            mDelayedExecutor.postAtTime(mNotifier, mNextNotify);
        }
    }

    private final Runnable mNotifier = new Runnable() {
        public void run() {
            SuggestionCursor.this.onChange(false);
        }
    };

    /**
     * Gets the current suggestion.
     */
    private SuggestionData get() {
        if (mPos < 0) {
            throw new CursorIndexOutOfBoundsException("Before first row.");
        }
        if (mPos >= mData.size()) {
            throw new CursorIndexOutOfBoundsException("After last row.");
        }

        SuggestionData suggestion = mData.get(mPos);
        if (DBG && SPEW) Log.d(TAG, "get(" + mPos + ")");
        if (DBG && SPEW) Log.d(TAG, suggestion.toString());
        return suggestion;
    }

    @Override
    public boolean requery() {
        if (mBacker != null) {
            mBacker.snapshotSuggestions(mData, mIncludeSources);
            if (DBG) Log.d(TAG, "requery(), now " + mData.size() + " items");
        }

        if (DUMP_SUGGESTIONS) {
            Log.d(TAG, "");
            Log.d(TAG, "");
            final int num = mData.size();
            for (int i = 0; i < num; i++) {
                final SuggestionData s = mData.get(i);
                Log.d(TAG, "/" + i + "---------\\");
                Log.d(TAG, "- " + s.getSource().getShortClassName());
                Log.d(TAG, "- " + s.getTitle());
                Log.d(TAG, "- " + s.getDescription());
                Log.d(TAG, "- " + s.getIntentAction());
                Log.d(TAG, "- " + s.getIntentData());
                Log.d(TAG, "\\---------/");
            }
        }

        return super.requery();
    }

    @Override
    public double getDouble(int column) {
        return Double.valueOf(getString(column));
    }

    @Override
    public float getFloat(int column) {
        return Float.valueOf(getString(column));
    }

    @Override
    public int getInt(int column) {
        return Integer.valueOf(getString(column));
    }

    @Override
    public long getLong(int column) {
        return Long.valueOf(getString(column));
    }

    @Override
    public short getShort(int column) {
        return Short.valueOf(getString(column));
    }


    @Override
    public String getString(int columnIndex) {
        if (DBG && SPEW) Log.d(TAG, "getString(columnIndex=" + columnIndex + ")");
        return (String) getColumnValue(get(), columnIndex);
    }

    private Object getColumnValue(SuggestionData suggestion, int columnIndex) {
        switch(columnIndex) {
            case _ID: return Integer.toString(mPos);
            case FORMAT: return suggestion.getFormat();
            case TEXT_1: return suggestion.getTitle();
            case TEXT_2: return suggestion.getDescription();
            case ICON_1: return suggestion.getIcon1();
            case ICON_2: return suggestion.getIcon2();
            case QUERY: return suggestion.getIntentQuery();
            case INTENT_ACTION: return suggestion.getIntentAction();
            case INTENT_DATA: return suggestion.getIntentData();
            case ACTION_MSG_CALL: return suggestion.getActionMsgCall();
            case INTENT_EXTRA_DATA: return suggestion.getIntentExtraData();
            case INTENT_COMPONENT_NAME: return suggestion.getIntentComponentName();
            case SHORTCUT_ID: return suggestion.getShortcutId();
            case BACKGROUND_COLOR: return Integer.toString(suggestion.getBackgroundColor());
            default:
                throw new RuntimeException("we musta forgot about one of the columns :-/");
        }
    }

    @Override
    public boolean isNull(int column) {
        return getString(column) == null;
    }

    /**
     * Sets the listener which will be notified if the "more results" entry is shown, and when
     * the cursor has been closed.
     *
     * @param listener The listener. May be <code>null</code> to remove
     * the current listener.
     */
    public void setListener(CursorListener listener) {
        mListener = listener;
    }
}
