/*
 * Copyright (C) 2015 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.documentsui.dirlist;

import static com.android.documentsui.Shared.DEBUG;
import static com.android.documentsui.State.MODE_GRID;
import static com.android.documentsui.State.MODE_LIST;
import static com.android.documentsui.model.DocumentInfo.getCursorInt;
import static com.android.documentsui.model.DocumentInfo.getCursorString;

import android.database.Cursor;
import android.provider.DocumentsContract.Document;
import android.util.Log;
import android.util.SparseArray;
import android.view.ViewGroup;

import com.android.documentsui.State;
import com.google.common.collect.Sets;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Adapts from dirlist.Model to something RecyclerView understands.
 */
final class ModelBackedDocumentsAdapter extends DocumentsAdapter {

    private static final String TAG = "ModelBackedDocuments";
    public static final int ITEM_TYPE_DOCUMENT = 1;
    public static final int ITEM_TYPE_DIRECTORY = 2;

    // Provides access to information needed when creating and view holders. This
    // isn't an ideal pattern (more transitive dependency stuff) but good enough for now.
    private final Environment mEnv;
    private final IconHelper mIconHelper;  // a transitive dependency of the holders.

    /**
     * An ordered list of model IDs. This is the data structure that determines what shows up in
     * the UI, and where.
     */
    private List<String> mModelIds = new ArrayList<>();

    // List of files that have been deleted. Some transient directory updates
    // may happen while files are being deleted. During this time we don't
    // want once-hidden files to be re-shown. We only remove
    // items from this list when we get a model update where the model
    // does not contain a corresponding id. This ensures hidden entries
    // don't momentarily re-appear if we get intermediate updates from
    // the file system.
    private Set<String> mHiddenIds = new HashSet<>();

    public ModelBackedDocumentsAdapter(Environment env, IconHelper iconHelper) {
        mEnv = env;
        mIconHelper = iconHelper;
    }

    @Override
    public DocumentHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        DocumentHolder holder = null;
        final State state = mEnv.getDisplayState();
        switch (state.derivedMode) {
            case MODE_GRID:
                switch (viewType) {
                    case ITEM_TYPE_DIRECTORY:
                        holder = new GridDirectoryHolder(mEnv.getContext(), parent);
                        break;
                    case ITEM_TYPE_DOCUMENT:
                        holder = new GridDocumentHolder(mEnv.getContext(), parent, mIconHelper);
                        break;
                    default:
                        throw new IllegalStateException("Unsupported layout type.");
                }
                break;
            case MODE_LIST:
                holder = new ListDocumentHolder(mEnv.getContext(), parent, mIconHelper);
                break;
            default:
                throw new IllegalStateException("Unsupported layout mode.");
        }

        mEnv.initDocumentHolder(holder);
        return holder;
    }

    @Override
    public void onBindViewHolder(DocumentHolder holder, int position, List<Object> payload) {
        if (payload.contains(SELECTION_CHANGED_MARKER)) {
            final boolean selected = mEnv.isSelected(mModelIds.get(position));
            holder.setSelected(selected);
        } else {
            onBindViewHolder(holder, position);
        }
    }

    @Override
    public void onBindViewHolder(DocumentHolder holder, int position) {
        String modelId = mModelIds.get(position);
        Cursor cursor = mEnv.getModel().getItem(modelId);
        holder.bind(cursor, modelId, mEnv.getDisplayState());

        final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
        final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);

        holder.setSelected(mEnv.isSelected(modelId));
        holder.setEnabled(mEnv.isDocumentEnabled(docMimeType, docFlags));

        mEnv.onBindDocumentHolder(holder, cursor);
    }

    @Override
    public int getItemCount() {
        return mModelIds.size();
    }

    @Override
    public void onModelUpdate(Model model) {
        if (DEBUG && mHiddenIds.size() > 0) {
            Log.d(TAG, "Updating model with hidden ids: " + mHiddenIds);
        }

        List<String> modelIds = model.getModelIds();
        mModelIds = new ArrayList<>(modelIds.size());
        for (String id : modelIds) {
            if (!mHiddenIds.contains(id)) {
                mModelIds.add(id);
            } else {
                if (DEBUG) Log.d(TAG, "Omitting hidden id from model during update: " + id);
            }
        }

        // Finally remove any hidden ids that aren't present in the model.
        // This assumes that model updates represent a complete set of files.
        mHiddenIds.retainAll(mModelIds);
    }

    @Override
    public void onModelUpdateFailed(Exception e) {
        Log.w(TAG, "Model update failed.", e);
        mModelIds.clear();
    }

    @Override
    public String getModelId(int adapterPosition) {
        return mModelIds.get(adapterPosition);
    }

    @Override
    public SparseArray<String> hide(String... ids) {
        if (DEBUG) Log.d(TAG, "Hiding ids: " + ids);
        Set<String> toHide = Sets.newHashSet(ids);

        // Proceed backwards through the list of items, because each removal causes the
        // positions of all subsequent items to change.
        SparseArray<String> hiddenItems = new SparseArray<>();
        for (int i = mModelIds.size() - 1; i >= 0; --i) {
            String id = mModelIds.get(i);
            if (toHide.contains(id)) {
                mHiddenIds.add(id);
                hiddenItems.put(i, mModelIds.remove(i));
                notifyItemRemoved(i);
            }
        }

        return hiddenItems;
    }

    @Override
    public void unhide(SparseArray<String> ids) {
        if (DEBUG) Log.d(TAG, "Unhiding ids: " + ids);

        // An ArrayList can shrink at runtime...and in fact
        // it does when we clear it completely.
        // This means we can't call add(pos, id) without
        // first checking the list size.
        List<String> oldIds = mModelIds;
        mModelIds = new ArrayList<>(oldIds.size() + ids.size());
        mModelIds.addAll(oldIds);

        // Finally insert the unhidden items.
        for (int i = 0; i < ids.size(); i++) {
            int pos = ids.keyAt(i);
            String id = ids.get(pos);
            mHiddenIds.remove(id);
            mModelIds.add(pos, id);
            notifyItemInserted(pos);
        }
    }

    @Override
    public List<String> getModelIds() {
        return mModelIds;
    }

    @Override
    public int getItemViewType(int position) {
        return isDirectory(mEnv.getModel(), position)
                ? ITEM_TYPE_DIRECTORY
                : ITEM_TYPE_DOCUMENT;
    }

    @Override
    public void onItemSelectionChanged(String id) {
        int position = mModelIds.indexOf(id);

        if (position >= 0) {
            notifyItemChanged(position, SELECTION_CHANGED_MARKER);
        } else {
            Log.w(TAG, "Item change notification received for unknown item: " + id);
        }
    }
}
