/*
 * Copyright (C) 2011 Cyril Mottier (http://www.cyrilmottier.com)
 *
 * 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 greendroid.app;

import greendroid.widget.ActionBar;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View;
import android.view.View.OnCreateContextMenuListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;

import com.cyrilmottier.android.greendroid.R;

/**
 * A {@link GDActivity} equivalent to ExpandableListActivity that manages an
 * ExpandableListView.
 */
public class GDExpandableListActivity extends GDActivity implements OnCreateContextMenuListener, ExpandableListView.OnChildClickListener,
        ExpandableListView.OnGroupCollapseListener, ExpandableListView.OnGroupExpandListener {

    private ExpandableListAdapter mAdapter;
    private ExpandableListView mList;
    private View mEmptyView;

    boolean mFinishedStart = false;

    public GDExpandableListActivity() {
        super();
    }

    public GDExpandableListActivity(ActionBar.Type actionBarType) {
        super(actionBarType);
    }

    /**
     * Override this to populate the context menu when an item is long pressed.
     * menuInfo will contain an
     * android.widget.ExpandableListView.ExpandableListContextMenuInfo whose
     * packedPosition is a packed position that should be used with
     * ExpandableListView#getPackedPositionType(long) and the other similar
     * methods.
     * <p>
     * {@inheritDoc}
     */
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
    }

    /**
     * Override this for receiving callbacks when a child has been clicked.
     * <p>
     * {@inheritDoc}
     */
    public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
        return false;
    }

    /**
     * Override this for receiving callbacks when a group has been collapsed.
     */
    public void onGroupCollapse(int groupPosition) {
    }

    /**
     * Override this for receiving callbacks when a group has been expanded.
     */
    public void onGroupExpand(int groupPosition) {
    }

    /**
     * Provide the adapter for the expandable list.
     */
    public void setListAdapter(ExpandableListAdapter adapter) {
        synchronized (this) {
            ensureLayout();
            mAdapter = adapter;
            mList.setAdapter(adapter);
        }
    }

    /**
     * Get the activity's expandable list view widget. This can be used to get
     * the selection, set the selection, and many other useful functions.
     * 
     * @see ExpandableListView
     */
    public ExpandableListView getExpandableListView() {
        ensureLayout();
        return mList;
    }

    /**
     * Get the ExpandableListAdapter associated with this activity's
     * ExpandableListView.
     */
    public ExpandableListAdapter getExpandableListAdapter() {
        return mAdapter;
    }

    @Override
    public int createLayout() {
        switch (getActionBarType()) {
            case Dashboard:
                return R.layout.gd_expandable_list_content_dashboard;
            case Empty:
                return R.layout.gd_expandable_list_content_empty;
            case Normal:
            default:
                return R.layout.gd_expandable_list_content_normal;
        }
    }

    @Override
    public void onPreContentChanged() {
        super.onPreContentChanged();

        mEmptyView = findViewById(android.R.id.empty);
        mList = (ExpandableListView) findViewById(android.R.id.list);
        if (mList == null) {
            throw new RuntimeException("Your content must have a ExpandableListView whose id attribute is " + "'android.R.id.list'");
        }
    }

    @Override
    public void onPostContentChanged() {
        super.onPostContentChanged();

        if (mEmptyView != null) {
            mList.setEmptyView(mEmptyView);
        }
        mList.setOnChildClickListener(this);
        mList.setOnGroupExpandListener(this);
        mList.setOnGroupCollapseListener(this);

        if (mFinishedStart) {
            setListAdapter(mAdapter);
        }
        mFinishedStart = true;
    }

    @Override
    public void setActionBarContentView(int resID) {
        throwSetActionBarContentViewException();
    }

    @Override
    public void setActionBarContentView(View view, LayoutParams params) {
        throwSetActionBarContentViewException();
    }

    @Override
    public void setActionBarContentView(View view) {
        throwSetActionBarContentViewException();
    }

    private void throwSetActionBarContentViewException() {
        throw new UnsupportedOperationException(
                "The setActionBarContentView method is not supported for GDListActivity. In order to get a custom layout you must return a layout identifier in createLayout");

    }

    @Override
    protected boolean verifyLayout() {
        return super.verifyLayout() && mList != null;
    }

    /**
     * Gets the ID of the currently selected group or child.
     * 
     * @return The ID of the currently selected group or child.
     */
    public long getSelectedId() {
        return mList.getSelectedId();
    }

    /**
     * Gets the position (in packed position representation) of the currently
     * selected group or child. Use ExpandableListView#getPackedPositionType,
     * ExpandableListView#getPackedPositionGroup, and
     * ExpandableListView#getPackedPositionChild to unpack the returned packed
     * position.
     * 
     * @return A packed position representation containing the currently
     *         selected group or child's position and type.
     */
    public long getSelectedPosition() {
        return mList.getSelectedPosition();
    }

    /**
     * Sets the selection to the specified child. If the child is in a collapsed
     * group, the group will only be expanded and child subsequently selected if
     * shouldExpandGroup is set to true, otherwise the method will return false.
     * 
     * @param groupPosition The position of the group that contains the child.
     * @param childPosition The position of the child within the group.
     * @param shouldExpandGroup Whether the child's group should be expanded if
     *            it is collapsed.
     * @return Whether the selection was successfully set on the child.
     */
    public boolean setSelectedChild(int groupPosition, int childPosition, boolean shouldExpandGroup) {
        return mList.setSelectedChild(groupPosition, childPosition, shouldExpandGroup);
    }

    /**
     * Sets the selection to the specified group.
     * 
     * @param groupPosition The position of the group that should be selected.
     */
    public void setSelectedGroup(int groupPosition) {
        mList.setSelectedGroup(groupPosition);
    }
}