/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.gecko.home;

import org.mozilla.gecko.R;
import org.mozilla.gecko.db.BrowserContract.Bookmarks;
import org.mozilla.gecko.db.BrowserContract.Combined;
import org.mozilla.gecko.db.BrowserContract.URLColumns;
import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
import org.mozilla.gecko.util.StringUtils;

import android.content.Context;
import android.content.res.TypedArray;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AbsListView.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ListView;

/**
 * HomeListView is a custom extension of ListView, that packs a HomeContextMenuInfo
 * when any of its rows is long pressed.
 */
public class HomeListView extends ListView
                          implements OnItemLongClickListener {

    // ContextMenuInfo associated with the currently long pressed list item.
    private HomeContextMenuInfo mContextMenuInfo;

    // On URL open listener
    private OnUrlOpenListener mUrlOpenListener;

    // Top divider
    private boolean mShowTopDivider;

    public HomeListView(Context context) {
        this(context, null);
    }

    public HomeListView(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.homeListViewStyle);
    }

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

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.HomeListView, defStyle, 0);
        mShowTopDivider = a.getBoolean(R.styleable.HomeListView_topDivider, false);
        a.recycle();

        setOnItemLongClickListener(this);
    }

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

        final Drawable divider = getDivider();
        if (mShowTopDivider && divider != null) {
            final int dividerHeight = getDividerHeight();
            final View view = new View(getContext());
            view.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, dividerHeight));
            addHeaderView(view);
        }
    }

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

        mUrlOpenListener = null;
    }

    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
        Object item = parent.getItemAtPosition(position);

        // HomeListView could hold headers too. Add a context menu info only for its children.
        if (item instanceof Cursor) {
            Cursor cursor = (Cursor) item;
            mContextMenuInfo = new HomeContextMenuInfo(view, position, id, cursor);
            return showContextMenuForChild(HomeListView.this);
        } else {
            mContextMenuInfo = null;
            return false;
        }
    }

    @Override
    public ContextMenuInfo getContextMenuInfo() {
        return mContextMenuInfo;
    }

    @Override
    public void setOnItemClickListener(final AdapterView.OnItemClickListener listener) {
        super.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if (mShowTopDivider) {
                    position--;
                }

                listener.onItemClick(parent, view, position, id);
            }
        });
    }

    public OnUrlOpenListener getOnUrlOpenListener() {
        return mUrlOpenListener;
    }

    public void setOnUrlOpenListener(OnUrlOpenListener listener) {
        mUrlOpenListener = listener;
    }

    /**
     * A ContextMenuInfo for HomeListView that adds details from the cursor.
     */
    public static class HomeContextMenuInfo extends AdapterContextMenuInfo {

        public int bookmarkId;
        public int historyId;
        public String url;
        public String title;
        public int display;
        public boolean isFolder;
        public boolean inReadingList;

        /**
         * This constructor assumes that the cursor was generated from a query
         * to either the combined view or the bookmarks table.
         */
        public HomeContextMenuInfo(View targetView, int position, long id, Cursor cursor) {
            super(targetView, position, id);

            if (cursor == null) {
                return;
            }

            final int typeCol = cursor.getColumnIndex(Bookmarks.TYPE);
            if (typeCol != -1) {
                isFolder = (cursor.getInt(typeCol) == Bookmarks.TYPE_FOLDER);
            } else {
                isFolder = false;
            }

            // We don't show a context menu for folders, so return early.
            if (isFolder) {
                return;
            }

            url = cursor.getString(cursor.getColumnIndexOrThrow(URLColumns.URL));
            title = cursor.getString(cursor.getColumnIndexOrThrow(URLColumns.TITLE));

            final int bookmarkIdCol = cursor.getColumnIndex(Combined.BOOKMARK_ID);
            if (bookmarkIdCol == -1) {
                // If there isn't a bookmark ID column, this must be a bookmarks cursor,
                // so the regular ID column will correspond to a bookmark ID.
                bookmarkId = cursor.getInt(cursor.getColumnIndexOrThrow(Bookmarks._ID));
            } else if (cursor.isNull(bookmarkIdCol)) {
                // If this is a combined cursor, we may get a history item without a
                // bookmark, in which case the bookmarks ID column value will be null.
                bookmarkId = -1;
            } else {
                bookmarkId = cursor.getInt(bookmarkIdCol);
            }

            final int historyIdCol = cursor.getColumnIndex(Combined.HISTORY_ID);
            if (historyIdCol != -1) {
                historyId = cursor.getInt(historyIdCol);
            } else {
                historyId = -1;
            }

            // We only have the parent column in cursors from getBookmarksInFolder.
            final int parentCol = cursor.getColumnIndex(Bookmarks.PARENT);
            if (parentCol != -1) {
                inReadingList = (cursor.getInt(parentCol) == Bookmarks.FIXED_READING_LIST_ID);
            } else {
                inReadingList = false;
            }

            final int displayCol = cursor.getColumnIndex(Combined.DISPLAY);
            if (displayCol != -1) {
                display = cursor.getInt(displayCol);
            } else {
                display = Combined.DISPLAY_NORMAL;
            }
        }

        public String getDisplayTitle() {
            return TextUtils.isEmpty(title) ?
                StringUtils.stripCommonSubdomains(StringUtils.stripScheme(url, StringUtils.UrlFlags.STRIP_HTTPS)) : title;
        }
    }
}
