/*
 * Copyright (C) 2010 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.launcher3.list;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;

/**
 * A subclass of {@link CompositeCursorAdapter} that manages pinned partition headers.
 */
public abstract class PinnedHeaderListAdapter extends CompositeCursorAdapter
        implements PinnedHeaderListView.PinnedHeaderAdapter {

    public static final int PARTITION_HEADER_TYPE = 0;

    private boolean mPinnedPartitionHeadersEnabled;
    private boolean mHeaderVisibility[];

    public PinnedHeaderListAdapter(Context context) {
        super(context);
    }

    public PinnedHeaderListAdapter(Context context, int initialCapacity) {
        super(context, initialCapacity);
    }

    public boolean getPinnedPartitionHeadersEnabled() {
        return mPinnedPartitionHeadersEnabled;
    }

    public void setPinnedPartitionHeadersEnabled(boolean flag) {
        this.mPinnedPartitionHeadersEnabled = flag;
    }

    @Override
    public int getPinnedHeaderCount() {
        if (mPinnedPartitionHeadersEnabled) {
            return getPartitionCount();
        } else {
            return 0;
        }
    }

    protected boolean isPinnedPartitionHeaderVisible(int partition) {
        return getPinnedPartitionHeadersEnabled() && hasHeader(partition)
                && !isPartitionEmpty(partition);
    }

    /**
     * The default implementation creates the same type of view as a normal
     * partition header.
     */
    @Override
    public View getPinnedHeaderView(int partition, View convertView, ViewGroup parent) {
        if (hasHeader(partition)) {
            View view = null;
            if (convertView != null) {
                Integer headerType = (Integer)convertView.getTag();
                if (headerType != null && headerType == PARTITION_HEADER_TYPE) {
                    view = convertView;
                }
            }
            if (view == null) {
                view = newHeaderView(getContext(), partition, null, parent);
                view.setTag(PARTITION_HEADER_TYPE);
                view.setFocusable(false);
                view.setEnabled(false);
            }
            bindHeaderView(view, partition, getCursor(partition));
            view.setLayoutDirection(parent.getLayoutDirection());
            return view;
        } else {
            return null;
        }
    }

    @Override
    public void configurePinnedHeaders(PinnedHeaderListView listView) {
        if (!getPinnedPartitionHeadersEnabled()) {
            return;
        }

        int size = getPartitionCount();
        boolean unCached = false;
        // Cache visibility bits, because we will need them several times later on
        if (mHeaderVisibility == null || mHeaderVisibility.length != size) {
            mHeaderVisibility = new boolean[size];
            unCached = true;
        }
        for (int i = 0; i < size; i++) {
            boolean visible = isPinnedPartitionHeaderVisible(i);
            mHeaderVisibility[i] = visible;
            if (!visible) {
                listView.setHeaderInvisible(i, true);
            }
        }

        int headerViewsCount = listView.getHeaderViewsCount();

        // Starting at the top, find and pin headers for partitions preceding the visible one(s)
        int topHeaderHeight = 0;
        for (int i = 0; i < size; i++) {
            if (mHeaderVisibility[i]) {
                int position = listView.getPositionAt(topHeaderHeight) - headerViewsCount;
                int partition = getPartitionForPosition(position);
                if (i > partition) {
                    break;
                }

                if (!unCached){
                    listView.setHeaderPinnedAtTop(i, topHeaderHeight, false);
                    topHeaderHeight += listView.getPinnedHeaderHeight(i);
                }

            }
        }
    }

    @Override
    public int getScrollPositionForHeader(int viewIndex) {
        return getPositionForPartition(viewIndex);
    }
}