/*
 * Copyright (C) 2008 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.browser;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Fragment;
import android.app.FragmentBreadCrumbs;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.ClipboardManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.CursorLoader;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.Loader;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.database.DataSetObserver;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Browser;
import android.provider.BrowserContract;
import android.provider.BrowserContract.Combined;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Activity for displaying the browser's history, divided into
 * days of viewing.
 */
public class BrowserHistoryPage extends Fragment
        implements LoaderCallbacks<Cursor>, OnChildClickListener {

    static final int LOADER_HISTORY = 1;
    static final int LOADER_MOST_VISITED = 2;

    CombinedBookmarksCallbacks mCallback;
    HistoryAdapter mAdapter;
    HistoryChildWrapper mChildWrapper;
    boolean mDisableNewWindow;
    HistoryItem mContextHeader;
    String mMostVisitsLimit;
    ListView mGroupList, mChildList;
    private ViewGroup mPrefsContainer;
    private FragmentBreadCrumbs mFragmentBreadCrumbs;
    private ExpandableListView mHistoryList;

    private View mRoot;

    static interface HistoryQuery {
        static final String[] PROJECTION = new String[] {
                Combined._ID, // 0
                Combined.DATE_LAST_VISITED, // 1
                Combined.TITLE, // 2
                Combined.URL, // 3
                Combined.FAVICON, // 4
                Combined.VISITS, // 5
                Combined.IS_BOOKMARK, // 6
        };

        static final int INDEX_ID = 0;
        static final int INDEX_DATE_LAST_VISITED = 1;
        static final int INDEX_TITE = 2;
        static final int INDEX_URL = 3;
        static final int INDEX_FAVICON = 4;
        static final int INDEX_VISITS = 5;
        static final int INDEX_IS_BOOKMARK = 6;
    }

    private void copy(CharSequence text) {
        ClipboardManager cm = (ClipboardManager) getActivity().getSystemService(
                Context.CLIPBOARD_SERVICE);
        cm.setText(text);
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        Uri.Builder combinedBuilder = Combined.CONTENT_URI.buildUpon();

        switch (id) {
            case LOADER_HISTORY: {
                String sort = Combined.DATE_LAST_VISITED + " DESC";
                String where = Combined.VISITS + " > 0";
                CursorLoader loader = new CursorLoader(getActivity(), combinedBuilder.build(),
                        HistoryQuery.PROJECTION, where, null, sort);
                return loader;
            }

            case LOADER_MOST_VISITED: {
                Uri uri = combinedBuilder
                        .appendQueryParameter(BrowserContract.PARAM_LIMIT, mMostVisitsLimit)
                        .build();
                String where = Combined.VISITS + " > 0";
                CursorLoader loader = new CursorLoader(getActivity(), uri,
                        HistoryQuery.PROJECTION, where, null, Combined.VISITS + " DESC");
                return loader;
            }

            default: {
                throw new IllegalArgumentException();
            }
        }
    }

    void selectGroup(int position) {
        mGroupItemClickListener.onItemClick(null,
                mAdapter.getGroupView(position, false, null, null),
                position, position);
    }

    void checkIfEmpty() {
        if (mAdapter.mMostVisited != null && mAdapter.mHistoryCursor != null) {
            // Both cursors have loaded - check to see if we have data
            if (mAdapter.isEmpty()) {
                mRoot.findViewById(R.id.history).setVisibility(View.GONE);
                mRoot.findViewById(android.R.id.empty).setVisibility(View.VISIBLE);
            } else {
                mRoot.findViewById(R.id.history).setVisibility(View.VISIBLE);
                mRoot.findViewById(android.R.id.empty).setVisibility(View.GONE);
            }
        }
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        switch (loader.getId()) {
            case LOADER_HISTORY: {
                mAdapter.changeCursor(data);
                if (!mAdapter.isEmpty() && mGroupList != null
                        && mGroupList.getCheckedItemPosition() == ListView.INVALID_POSITION) {
                    selectGroup(0);
                }

                checkIfEmpty();
                break;
            }

            case LOADER_MOST_VISITED: {
                mAdapter.changeMostVisitedCursor(data);

                checkIfEmpty();
                break;
            }

            default: {
                throw new IllegalArgumentException();
            }
        }
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
    }

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        setHasOptionsMenu(true);

        Bundle args = getArguments();
        mDisableNewWindow = args.getBoolean(BrowserBookmarksPage.EXTRA_DISABLE_WINDOW, false);
        int mvlimit = getResources().getInteger(R.integer.most_visits_limit);
        mMostVisitsLimit = Integer.toString(mvlimit);
        mCallback = (CombinedBookmarksCallbacks) getActivity();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        mRoot = inflater.inflate(R.layout.history, container, false);
        mAdapter = new HistoryAdapter(getActivity());
        ViewStub stub = (ViewStub) mRoot.findViewById(R.id.pref_stub);
        if (stub != null) {
            inflateTwoPane(stub);
        } else {
            inflateSinglePane();
        }

        // Start the loaders
        getLoaderManager().restartLoader(LOADER_HISTORY, null, this);
        getLoaderManager().restartLoader(LOADER_MOST_VISITED, null, this);

        return mRoot;
    }

    private void inflateSinglePane() {
        mHistoryList = (ExpandableListView) mRoot.findViewById(R.id.history);
        mHistoryList.setAdapter(mAdapter);
        mHistoryList.setOnChildClickListener(this);
        registerForContextMenu(mHistoryList);
    }

    private void inflateTwoPane(ViewStub stub) {
        stub.setLayoutResource(R.layout.preference_list_content);
        stub.inflate();
        mGroupList = (ListView) mRoot.findViewById(android.R.id.list);
        mPrefsContainer = (ViewGroup) mRoot.findViewById(R.id.prefs_frame);
        mFragmentBreadCrumbs = (FragmentBreadCrumbs) mRoot.findViewById(android.R.id.title);
        mFragmentBreadCrumbs.setMaxVisible(1);
        mFragmentBreadCrumbs.setActivity(getActivity());
        mPrefsContainer.setVisibility(View.VISIBLE);
        mGroupList.setAdapter(new HistoryGroupWrapper(mAdapter));
        mGroupList.setOnItemClickListener(mGroupItemClickListener);
        mGroupList.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
        mChildWrapper = new HistoryChildWrapper(mAdapter);
        mChildList = new ListView(getActivity());
        mChildList.setAdapter(mChildWrapper);
        mChildList.setOnItemClickListener(mChildItemClickListener);
        registerForContextMenu(mChildList);
        ViewGroup prefs = (ViewGroup) mRoot.findViewById(R.id.prefs);
        prefs.addView(mChildList);
    }

    private OnItemClickListener mGroupItemClickListener = new OnItemClickListener() {
        @Override
        public void onItemClick(
                AdapterView<?> parent, View view, int position, long id) {
            CharSequence title = ((TextView) view).getText();
            mFragmentBreadCrumbs.setTitle(title, title);
            mChildWrapper.setSelectedGroup(position);
            mGroupList.setItemChecked(position, true);
        }
    };

    private OnItemClickListener mChildItemClickListener = new OnItemClickListener() {
        @Override
        public void onItemClick(
                AdapterView<?> parent, View view, int position, long id) {
            mCallback.openUrl(((HistoryItem) view).getUrl());
        }
    };

    @Override
    public boolean onChildClick(ExpandableListView parent, View view,
            int groupPosition, int childPosition, long id) {
        mCallback.openUrl(((HistoryItem) view).getUrl());
        return true;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        getLoaderManager().destroyLoader(LOADER_HISTORY);
        getLoaderManager().destroyLoader(LOADER_MOST_VISITED);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate(R.menu.history, menu);
    }

    void promptToClearHistory() {
        final ContentResolver resolver = getActivity().getContentResolver();
        final ClearHistoryTask clear = new ClearHistoryTask(resolver);
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
                .setMessage(R.string.pref_privacy_clear_history_dlg)
                .setIconAttribute(android.R.attr.alertDialogIcon)
                .setNegativeButton(R.string.cancel, null)
                .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                     @Override
                     public void onClick(DialogInterface dialog, int which) {
                         if (which == DialogInterface.BUTTON_POSITIVE) {
                             clear.start();
                         }
                     }
                });
        final Dialog dialog = builder.create();
        dialog.show();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.clear_history_menu_id) {
            promptToClearHistory();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    static class ClearHistoryTask extends Thread {
        ContentResolver mResolver;

        public ClearHistoryTask(ContentResolver resolver) {
            mResolver = resolver;
        }

        @Override
        public void run() {
            Browser.clearHistory(mResolver);
        }
    }

    View getTargetView(ContextMenuInfo menuInfo) {
        if (menuInfo instanceof AdapterContextMenuInfo) {
            return ((AdapterContextMenuInfo) menuInfo).targetView;
        }
        if (menuInfo instanceof ExpandableListContextMenuInfo) {
            return ((ExpandableListContextMenuInfo) menuInfo).targetView;
        }
        return null;
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {

        View targetView = getTargetView(menuInfo);
        if (!(targetView instanceof HistoryItem)) {
            return;
        }
        HistoryItem historyItem = (HistoryItem) targetView;

        // Inflate the menu
        Activity parent = getActivity();
        MenuInflater inflater = parent.getMenuInflater();
        inflater.inflate(R.menu.historycontext, menu);

        // Setup the header
        if (mContextHeader == null) {
            mContextHeader = new HistoryItem(parent, false);
            mContextHeader.setEnableScrolling(true);
        } else if (mContextHeader.getParent() != null) {
            ((ViewGroup) mContextHeader.getParent()).removeView(mContextHeader);
        }
        historyItem.copyTo(mContextHeader);
        menu.setHeaderView(mContextHeader);

        // Only show open in new tab if it was not explicitly disabled
        if (mDisableNewWindow) {
            menu.findItem(R.id.new_window_context_menu_id).setVisible(false);
        }
        // For a bookmark, provide the option to remove it from bookmarks
        if (historyItem.isBookmark()) {
            MenuItem item = menu.findItem(R.id.save_to_bookmarks_menu_id);
            item.setTitle(R.string.remove_from_bookmarks);
        }
        // decide whether to show the share link option
        PackageManager pm = parent.getPackageManager();
        Intent send = new Intent(Intent.ACTION_SEND);
        send.setType("text/plain");
        ResolveInfo ri = pm.resolveActivity(send, PackageManager.MATCH_DEFAULT_ONLY);
        menu.findItem(R.id.share_link_context_menu_id).setVisible(ri != null);

        super.onCreateContextMenu(menu, v, menuInfo);
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        ContextMenuInfo menuInfo = item.getMenuInfo();
        if (menuInfo == null) {
            return false;
        }
        View targetView = getTargetView(menuInfo);
        if (!(targetView instanceof HistoryItem)) {
            return false;
        }
        HistoryItem historyItem = (HistoryItem) targetView;
        String url = historyItem.getUrl();
        String title = historyItem.getName();
        Activity activity = getActivity();
        switch (item.getItemId()) {
            case R.id.open_context_menu_id:
                mCallback.openUrl(url);
                return true;
            case R.id.new_window_context_menu_id:
                mCallback.openInNewTab(url);
                return true;
            case R.id.save_to_bookmarks_menu_id:
                if (historyItem.isBookmark()) {
                    Bookmarks.removeFromBookmarks(activity, activity.getContentResolver(),
                            url, title);
                } else {
                    Browser.saveBookmark(activity, title, url);
                }
                return true;
            case R.id.share_link_context_menu_id:
                Browser.sendString(activity, url,
                        activity.getText(R.string.choosertitle_sharevia).toString());
                return true;
            case R.id.copy_url_context_menu_id:
                copy(url);
                return true;
            case R.id.delete_context_menu_id:
                Browser.deleteFromHistory(activity.getContentResolver(), url);
                return true;
            case R.id.homepage_context_menu_id:
                BrowserSettings.getInstance().setHomePage(url);
                Toast.makeText(activity, R.string.homepage_set, Toast.LENGTH_LONG).show();
                return true;
            default:
                break;
        }
        return super.onContextItemSelected(item);
    }

    private static abstract class HistoryWrapper extends BaseAdapter {

        protected HistoryAdapter mAdapter;
        private DataSetObserver mObserver = new DataSetObserver() {
            @Override
            public void onChanged() {
                super.onChanged();
                notifyDataSetChanged();
            }

            @Override
            public void onInvalidated() {
                super.onInvalidated();
                notifyDataSetInvalidated();
            }
        };

        public HistoryWrapper(HistoryAdapter adapter) {
            mAdapter = adapter;
            mAdapter.registerDataSetObserver(mObserver);
        }

    }
    private static class HistoryGroupWrapper extends HistoryWrapper {

        public HistoryGroupWrapper(HistoryAdapter adapter) {
            super(adapter);
        }

        @Override
        public int getCount() {
            return mAdapter.getGroupCount();
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            return mAdapter.getGroupView(position, false, convertView, parent);
        }

    }

    private static class HistoryChildWrapper extends HistoryWrapper {

        private int mSelectedGroup;

        public HistoryChildWrapper(HistoryAdapter adapter) {
            super(adapter);
        }

        void setSelectedGroup(int groupPosition) {
            mSelectedGroup = groupPosition;
            notifyDataSetChanged();
        }

        @Override
        public int getCount() {
            return mAdapter.getChildrenCount(mSelectedGroup);
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            return mAdapter.getChildView(mSelectedGroup, position,
                    false, convertView, parent);
        }

    }

    private class HistoryAdapter extends DateSortedExpandableListAdapter {

        private Cursor mMostVisited, mHistoryCursor;
        Drawable mFaviconBackground;

        HistoryAdapter(Context context) {
            super(context, HistoryQuery.INDEX_DATE_LAST_VISITED);
            mFaviconBackground = BookmarkUtils.createListFaviconBackground(context);
        }

        @Override
        public void changeCursor(Cursor cursor) {
            mHistoryCursor = cursor;
            super.changeCursor(cursor);
        }

        void changeMostVisitedCursor(Cursor cursor) {
            if (mMostVisited == cursor) {
                return;
            }
            if (mMostVisited != null) {
                mMostVisited.unregisterDataSetObserver(mDataSetObserver);
                mMostVisited.close();
            }
            mMostVisited = cursor;
            if (mMostVisited != null) {
                mMostVisited.registerDataSetObserver(mDataSetObserver);
            }
            notifyDataSetChanged();
        }

        @Override
        public long getChildId(int groupPosition, int childPosition) {
            if (moveCursorToChildPosition(groupPosition, childPosition)) {
                Cursor cursor = getCursor(groupPosition);
                return cursor.getLong(HistoryQuery.INDEX_ID);
            }
            return 0;
        }

        @Override
        public int getGroupCount() {
            return super.getGroupCount() + (!isMostVisitedEmpty() ? 1 : 0);
        }

        @Override
        public int getChildrenCount(int groupPosition) {
            if (groupPosition >= super.getGroupCount()) {
                if (isMostVisitedEmpty()) {
                    return 0;
                }
                return mMostVisited.getCount();
            }
            return super.getChildrenCount(groupPosition);
        }

        @Override
        public boolean isEmpty() {
            if (!super.isEmpty()) {
                return false;
            }
            return isMostVisitedEmpty();
        }

        private boolean isMostVisitedEmpty() {
            return mMostVisited == null
                    || mMostVisited.isClosed()
                    || mMostVisited.getCount() == 0;
        }

        Cursor getCursor(int groupPosition) {
            if (groupPosition >= super.getGroupCount()) {
                return mMostVisited;
            }
            return mHistoryCursor;
        }

        @Override
        public View getGroupView(int groupPosition, boolean isExpanded,
                View convertView, ViewGroup parent) {
            if (groupPosition >= super.getGroupCount()) {
                if (mMostVisited == null || mMostVisited.isClosed()) {
                    throw new IllegalStateException("Data is not valid");
                }
                TextView item;
                if (null == convertView || !(convertView instanceof TextView)) {
                    LayoutInflater factory = LayoutInflater.from(getContext());
                    item = (TextView) factory.inflate(R.layout.history_header, null);
                } else {
                    item = (TextView) convertView;
                }
                item.setText(R.string.tab_most_visited);
                return item;
            }
            return super.getGroupView(groupPosition, isExpanded, convertView, parent);
        }

        @Override
        boolean moveCursorToChildPosition(
                int groupPosition, int childPosition) {
            if (groupPosition >= super.getGroupCount()) {
                if (mMostVisited != null && !mMostVisited.isClosed()) {
                    mMostVisited.moveToPosition(childPosition);
                    return true;
                }
                return false;
            }
            return super.moveCursorToChildPosition(groupPosition, childPosition);
        }

        @Override
        public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
                View convertView, ViewGroup parent) {
            HistoryItem item;
            if (null == convertView || !(convertView instanceof HistoryItem)) {
                item = new HistoryItem(getContext());
                // Add padding on the left so it will be indented from the
                // arrows on the group views.
                item.setPadding(item.getPaddingLeft() + 10,
                        item.getPaddingTop(),
                        item.getPaddingRight(),
                        item.getPaddingBottom());
                item.setFaviconBackground(mFaviconBackground);
            } else {
                item = (HistoryItem) convertView;
            }

            // Bail early if the Cursor is closed.
            if (!moveCursorToChildPosition(groupPosition, childPosition)) {
                return item;
            }

            Cursor cursor = getCursor(groupPosition);
            item.setName(cursor.getString(HistoryQuery.INDEX_TITE));
            String url = cursor.getString(HistoryQuery.INDEX_URL);
            item.setUrl(url);
            byte[] data = cursor.getBlob(HistoryQuery.INDEX_FAVICON);
            if (data != null) {
                item.setFavicon(BitmapFactory.decodeByteArray(data, 0,
                        data.length));
            } else {
                item.setFavicon(null);
            }
            item.setIsBookmark(cursor.getInt(HistoryQuery.INDEX_IS_BOOKMARK) == 1);
            return item;
        }
    }
}
