/*
 * Copyright (C) 2012 Google Inc.
 * Licensed to 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.mail.ui;

import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.text.BidiFormatter;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView.OnScrollListener;
import android.widget.SimpleCursorAdapter;

import com.android.bitmap.AltBitmapCache;
import com.android.bitmap.BitmapCache;
import com.android.bitmap.DecodeAggregator;
import com.android.mail.R;
import com.android.mail.analytics.Analytics;
import com.android.mail.bitmap.ContactResolver;
import com.android.mail.browse.ConversationCursor;
import com.android.mail.browse.ConversationItemView;
import com.android.mail.browse.ConversationItemViewCoordinates.CoordinatesCache;
import com.android.mail.browse.SwipeableConversationItemView;
import com.android.mail.preferences.MailPrefs;
import com.android.mail.providers.Account;
import com.android.mail.providers.AccountObserver;
import com.android.mail.providers.Conversation;
import com.android.mail.providers.Folder;
import com.android.mail.providers.UIProvider;
import com.android.mail.providers.UIProvider.ConversationListIcon;
import com.android.mail.ui.SwipeableListView.ListItemsRemovedListener;
import com.android.mail.utils.LogTag;
import com.android.mail.utils.LogUtils;
import com.android.mail.utils.Utils;
import com.google.common.collect.Maps;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

public class AnimatedAdapter extends SimpleCursorAdapter {
    private static int sDismissAllShortDelay = -1;
    private static int sDismissAllLongDelay = -1;
    private static final String LAST_DELETING_ITEMS = "last_deleting_items";
    private static final String LEAVE_BEHIND_ITEM_DATA = "leave_behind_item_data";
    private static final String LEAVE_BEHIND_ITEM_ID = "leave_behind_item_id";
    private final static int TYPE_VIEW_CONVERSATION = 0;
    private final static int TYPE_VIEW_FOOTER = 1;
    private final static int TYPE_VIEW_DONT_RECYCLE = -1;
    private final HashSet<Long> mDeletingItems = new HashSet<Long>();
    private final ArrayList<Long> mLastDeletingItems = new ArrayList<Long>();
    private final HashSet<Long> mUndoingItems = new HashSet<Long>();
    private final HashSet<Long> mSwipeDeletingItems = new HashSet<Long>();
    private final HashSet<Long> mSwipeUndoingItems = new HashSet<Long>();
    private final HashMap<Long, SwipeableConversationItemView> mAnimatingViews =
            new HashMap<Long, SwipeableConversationItemView>();
    private final HashMap<Long, LeaveBehindItem> mFadeLeaveBehindItems =
            new HashMap<Long, LeaveBehindItem>();
    /** The current account */
    private Account mAccount;
    private final Context mContext;
    private final ConversationSelectionSet mBatchConversations;
    private Runnable mCountDown;
    private final Handler mHandler;
    protected long mLastLeaveBehind = -1;

    private final AnimatorListener mAnimatorListener = new AnimatorListenerAdapter() {

        @Override
        public void onAnimationStart(Animator animation) {
            if (!mUndoingItems.isEmpty()) {
                mDeletingItems.clear();
                mLastDeletingItems.clear();
                mSwipeDeletingItems.clear();
            }
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            Object obj;
            if (animation instanceof AnimatorSet) {
                AnimatorSet set = (AnimatorSet) animation;
                obj = ((ObjectAnimator) set.getChildAnimations().get(0)).getTarget();
            } else {
                obj = ((ObjectAnimator) animation).getTarget();
            }
            updateAnimatingConversationItems(obj, mSwipeDeletingItems);
            updateAnimatingConversationItems(obj, mDeletingItems);
            updateAnimatingConversationItems(obj, mSwipeUndoingItems);
            updateAnimatingConversationItems(obj, mUndoingItems);
            if (hasFadeLeaveBehinds() && obj instanceof LeaveBehindItem) {
                LeaveBehindItem objItem = (LeaveBehindItem) obj;
                clearLeaveBehind(objItem.getConversationId());
                objItem.commit();
                if (!hasFadeLeaveBehinds()) {
                    // Cancel any existing animations on the remaining leave behind
                    // item and start fading in text immediately.
                    LeaveBehindItem item = getLastLeaveBehindItem();
                    if (item != null) {
                        boolean cancelled = item.cancelFadeInTextAnimationIfNotStarted();
                        if (cancelled) {
                            item.startFadeInTextAnimation(0 /* delay start */);
                        }
                    }
                }
                // The view types have changed, since the animating views are gone.
                notifyDataSetChanged();
            }

            if (!isAnimating()) {
                mActivity.onAnimationEnd(AnimatedAdapter.this);
            }
        }

    };

    /**
     * The next action to perform. Do not read or write this. All accesses should
     * be in {@link #performAndSetNextAction(SwipeableListView.ListItemsRemovedListener)} which
     * commits the previous action, if any.
     */
    private ListItemsRemovedListener mPendingDestruction;

    /**
     * A destructive action that refreshes the list and performs no other action.
     */
    private final ListItemsRemovedListener mRefreshAction = new ListItemsRemovedListener() {
        @Override
        public void onListItemsRemoved() {
            notifyDataSetChanged();
        }
    };

    public interface Listener {
        void onAnimationEnd(AnimatedAdapter adapter);
    }

    private View mFooter;
    private boolean mShowFooter;
    private Folder mFolder;
    private final SwipeableListView mListView;
    private boolean mSwipeEnabled;
    private final HashMap<Long, LeaveBehindItem> mLeaveBehindItems = Maps.newHashMap();
    /** True if priority inbox markers are enabled, false otherwise. */
    private boolean mPriorityMarkersEnabled;
    private final ControllableActivity mActivity;
    private final AccountObserver mAccountListener = new AccountObserver() {
        @Override
        public void onChanged(Account newAccount) {
            if (setAccount(newAccount)) {
                notifyDataSetChanged();
            }
        }
    };

    /**
     * A list of all views that are not conversations. These include temporary views from
     * {@link #mFleetingViews}.
     */
    private final SparseArray<ConversationSpecialItemView> mSpecialViews;

    private final CoordinatesCache mCoordinatesCache = new CoordinatesCache();

    /**
     * Temporary views insert at specific positions relative to conversations. These can be
     * related to showing new features (on-boarding) or showing information about new mailboxes
     * that have been added by the system.
     */
    private final List<ConversationSpecialItemView> mFleetingViews;

    private final BidiFormatter mBidiFormatter = BidiFormatter.getInstance();

    /**
     * @return <code>true</code> if a relevant part of the account has changed, <code>false</code>
     *         otherwise
     */
    private boolean setAccount(Account newAccount) {
        final boolean accountChanged;
        if (mAccount != null && mAccount.uri.equals(newAccount.uri)
                && mAccount.settings.priorityArrowsEnabled ==
                        newAccount.settings.priorityArrowsEnabled
                && mAccount.supportsCapability(UIProvider.AccountCapabilities.UNDO) ==
                        newAccount.supportsCapability(UIProvider.AccountCapabilities.UNDO)
                && mAccount.settings.convListIcon == newAccount.settings.convListIcon
                && mAccount.settings.convListAttachmentPreviews ==
                        newAccount.settings.convListAttachmentPreviews) {
            accountChanged = false;
        } else {
            accountChanged = true;
        }

        mAccount = newAccount;
        mPriorityMarkersEnabled = mAccount.settings.priorityArrowsEnabled;
        mSwipeEnabled = mAccount.supportsCapability(UIProvider.AccountCapabilities.UNDO);

        Analytics.getInstance().setCustomDimension(Analytics.CD_INDEX_SENDER_IMAGES_ENABLED, Boolean
                .toString(newAccount.settings.convListIcon == ConversationListIcon.SENDER_IMAGE));
        Analytics.getInstance().setCustomDimension(Analytics.CD_INDEX_ATTACHMENT_PREVIEWS_ENABLED,
                Boolean.toString(newAccount.settings.convListAttachmentPreviews));
        Analytics.getInstance().setCustomDimension(Analytics.CD_INDEX_REPLY_ALL_SETTING,
                (newAccount.settings.replyBehavior == UIProvider.DefaultReplyBehavior.REPLY)
                ? "reply"
                : "reply_all");
        Analytics.getInstance().setCustomDimension(Analytics.CD_INDEX_AUTO_ADVANCE,
                UIProvider.AutoAdvance.getAutoAdvanceStr(
                        newAccount.settings.getAutoAdvanceSetting()));

        return accountChanged;
    }

    private static final String LOG_TAG = LogTag.getLogTag();
    private static final int INCREASE_WAIT_COUNT = 2;

    private final BitmapCache mAttachmentPreviewsCache;
    private final DecodeAggregator mAttachmentPreviewsDecodeAggregator;
    private final BitmapCache mSendersImagesCache;
    private final ContactResolver mContactResolver;

    private static final int ATTACHMENT_PREVIEWS_CACHE_TARGET_SIZE_BYTES = 0; // TODO: enable cache
    /** 339KB cache fits 10 bitmaps at 33856 bytes each. */
    private static final int SENDERS_IMAGES_CACHE_TARGET_SIZE_BYTES = 1024 * 339;
    /**
     * This is the fractional portion of the total cache size above that's dedicated to non-pooled
     * bitmaps. (This is basically the portion of cache dedicated to GIFs.)
     */
    private static final float ATTACHMENT_PREVIEWS_CACHE_NON_POOLED_FRACTION = 0.1f;
    private static final float SENDERS_IMAGES_PREVIEWS_CACHE_NON_POOLED_FRACTION = 0f;
    /** Each string has upper estimate of 50 bytes, so this cache would be 5KB. */
    private static final int SENDERS_IMAGES_PREVIEWS_CACHE_NULL_CAPACITY = 100;

    public AnimatedAdapter(Context context, ConversationCursor cursor,
            ConversationSelectionSet batch, ControllableActivity activity,
            SwipeableListView listView, final List<ConversationSpecialItemView> specialViews) {
        super(context, -1, cursor, UIProvider.CONVERSATION_PROJECTION, null, 0);
        mContext = context;
        mBatchConversations = batch;
        setAccount(mAccountListener.initialize(activity.getAccountController()));
        mActivity = activity;
        mShowFooter = false;
        mListView = listView;

        mAttachmentPreviewsCache = new AltBitmapCache(ATTACHMENT_PREVIEWS_CACHE_TARGET_SIZE_BYTES,
                ATTACHMENT_PREVIEWS_CACHE_NON_POOLED_FRACTION, 0);
        mAttachmentPreviewsDecodeAggregator = new DecodeAggregator();
        mSendersImagesCache = new AltBitmapCache(Utils.isLowRamDevice(mContext) ?
                0 : SENDERS_IMAGES_CACHE_TARGET_SIZE_BYTES,
                SENDERS_IMAGES_PREVIEWS_CACHE_NON_POOLED_FRACTION,
                SENDERS_IMAGES_PREVIEWS_CACHE_NULL_CAPACITY);
        mContactResolver = new ContactResolver(mContext.getContentResolver(), mSendersImagesCache);

        mHandler = new Handler();
        if (sDismissAllShortDelay == -1) {
            final Resources r = context.getResources();
            sDismissAllShortDelay = r.getInteger(R.integer.dismiss_all_leavebehinds_short_delay);
            sDismissAllLongDelay = r.getInteger(R.integer.dismiss_all_leavebehinds_long_delay);
        }
        if (specialViews != null) {
            mFleetingViews = new ArrayList<ConversationSpecialItemView>(specialViews);
        } else {
            mFleetingViews = new ArrayList<ConversationSpecialItemView>(0);
        }
        /** Total number of special views */
        final int size = mFleetingViews.size();
        mSpecialViews = new SparseArray<ConversationSpecialItemView>(size);

        // Set the adapter in teaser views.
        for (final ConversationSpecialItemView view : mFleetingViews) {
            view.setAdapter(this);
        }
        updateSpecialViews();
    }

    public void cancelDismissCounter() {
        cancelLeaveBehindFadeInAnimation();
        mHandler.removeCallbacks(mCountDown);
    }

    public void startDismissCounter() {
        if (mLeaveBehindItems.size() > INCREASE_WAIT_COUNT) {
            mHandler.postDelayed(mCountDown, sDismissAllLongDelay);
        } else {
            mHandler.postDelayed(mCountDown, sDismissAllShortDelay);
        }
    }

    public final void destroy() {
        // Set a null cursor in the adapter
        swapCursor(null);
        mAccountListener.unregisterAndDestroy();
    }

    @Override
    public int getCount() {
        // mSpecialViews only contains the views that are currently being displayed
        final int specialViewCount = mSpecialViews.size();

        final int count = super.getCount() + specialViewCount;
        return mShowFooter ? count + 1 : count;
    }

    /**
     * Add a conversation to the undo set, but only if its deletion is still cached. If the
     * deletion has already been written through and the cursor doesn't have it anymore, we can't
     * handle it here, and should instead rely on the cursor refresh to restore the item.
     * @param item id for the conversation that is being undeleted.
     * @return true if the conversation is still cached and therefore we will handle the undo.
     */
    private boolean addUndoingItem(final long item) {
        if (getConversationCursor().getUnderlyingPosition(item) >= 0) {
            mUndoingItems.add(item);
            return true;
        }
        return false;
    }

    public void setUndo(boolean undo) {
        if (undo) {
            boolean itemAdded = false;
            if (!mLastDeletingItems.isEmpty()) {
                for (Long item : mLastDeletingItems) {
                    itemAdded |= addUndoingItem(item);
                }
                mLastDeletingItems.clear();
            }
            if (mLastLeaveBehind != -1) {
                itemAdded |= addUndoingItem(mLastLeaveBehind);
                mLastLeaveBehind = -1;
            }
            // Start animation, only if we're handling the undo.
            if (itemAdded) {
                notifyDataSetChanged();
                performAndSetNextAction(mRefreshAction);
            }
        }
    }

    public void setSwipeUndo(boolean undo) {
        if (undo) {
            if (!mLastDeletingItems.isEmpty()) {
                mSwipeUndoingItems.addAll(mLastDeletingItems);
                mLastDeletingItems.clear();
            }
            if (mLastLeaveBehind != -1) {
                mSwipeUndoingItems.add(mLastLeaveBehind);
                mLastLeaveBehind = -1;
            }
            // Start animation
            notifyDataSetChanged();
            performAndSetNextAction(mRefreshAction);
        }
    }

    public View createConversationItemView(SwipeableConversationItemView view, Context context,
            Conversation conv) {
        if (view == null) {
            view = new SwipeableConversationItemView(context, mAccount.name);
        }
        view.bind(conv, mActivity, mBatchConversations, mFolder, getCheckboxSetting(),
                getAttachmentPreviewsSetting(), getParallaxSpeedAlternativeSetting(),
                getParallaxDirectionAlternativeSetting(), mSwipeEnabled, mPriorityMarkersEnabled,
                this);
        return view;
    }

    @Override
    public boolean hasStableIds() {
        return true;
    }

    @Override
    public int getViewTypeCount() {
        // TYPE_VIEW_CONVERSATION, TYPE_VIEW_DELETING, TYPE_VIEW_UNDOING, and
        // TYPE_VIEW_FOOTER, TYPE_VIEW_LEAVEBEHIND.
        return 5;
    }

    @Override
    public int getItemViewType(int position) {
        // Try to recycle views.
        if (mShowFooter && position == getCount() - 1) {
            return TYPE_VIEW_FOOTER;
        } else if (hasLeaveBehinds() || isAnimating()) {
            // Setting as type -1 means the recycler won't take this view and
            // return it in get view. This is a bit of a "hammer" in that it
            // won't let even safe views be recycled here,
            // but its safer and cheaper than trying to determine individual
            // types. In a future release, use position/id map to try to make
            // this cleaner / faster to determine if the view is animating.
            return TYPE_VIEW_DONT_RECYCLE;
        } else if (mSpecialViews.get(position) != null) {
            // Don't recycle the special views
            return TYPE_VIEW_DONT_RECYCLE;
        }
        return TYPE_VIEW_CONVERSATION;
    }

    /**
     * Deletes the selected conversations from the conversation list view with a
     * translation and then a shrink. These conversations <b>must</b> have their
     * {@link Conversation#position} set to the position of these conversations
     * among the list. This will only remove the element from the list. The job
     * of deleting the actual element is left to the the listener. This listener
     * will be called when the animations are complete and is required to delete
     * the conversation.
     * @param conversations
     * @param listener
     */
    public void swipeDelete(Collection<Conversation> conversations,
            ListItemsRemovedListener listener) {
        delete(conversations, listener, mSwipeDeletingItems);
    }


    /**
     * Deletes the selected conversations from the conversation list view by
     * shrinking them away. These conversations <b>must</b> have their
     * {@link Conversation#position} set to the position of these conversations
     * among the list. This will only remove the element from the list. The job
     * of deleting the actual element is left to the the listener. This listener
     * will be called when the animations are complete and is required to delete
     * the conversation.
     * @param conversations
     * @param listener
     */
    public void delete(Collection<Conversation> conversations, ListItemsRemovedListener listener) {
        delete(conversations, listener, mDeletingItems);
    }

    private void delete(Collection<Conversation> conversations, ListItemsRemovedListener listener,
            HashSet<Long> list) {
        // Clear out any remaining items and add the new ones
        mLastDeletingItems.clear();
        // Since we are deleting new items, clear any remaining undo items
        mUndoingItems.clear();

        final int startPosition = mListView.getFirstVisiblePosition();
        final int endPosition = mListView.getLastVisiblePosition();

        // Only animate visible items
        for (Conversation c: conversations) {
            if (c.position >= startPosition && c.position <= endPosition) {
                mLastDeletingItems.add(c.id);
                list.add(c.id);
            }
        }

        if (list.isEmpty()) {
            // If we have no deleted items on screen, skip the animation
            listener.onListItemsRemoved();
            // If we have an action queued up, perform it
            performAndSetNextAction(null);
        } else {
            performAndSetNextAction(listener);
        }
        notifyDataSetChanged();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (mShowFooter && position == getCount() - 1) {
            return mFooter;
        }

        // Check if this is a special view
        final ConversationSpecialItemView specialView = mSpecialViews.get(position);
        if (specialView != null) {
            specialView.onGetView();
            return (View) specialView;
        }

        Utils.traceBeginSection("AA.getView");

        final ConversationCursor cursor = (ConversationCursor) getItem(position);
        final Conversation conv = cursor.getConversation();

        // Notify the provider of this change in the position of Conversation cursor
        cursor.notifyUIPositionChange();

        if (isPositionUndoing(conv.id)) {
            return getUndoingView(position - getPositionOffset(position), conv, parent,
                    false /* don't show swipe background */);
        } if (isPositionUndoingSwipe(conv.id)) {
            return getUndoingView(position - getPositionOffset(position), conv, parent,
                    true /* show swipe background */);
        } else if (isPositionDeleting(conv.id)) {
            return getDeletingView(position - getPositionOffset(position), conv, parent, false);
        } else if (isPositionSwipeDeleting(conv.id)) {
            return getDeletingView(position - getPositionOffset(position), conv, parent, true);
        }
        if (hasFadeLeaveBehinds()) {
            if(isPositionFadeLeaveBehind(conv)) {
                LeaveBehindItem fade  = getFadeLeaveBehindItem(position, conv);
                fade.startShrinkAnimation(mAnimatorListener);
                Utils.traceEndSection();
                return fade;
            }
        }
        if (hasLeaveBehinds()) {
            if (isPositionLeaveBehind(conv)) {
                final LeaveBehindItem fadeIn = getLeaveBehindItem(conv);
                if (conv.id == mLastLeaveBehind) {
                    // If it looks like the person is doing a lot of rapid
                    // swipes, wait patiently before animating
                    if (mLeaveBehindItems.size() > INCREASE_WAIT_COUNT) {
                        if (fadeIn.isAnimating()) {
                            fadeIn.increaseFadeInDelay(sDismissAllLongDelay);
                        } else {
                            fadeIn.startFadeInTextAnimation(sDismissAllLongDelay);
                        }
                    } else {
                        // Otherwise, assume they are just doing 1 and wait less time
                        fadeIn.startFadeInTextAnimation(sDismissAllShortDelay /* delay start */);
                    }
                }
                Utils.traceEndSection();
                return fadeIn;
            }
        }

        if (convertView != null && !(convertView instanceof SwipeableConversationItemView)) {
            LogUtils.w(LOG_TAG, "Incorrect convert view received; nulling it out");
            convertView = newView(mContext, cursor, parent);
        } else if (convertView != null) {
            ((SwipeableConversationItemView) convertView).reset();
        }
        final View v = createConversationItemView((SwipeableConversationItemView) convertView,
                mContext, conv);
        Utils.traceEndSection();
        return v;
    }

    private boolean hasLeaveBehinds() {
        return !mLeaveBehindItems.isEmpty();
    }

    private boolean hasFadeLeaveBehinds() {
        return !mFadeLeaveBehindItems.isEmpty();
    }

    public LeaveBehindItem setupLeaveBehind(Conversation target, ToastBarOperation undoOp,
            int deletedRow, int viewHeight) {
        cancelLeaveBehindFadeInAnimation();
        mLastLeaveBehind = target.id;
        fadeOutLeaveBehindItems();

        final LeaveBehindItem leaveBehind = (LeaveBehindItem) LayoutInflater.from(mContext)
                .inflate(R.layout.swipe_leavebehind, mListView, false);
        leaveBehind.bind(deletedRow, mAccount, this, undoOp, target, mFolder, viewHeight);
        mLeaveBehindItems.put(target.id, leaveBehind);
        mLastDeletingItems.add(target.id);
        return leaveBehind;
    }

    public void fadeOutSpecificLeaveBehindItem(long id) {
        if (mLastLeaveBehind == id) {
            mLastLeaveBehind = -1;
        }
        startFadeOutLeaveBehindItemsAnimations();
    }

    // This should kick off a timer such that there is a minimum time each item
    // shows up before being dismissed. That way if the user is swiping away
    // items in rapid succession, their finger position is maintained.
    public void fadeOutLeaveBehindItems() {
        if (mCountDown == null) {
            mCountDown = new Runnable() {
                @Override
                public void run() {
                    startFadeOutLeaveBehindItemsAnimations();
                }
            };
        } else {
            mHandler.removeCallbacks(mCountDown);
        }
        // Clear all the text since these are no longer clickable
        Iterator<Entry<Long, LeaveBehindItem>> i = mLeaveBehindItems.entrySet().iterator();
        LeaveBehindItem item;
        while (i.hasNext()) {
            item = i.next().getValue();
            Conversation conv = item.getData();
            if (mLastLeaveBehind == -1 || conv.id != mLastLeaveBehind) {
                item.cancelFadeInTextAnimation();
                item.makeInert();
            }
        }
        startDismissCounter();
    }

    protected void startFadeOutLeaveBehindItemsAnimations() {
        final int startPosition = mListView.getFirstVisiblePosition();
        final int endPosition = mListView.getLastVisiblePosition();

        if (hasLeaveBehinds()) {
            // If the item is visible, fade it out. Otherwise, just remove
            // it.
            Iterator<Entry<Long, LeaveBehindItem>> i = mLeaveBehindItems.entrySet().iterator();
            LeaveBehindItem item;
            while (i.hasNext()) {
                item = i.next().getValue();
                Conversation conv = item.getData();
                if (mLastLeaveBehind == -1 || conv.id != mLastLeaveBehind) {
                    if (conv.position >= startPosition && conv.position <= endPosition) {
                        mFadeLeaveBehindItems.put(conv.id, item);
                    } else {
                        item.commit();
                    }
                    i.remove();
                }
            }
            cancelLeaveBehindFadeInAnimation();
        }
        if (!mLastDeletingItems.isEmpty()) {
            mLastDeletingItems.clear();
        }
        notifyDataSetChanged();
    }

    private void cancelLeaveBehindFadeInAnimation() {
        LeaveBehindItem leaveBehind = getLastLeaveBehindItem();
        if (leaveBehind != null) {
            leaveBehind.cancelFadeInTextAnimation();
        }
    }

    public CoordinatesCache getCoordinatesCache() {
        return mCoordinatesCache;
    }

    public BidiFormatter getBidiFormatter() {
        return mBidiFormatter;
    }

    public SwipeableListView getListView() {
        return mListView;
    }

    public void commitLeaveBehindItems(boolean animate) {
        // Remove any previously existing leave behinds.
        boolean changed = false;
        if (hasLeaveBehinds()) {
            for (LeaveBehindItem item : mLeaveBehindItems.values()) {
                if (animate) {
                    mFadeLeaveBehindItems.put(item.getConversationId(), item);
                } else {
                    item.commit();
                }
            }
            changed = true;
            mLastLeaveBehind = -1;
            mLeaveBehindItems.clear();
        }
        if (hasFadeLeaveBehinds() && !animate) {
            // Find any fading leave behind items and commit them all, too.
            for (LeaveBehindItem item : mFadeLeaveBehindItems.values()) {
                item.commit();
            }
            mFadeLeaveBehindItems.clear();
            changed = true;
        }
        if (!mLastDeletingItems.isEmpty()) {
            mLastDeletingItems.clear();
            changed = true;
        }

        for (final ConversationSpecialItemView view : mFleetingViews) {
            if (view.commitLeaveBehindItem()) {
                changed = true;
            }
        }

        if (changed) {
            notifyDataSetChanged();
        }
    }

    private LeaveBehindItem getLeaveBehindItem(Conversation target) {
        return mLeaveBehindItems.get(target.id);
    }

    private LeaveBehindItem getFadeLeaveBehindItem(int position, Conversation target) {
        return mFadeLeaveBehindItems.get(target.id);
    }

    @Override
    public long getItemId(int position) {
        if (mShowFooter && position == getCount() - 1) {
            return -1;
        }

        final ConversationSpecialItemView specialView = mSpecialViews.get(position);
        if (specialView != null) {
            // TODO(skennedy) We probably want something better than this
            return specialView.hashCode();
        }

        final int cursorPos = position - getPositionOffset(position);
        // advance the cursor to the right position and read the cached conversation, if present
        //
        // (no need to have CursorAdapter check mDataValid because in our incarnation without
        // FLAG_REGISTER_CONTENT_OBSERVER, mDataValid is effectively identical to mCursor being
        // non-null)
        final ConversationCursor cursor = getConversationCursor();
        if (cursor != null && cursor.moveToPosition(cursorPos)) {
            final Conversation conv = cursor.getCachedConversation();
            if (conv != null) {
                return conv.id;
            }
        }
        return super.getItemId(cursorPos);
    }

    /**
     * @param position The position in the cursor
     */
    private View getDeletingView(int position, Conversation conversation, ViewGroup parent,
            boolean swipe) {
        conversation.position = position;
        SwipeableConversationItemView deletingView = mAnimatingViews.get(conversation.id);
        if (deletingView == null) {
            // The undo animation consists of fading in the conversation that
            // had been destroyed.
            deletingView = newConversationItemView(position, parent, conversation);
            deletingView.startDeleteAnimation(mAnimatorListener, swipe);
        }
        return deletingView;
    }

    /**
     * @param position The position in the cursor
     */
    private View getUndoingView(int position, Conversation conv, ViewGroup parent, boolean swipe) {
        conv.position = position;
        SwipeableConversationItemView undoView = mAnimatingViews.get(conv.id);
        if (undoView == null) {
            // The undo animation consists of fading in the conversation that
            // had been destroyed.
            undoView = newConversationItemView(position, parent, conv);
            undoView.startUndoAnimation(mAnimatorListener, swipe);
        }
        return undoView;
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        return new SwipeableConversationItemView(context, mAccount.name);
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        // no-op. we only get here from newConversationItemView(), which will immediately bind
        // on its own.
    }

    private SwipeableConversationItemView newConversationItemView(int position, ViewGroup parent,
            Conversation conversation) {
        SwipeableConversationItemView view = (SwipeableConversationItemView) super.getView(
                position, null, parent);
        view.reset();
        view.bind(conversation, mActivity, mBatchConversations, mFolder, getCheckboxSetting(),
                getAttachmentPreviewsSetting(), getParallaxSpeedAlternativeSetting(),
                getParallaxDirectionAlternativeSetting(), mSwipeEnabled, mPriorityMarkersEnabled,
                this);
        mAnimatingViews.put(conversation.id, view);
        return view;
    }

    private int getCheckboxSetting() {
        return mAccount != null ? mAccount.settings.convListIcon :
            ConversationListIcon.DEFAULT;
    }

    private boolean getAttachmentPreviewsSetting() {
        return mAccount == null || mAccount.settings.convListAttachmentPreviews;
    }

    private boolean getParallaxSpeedAlternativeSetting() {
        return MailPrefs.get(mContext).getParallaxSpeedAlternative();
    }

    private boolean getParallaxDirectionAlternativeSetting() {
        return MailPrefs.get(mContext).getParallaxDirectionAlternative();
    }

    @Override
    public Object getItem(int position) {
        if (mShowFooter && position == getCount() - 1) {
            return mFooter;
        } else if (mSpecialViews.get(position) != null) {
            return mSpecialViews.get(position);
        }
        return super.getItem(position - getPositionOffset(position));
    }

    private boolean isPositionDeleting(long id) {
        return mDeletingItems.contains(id);
    }

    private boolean isPositionSwipeDeleting(long id) {
        return mSwipeDeletingItems.contains(id);
    }

    private boolean isPositionUndoing(long id) {
        return mUndoingItems.contains(id);
    }

    private boolean isPositionUndoingSwipe(long id) {
        return mSwipeUndoingItems.contains(id);
    }

    private boolean isPositionLeaveBehind(Conversation conv) {
        return hasLeaveBehinds()
                && mLeaveBehindItems.containsKey(conv.id)
                && conv.isMostlyDead();
    }

    private boolean isPositionFadeLeaveBehind(Conversation conv) {
        return hasFadeLeaveBehinds()
                && mFadeLeaveBehindItems.containsKey(conv.id)
                && conv.isMostlyDead();
    }

    /**
     * Performs the pending destruction, if any and assigns the next pending action.
     * @param next The next action that is to be performed, possibly null (if no next action is
     * needed).
     */
    private void performAndSetNextAction(ListItemsRemovedListener next) {
        if (mPendingDestruction != null) {
            mPendingDestruction.onListItemsRemoved();
        }
        mPendingDestruction = next;
    }

    private void updateAnimatingConversationItems(Object obj, HashSet<Long> items) {
        if (!items.isEmpty()) {
            if (obj instanceof ConversationItemView) {
                final ConversationItemView target = (ConversationItemView) obj;
                final long id = target.getConversation().id;
                items.remove(id);
                mAnimatingViews.remove(id);
                if (items.isEmpty()) {
                    performAndSetNextAction(null);
                    notifyDataSetChanged();
                }
            }
        }
    }

    @Override
    public boolean areAllItemsEnabled() {
        // The animating items and some special views are not enabled.
        return false;
    }

    @Override
    public boolean isEnabled(final int position) {
        final ConversationSpecialItemView view = mSpecialViews.get(position);
        if (view != null) {
            final boolean enabled = view.acceptsUserTaps();
            LogUtils.d(LOG_TAG, "AA.isEnabled(%d) = %b", position, enabled);
            return enabled;
        }
        return !isPositionDeleting(position) && !isPositionUndoing(position);
    }

    public void setFooterVisibility(boolean show) {
        if (mShowFooter != show) {
            mShowFooter = show;
            notifyDataSetChanged();
        }
    }

    public void addFooter(View footerView) {
        mFooter = footerView;
    }

    public void setFolder(Folder folder) {
        mFolder = folder;
    }

    public void clearLeaveBehind(long itemId) {
        if (hasLeaveBehinds() && mLeaveBehindItems.containsKey(itemId)) {
            mLeaveBehindItems.remove(itemId);
        } else if (hasFadeLeaveBehinds()) {
            mFadeLeaveBehindItems.remove(itemId);
        } else {
            LogUtils.d(LOG_TAG, "Trying to clear a non-existant leave behind");
        }
        if (mLastLeaveBehind == itemId) {
            mLastLeaveBehind = -1;
        }
    }

    public void onSaveInstanceState(Bundle outState) {
        long[] lastDeleting = new long[mLastDeletingItems.size()];
        for (int i = 0; i < lastDeleting.length; i++) {
            lastDeleting[i] = mLastDeletingItems.get(i);
        }
        outState.putLongArray(LAST_DELETING_ITEMS, lastDeleting);
        if (hasLeaveBehinds()) {
            if (mLastLeaveBehind != -1) {
                outState.putParcelable(LEAVE_BEHIND_ITEM_DATA,
                        mLeaveBehindItems.get(mLastLeaveBehind).getLeaveBehindData());
                outState.putLong(LEAVE_BEHIND_ITEM_ID, mLastLeaveBehind);
            }
            for (LeaveBehindItem item : mLeaveBehindItems.values()) {
                if (mLastLeaveBehind == -1 || item.getData().id != mLastLeaveBehind) {
                    item.commit();
                }
            }
        }
    }

    public void onRestoreInstanceState(Bundle outState) {
        if (outState.containsKey(LAST_DELETING_ITEMS)) {
            final long[] lastDeleting = outState.getLongArray(LAST_DELETING_ITEMS);
            for (final long aLastDeleting : lastDeleting) {
                mLastDeletingItems.add(aLastDeleting);
            }
        }
        if (outState.containsKey(LEAVE_BEHIND_ITEM_DATA)) {
            LeaveBehindData left =
                    (LeaveBehindData) outState.getParcelable(LEAVE_BEHIND_ITEM_DATA);
            mLeaveBehindItems.put(outState.getLong(LEAVE_BEHIND_ITEM_ID),
                    setupLeaveBehind(left.data, left.op, left.data.position, left.height));
        }
    }

    /**
     * Return if the adapter is in the process of animating anything.
     */
    public boolean isAnimating() {
        return !mUndoingItems.isEmpty()
                || !mSwipeUndoingItems.isEmpty()
                || hasFadeLeaveBehinds()
                || !mDeletingItems.isEmpty()
                || !mSwipeDeletingItems.isEmpty();
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("{");
        sb.append(super.toString());
        sb.append(" mUndoingItems=");
        sb.append(mUndoingItems);
        sb.append(" mSwipeUndoingItems=");
        sb.append(mSwipeUndoingItems);
        sb.append(" mDeletingItems=");
        sb.append(mDeletingItems);
        sb.append(" mSwipeDeletingItems=");
        sb.append(mSwipeDeletingItems);
        sb.append(" mLeaveBehindItems=");
        sb.append(mLeaveBehindItems);
        sb.append(" mFadeLeaveBehindItems=");
        sb.append(mFadeLeaveBehindItems);
        sb.append(" mLastDeletingItems=");
        sb.append(mLastDeletingItems);
        sb.append("}");
        return sb.toString();
    }

    /**
     * Get the ConversationCursor associated with this adapter.
     */
    public ConversationCursor getConversationCursor() {
        return (ConversationCursor) getCursor();
    }

    /**
     * Get the currently visible leave behind item.
     */
    public LeaveBehindItem getLastLeaveBehindItem() {
        if (mLastLeaveBehind != -1) {
            return mLeaveBehindItems.get(mLastLeaveBehind);
        }
        return null;
    }

    /**
     * Cancel fading out the text displayed in the leave behind item currently
     * shown.
     */
    public void cancelFadeOutLastLeaveBehindItemText() {
        LeaveBehindItem item = getLastLeaveBehindItem();
        if (item != null) {
            item.cancelFadeOutText();
        }
    }

    /**
     * Updates special (non-conversation view) when {@link #mFleetingViews} changed
     */
    private void updateSpecialViews() {
        // We recreate all the special views using mFleetingViews.
        mSpecialViews.clear();

        // Fleeting (temporary) views specify a position, which is 0-indexed and
        // has to be adjusted for the number of fleeting views above it.
        for (final ConversationSpecialItemView specialView : mFleetingViews) {
            specialView.onUpdate(mFolder, getConversationCursor());

            if (specialView.getShouldDisplayInList()) {
                // If the special view asks for position 0, it wants to be at the top.
                int position = (specialView.getPosition());

                // insert the special view into the position, but if there is
                // already an item occupying that position, move that item back
                // one position, and repeat
                ConversationSpecialItemView insert = specialView;
                while (insert != null) {
                    final ConversationSpecialItemView kickedOut = mSpecialViews.get(position);
                    mSpecialViews.put(position, insert);
                    insert = kickedOut;
                    position++;
                }
            }
        }
    }

    /**
     * Gets the position of the specified {@link ConversationSpecialItemView}, as determined by
     * the adapter.
     *
     * @return The position in the list, or a negative value if it could not be found
     */
    public int getSpecialViewPosition(final ConversationSpecialItemView view) {
        return mSpecialViews.indexOfValue(view);
    }

    @Override
    public void notifyDataSetChanged() {
        // This may be a temporary catch for a problem, or we may leave it here.
        // b/9527863
        if (Looper.getMainLooper() != Looper.myLooper()) {
            LogUtils.wtf(LOG_TAG, "notifyDataSetChanged() called off the main thread");
        }

        updateSpecialViews();
        super.notifyDataSetChanged();
    }

    @Override
    public void changeCursor(final Cursor cursor) {
        super.changeCursor(cursor);
        updateSpecialViews();
    }

    @Override
    public void changeCursorAndColumns(final Cursor c, final String[] from, final int[] to) {
        super.changeCursorAndColumns(c, from, to);
        updateSpecialViews();
    }

    @Override
    public Cursor swapCursor(final Cursor c) {
        final Cursor oldCursor = super.swapCursor(c);
        updateSpecialViews();

        return oldCursor;
    }

    public BitmapCache getAttachmentPreviewsCache() {
        return mAttachmentPreviewsCache;
    }

    public DecodeAggregator getAttachmentPreviewsDecodeAggregator() {
        return mAttachmentPreviewsDecodeAggregator;
    }

    public BitmapCache getSendersImagesCache() {
        return mSendersImagesCache;
    }

    public ContactResolver getContactResolver() {
        return mContactResolver;
    }

    /**
     * Gets the offset for the given position in the underlying cursor, based on any special views
     * that may be above it.
     */
    public int getPositionOffset(final int position) {
        int viewsAbove = 0;

        for (int i = 0, size = mSpecialViews.size(); i < size; i++) {
            final int bidPosition = mSpecialViews.keyAt(i);
            // If the view bid for a position above the cursor position,
            // it is above the conversation.
            if (bidPosition <= position) {
                viewsAbove++;
            }
        }

        return viewsAbove;
    }

    public void cleanup() {
        // Clean up teaser views.
        for (final ConversationSpecialItemView view : mFleetingViews) {
            view.cleanup();
        }
    }

    public void onConversationSelected() {
        // Notify teaser views.
        for (final ConversationSpecialItemView specialView : mFleetingViews) {
            specialView.onConversationSelected();
        }
    }

    public void onCabModeEntered() {
        for (final ConversationSpecialItemView specialView : mFleetingViews) {
            specialView.onCabModeEntered();
        }
    }

    public void onCabModeExited() {
        for (final ConversationSpecialItemView specialView : mFleetingViews) {
            specialView.onCabModeExited();
        }
    }

    public void onConversationListVisibilityChanged(final boolean visible) {
        for (final ConversationSpecialItemView specialView : mFleetingViews) {
            specialView.onConversationListVisibilityChanged(visible);
        }
    }

    public void onScrollStateChanged(final int scrollState) {
        final boolean scrolling = scrollState != OnScrollListener.SCROLL_STATE_IDLE;
        mAttachmentPreviewsCache.setBlocking(scrolling);
    }

    public int getViewMode() {
        return mActivity.getViewMode().getMode();
    }

    public boolean isInCabMode() {
        // If we have conversation in our selected set, we're in CAB mode
        return !mBatchConversations.isEmpty();
    }

    public void saveSpecialItemInstanceState(final Bundle outState) {
        for (final ConversationSpecialItemView specialView : mFleetingViews) {
            specialView.saveInstanceState(outState);
        }
    }
}
