/*
 * Copyright (C) 2013 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.app.LoaderManager;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.Context;
import android.content.Loader;
import android.content.res.Resources;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.util.SparseArrayCompat;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.android.mail.R;
import com.android.mail.browse.ConversationCursor;
import com.android.mail.content.ObjectCursor;
import com.android.mail.content.ObjectCursorLoader;
import com.android.mail.providers.Account;
import com.android.mail.providers.Conversation;
import com.android.mail.providers.Folder;
import com.android.mail.providers.MessageInfo;
import com.android.mail.providers.UIProvider;
import com.android.mail.providers.UIProvider.AccountCapabilities;
import com.android.mail.providers.UIProvider.ConversationListQueryParameters;
import com.android.mail.utils.LogUtils;
import com.android.mail.utils.Utils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

/**
 * The teaser list item in the conversation list that shows nested folders.
 */
public class NestedFolderTeaserView extends LinearLayout implements ConversationSpecialItemView {
    private static final String LOG_TAG = "NestedFolderTeaserView";

    private boolean mShouldDisplayInList = false;

    private Account mAccount;
    private Uri mFolderListUri;
    private FolderSelector mListener;

    private LoaderManager mLoaderManager = null;
    private AnimatedAdapter mAdapter = null;

    private final SparseArrayCompat<FolderHolder> mFolderHolders =
            new SparseArrayCompat<FolderHolder>();

    private final int mFolderItemUpdateDelayMs;

    private int mAnimatedHeight = -1;

    private ViewGroup mNestedFolderContainer;

    private View mShowMoreFoldersRow;
    private TextView mShowMoreFoldersTextView;
    private TextView mShowMoreFoldersCountTextView;

    /**
     * If <code>true</code> we show a limited set of folders, and a means to show all folders. If
     * <code>false</code>, we show all folders.
     */
    private boolean mCollapsed = true;

    private View mTeaserRightEdge;
    /** Whether we are on a tablet device or not */
    private final boolean mTabletDevice;
    /** When in conversation mode, true if the list is hidden */
    private final boolean mListCollapsible;

    /** If <code>true</code>, the list of folders has updated since the view was last shown. */
    private boolean mListUpdated;

    // Each folder's loader will be this value plus the folder id
    private static final int LOADER_FOLDER_LIST =
            AbstractActivityController.LAST_FRAGMENT_LOADER_ID + 100000;

    /**
     * The maximum number of senders to show in the sender snippet.
     */
    private static final String MAX_SENDERS = "20";

    /**
     * The number of folders to show when the teaser is collapsed.
     */
    private static int sCollapsedFolderThreshold = -1;

    private static class FolderHolder {
        private final View mItemView;
        private final TextView mSendersTextView;
        private final TextView mCountTextView;
        private Folder mFolder;
        private List<String> mUnreadSenders = ImmutableList.of();

        public FolderHolder(final View itemView, final TextView sendersTextView,
                final TextView countTextView) {
            mItemView = itemView;
            mSendersTextView = sendersTextView;
            mCountTextView = countTextView;
        }

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

        public View getItemView() {
            return mItemView;
        }

        public TextView getSendersTextView() {
            return mSendersTextView;
        }

        public TextView getCountTextView() {
            return mCountTextView;
        }

        public Folder getFolder() {
            return mFolder;
        }

        /**
         * @return a {@link List} of senders of unread messages
         */
        public List<String> getUnreadSenders() {
            return mUnreadSenders;
        }

        public void setUnreadSenders(final List<String> unreadSenders) {
            mUnreadSenders = unreadSenders;
        }

        public static final Comparator<FolderHolder> NAME_COMPARATOR =
                new Comparator<FolderHolder>() {
            @Override
            public int compare(final FolderHolder lhs, final FolderHolder rhs) {
                return lhs.getFolder().name.compareTo(rhs.getFolder().name);
            }
        };
    }

    public NestedFolderTeaserView(final Context context) {
        this(context, null);
    }

    public NestedFolderTeaserView(final Context context, final AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public NestedFolderTeaserView(
            final Context context, final AttributeSet attrs, final int defStyle) {
        super(context, attrs, defStyle);

        final Resources resources = context.getResources();

        if (sCollapsedFolderThreshold < 0) {
            sCollapsedFolderThreshold =
                    resources.getInteger(R.integer.nested_folders_collapse_threshold);
        }

        mFolderItemUpdateDelayMs =
                resources.getInteger(R.integer.folder_item_refresh_delay_ms);

        mTabletDevice = com.android.mail.utils.Utils.useTabletUI(resources);
        mListCollapsible = resources.getBoolean(R.bool.list_collapsible);
    }

    @Override
    protected void onFinishInflate() {
        mNestedFolderContainer = (ViewGroup) findViewById(R.id.nested_folder_container);
        mTeaserRightEdge = findViewById(R.id.teaser_right_edge);

        mShowMoreFoldersRow = findViewById(R.id.show_more_folders_row);
        mShowMoreFoldersRow.setOnClickListener(mShowMoreOnClickListener);

        mShowMoreFoldersTextView = (TextView) findViewById(R.id.show_more_folders_textView);
        mShowMoreFoldersCountTextView =
                (TextView) findViewById(R.id.show_more_folders_count_textView);
    }

    public void bind(final Account account, final FolderSelector listener) {
        mAccount = account;
        mListener = listener;
    }

    /**
     * Creates a {@link FolderHolder}.
     */
    private FolderHolder createFolderHolder(final CharSequence folderName) {
        final View itemView =
                LayoutInflater.from(getContext()).inflate(R.layout.folder_teaser_item, null);

        final ImageView imageView = (ImageView) itemView.findViewById(R.id.folder_imageView);
        imageView.setImageResource(R.drawable.ic_menu_folders_holo_light);
        // Remove background
        imageView.setBackgroundColor(Color.TRANSPARENT);

        ((TextView) itemView.findViewById(R.id.folder_textView)).setText(folderName);
        final TextView sendersTextView = (TextView) itemView.findViewById(R.id.senders_textView);
        final TextView countTextView = (TextView) itemView.findViewById(R.id.count_textView);
        final FolderHolder holder = new FolderHolder(itemView, sendersTextView, countTextView);

        attachOnClickListener(itemView, holder);

        return holder;
    }

    private void attachOnClickListener(final View view, final FolderHolder holder) {
        view.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(final View v) {
                mListener.onFolderSelected(holder.getFolder());
            }
        });
    }

    @Override
    public void onUpdate(final Folder folder, final ConversationCursor cursor) {
        mShouldDisplayInList = false; // Assume disabled

        if (folder == null) {
            return;
        }

        final Uri folderListUri = folder.childFoldersListUri;
        if (folderListUri == null) {
            return;
        }

        // If we don't support nested folders, don't show this view
        if (!mAccount.supportsCapability(AccountCapabilities.NESTED_FOLDERS)) {
            return;
        }

        if (mFolderListUri == null || !mFolderListUri.equals(folder.childFoldersListUri)) {
            // We have a new uri
            mFolderListUri = folderListUri;

            // Restart the loader
            mLoaderManager.destroyLoader(LOADER_FOLDER_LIST);
            mLoaderManager.initLoader(LOADER_FOLDER_LIST, null, mFolderListLoaderCallbacks);
        }

        mShouldDisplayInList = true; // Now we know we have something to display
    }

    @Override
    public void onGetView() {
        if (mListUpdated) {
            // Clear out the folder views
            mNestedFolderContainer.removeAllViews();

            // Sort the folders by name
            // TODO(skennedy) recents? starred?
            final ImmutableSortedSet.Builder<FolderHolder> folderHoldersBuilder =
                    new ImmutableSortedSet.Builder<FolderHolder>(FolderHolder.NAME_COMPARATOR);

            for (int i = 0; i < mFolderHolders.size(); i++) {
                folderHoldersBuilder.add(mFolderHolders.valueAt(i));
            }

            final ImmutableSortedSet<FolderHolder> folderHolders = folderHoldersBuilder.build();

            // Add all folder views to the teaser
            int added = 0;
            for (final FolderHolder folderHolder : folderHolders) {
                mNestedFolderContainer.addView(folderHolder.getItemView());
                added++;

                if (added >= sCollapsedFolderThreshold && mCollapsed) {
                    // We will display the rest when "Show more" is clicked
                    break;
                }
            }

            updateShowMoreView();

            mListUpdated = false;
        }
    }

    private final OnClickListener mShowMoreOnClickListener = new OnClickListener() {
        @Override
        public void onClick(final View v) {
            mCollapsed = !mCollapsed;
            mListUpdated = true;
            mAdapter.notifyDataSetChanged();
        }
    };

    private void updateShowMoreView() {
        final int total = mFolderHolders.size();
        final int displayed = mNestedFolderContainer.getChildCount();
        final int notShown = total - displayed;

        if (notShown > 0) {
            // We are not displaying all the folders
            mShowMoreFoldersRow.setVisibility(VISIBLE);
            mShowMoreFoldersTextView.setText(String.format(
                    getContext().getString(R.string.show_n_more_folders), notShown));
            mShowMoreFoldersCountTextView.setVisibility(VISIBLE);

            // Get a count of unread messages in other folders
            int unreadCount = 0;
            for (int i = 0; i < mFolderHolders.size(); i++) {
                final FolderHolder holder = mFolderHolders.valueAt(i);

                if (holder.getItemView().getParent() == null) {
                    // This view is not shown, so we want to use its unread count
                    // TODO(skennedy) We want a "nested" unread count, that includes the unread
                    // count of nested folders
                    unreadCount += holder.getFolder().unreadCount;
                }
            }

            mShowMoreFoldersCountTextView.setText(Integer.toString(unreadCount));
        } else if (displayed > sCollapsedFolderThreshold) {
            // We are expanded
            mShowMoreFoldersRow.setVisibility(VISIBLE);
            mShowMoreFoldersTextView.setText(R.string.hide_folders);
            mShowMoreFoldersCountTextView.setVisibility(GONE);
        } else {
            // We don't need to collapse the folders
            mShowMoreFoldersRow.setVisibility(GONE);
        }
    }

    private void updateViews(final FolderHolder folderHolder) {
        final Folder folder = folderHolder.getFolder();

        final String unreadText = Utils.getUnreadCountString(getContext(), folder.unreadCount);
        folderHolder.getCountTextView().setText(unreadText.isEmpty() ? "0" : unreadText);

        final String sendersText = TextUtils.join(", ", folderHolder.getUnreadSenders());
        folderHolder.getSendersTextView().setText(sendersText);
    }

    @Override
    public boolean getShouldDisplayInList() {
        return mShouldDisplayInList;
    }

    @Override
    public int getPosition() {
        return 0;
    }

    @Override
    public void setAdapter(final AnimatedAdapter adapter) {
        mAdapter = adapter;
    }

    @Override
    public void bindFragment(final LoaderManager loaderManager, final Bundle savedInstanceState) {
        if (mLoaderManager != null) {
            throw new IllegalStateException("This view has already been bound to a LoaderManager.");
        }

        mLoaderManager = loaderManager;
    }

    @Override
    public void cleanup() {
        // Do nothing
    }

    @Override
    public void onConversationSelected() {
        // Do nothing
    }

    @Override
    public void onCabModeEntered() {
        // Do nothing
    }

    @Override
    public void onCabModeExited() {
        // Do nothing
    }

    @Override
    public void onConversationListVisibilityChanged(final boolean visible) {
        // Do nothing
    }

    @Override
    public void saveInstanceState(final Bundle outState) {
        // Do nothing
    }

    @Override
    public boolean acceptsUserTaps() {
        // The teaser does not allow user tap in the list.
        return false;
    }

    @Override
    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
        if (com.android.mail.utils.Utils.getDisplayListRightEdgeEffect(mTabletDevice,
                mListCollapsible, mAdapter.getViewMode())) {
            mTeaserRightEdge.setVisibility(VISIBLE);
        } else {
            mTeaserRightEdge.setVisibility(GONE);
        }

        if (mAnimatedHeight == -1) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        } else {
            setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), mAnimatedHeight);
        }
    }

    private static int getLoaderId(final int folderId) {
        return folderId + LOADER_FOLDER_LIST;
    }

    private static int getFolderId(final int loaderId) {
        return loaderId - LOADER_FOLDER_LIST;
    }

    private final LoaderCallbacks<ObjectCursor<Folder>> mFolderListLoaderCallbacks =
            new LoaderCallbacks<ObjectCursor<Folder>>() {
        @Override
        public void onLoaderReset(final Loader<ObjectCursor<Folder>> loader) {
            // Do nothing
        }

        @Override
        public void onLoadFinished(final Loader<ObjectCursor<Folder>> loader,
                final ObjectCursor<Folder> data) {
            if (data != null) {
                // We need to keep track of all current folders in case one has been removed
                final List<Integer> oldFolderIds = new ArrayList<Integer>(mFolderHolders.size());
                for (int i = 0; i < mFolderHolders.size(); i++) {
                    oldFolderIds.add(mFolderHolders.keyAt(i));
                }

                if (data.moveToFirst()) {
                    do {
                        final Folder folder = data.getModel();
                        final FolderHolder holder = mFolderHolders.get(folder.id);

                        if (holder != null) {
                            final Folder oldFolder = holder.getFolder();
                            holder.setFolder(folder);

                            /*
                             * We only need to change anything if the old Folder was null, or the
                             * unread count has changed.
                             */
                            if (oldFolder == null || oldFolder.unreadCount != folder.unreadCount) {
                                updateViews(holder);
                            }
                        } else {
                            // Create the holder, and init a loader
                            final FolderHolder newHolder = createFolderHolder(folder.name);
                            newHolder.setFolder(folder);
                            mFolderHolders.put(folder.id, newHolder);

                            initFolderLoader(getLoaderId(folder.id));

                            updateViews(newHolder);

                            mListUpdated = true;
                        }

                        // Note: #remove(int) removes from that POSITION
                        //       #remove(Integer) removes that OBJECT
                        oldFolderIds.remove(Integer.valueOf(folder.id));
                    } while (data.moveToNext());
                }

                for (final int folderId : oldFolderIds) {
                    // We have a folder that no longer exists
                    mFolderHolders.remove(folderId);
                    mLoaderManager.destroyLoader(getLoaderId(folderId));
                    mListUpdated = true;
                }

                // If the list has not changed, we've already updated the counts, etc.
                // If the list has changed, we need to rebuild it
                if (mListUpdated) {
                    mAdapter.notifyDataSetChanged();
                }
            } else {
                LogUtils.w(LOG_TAG, "Problem with folder list cursor returned from loader");
            }
        }

        private void initFolderLoader(final int loaderId) {
            LogUtils.d(LOG_TAG, "Initializing folder loader %d", loaderId);
            mLoaderManager.initLoader(loaderId, null, mFolderLoaderCallbacks);
        }

        @Override
        public Loader<ObjectCursor<Folder>> onCreateLoader(final int id, final Bundle args) {
            final ObjectCursorLoader<Folder> loader = new ObjectCursorLoader<Folder>(getContext(),
                    mFolderListUri, UIProvider.FOLDERS_PROJECTION, Folder.FACTORY);
            loader.setUpdateThrottle(mFolderItemUpdateDelayMs);
            return loader;
        }
    };

    private final LoaderCallbacks<ObjectCursor<Conversation>> mFolderLoaderCallbacks =
            new LoaderCallbacks<ObjectCursor<Conversation>>() {
        @Override
        public void onLoaderReset(final Loader<ObjectCursor<Conversation>> loader) {
            // Do nothing
        }

        @Override
        public void onLoadFinished(final Loader<ObjectCursor<Conversation>> loader,
                final ObjectCursor<Conversation> data) {
            // Sometimes names are condensed to just the first name.
            // This data structure keeps a map of emails to names
            final Map<String, String> emailToNameMap = Maps.newHashMap();
            final List<String> senders = Lists.newArrayList();

            final int folderId = getFolderId(loader.getId());

            final FolderHolder folderHolder = mFolderHolders.get(folderId);
            final int maxSenders = folderHolder.mFolder.unreadCount;

            if (maxSenders > 0 && data != null && data.moveToFirst()) {
                LogUtils.d(LOG_TAG, "Folder id %d loader finished", folderId);

                // Look through all conversations until we find 'maxSenders' unread
                int sendersFound = 0;

                do {
                    final Conversation conversation = data.getModel();

                    if (!conversation.read) {
                        String sender = null;
                        String senderEmail = null;
                        int priority = Integer.MIN_VALUE;

                        // Find the highest priority sender
                        for (final MessageInfo messageInfo :
                            conversation.conversationInfo.messageInfos) {
                            if (sender == null || priority < messageInfo.priority) {
                                sender = messageInfo.sender;
                                senderEmail = messageInfo.senderEmail;
                                priority = messageInfo.priority;
                            }
                        }

                        if (sender != null) {
                            sendersFound++;
                            final String existingSender = emailToNameMap.get(senderEmail);
                            if (existingSender != null) {
                                // Prefer longer names
                                if (existingSender.length() >= sender.length()) {
                                    // old name is longer
                                    sender = existingSender;
                                } else {
                                    // new name is longer
                                    int index = senders.indexOf(existingSender);
                                    senders.set(index, sender);
                                }
                            } else {
                                senders.add(sender);
                            }
                            emailToNameMap.put(senderEmail, sender);
                        }
                    }
                } while (data.moveToNext() && sendersFound < maxSenders);
            } else {
                LogUtils.w(LOG_TAG, "Problem with folder cursor returned from loader");
            }

            folderHolder.setUnreadSenders(senders);

            /*
             * Just update the views in place. We don't need to call notifyDataSetChanged()
             * because we aren't changing the teaser's visibility or position.
             */
            updateViews(folderHolder);
        }

        @Override
        public Loader<ObjectCursor<Conversation>> onCreateLoader(final int id, final Bundle args) {
            final int folderId = getFolderId(id);
            final Uri uri = mFolderHolders.get(folderId).mFolder.conversationListUri
                    .buildUpon()
                    .appendQueryParameter(ConversationListQueryParameters.USE_NETWORK,
                            Boolean.FALSE.toString())
                    .appendQueryParameter(ConversationListQueryParameters.LIMIT, MAX_SENDERS)
                    .build();
            return new ObjectCursorLoader<Conversation>(getContext(), uri,
                    UIProvider.CONVERSATION_PROJECTION, Conversation.FACTORY);
        }
    };

    @Override
    public boolean commitLeaveBehindItem() {
        // This view has no leave-behind
        return false;
    }
}
