/*
 * 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.settings.quicklaunch;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.provider.Settings.Bookmarks;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.View;
import android.widget.AdapterView;

import com.android.settings.R;

import java.net.URISyntaxException;

/**
 * Settings activity for quick launch.
 * <p>
 * Shows a list of possible shortcuts, the current application each is bound to,
 * and allows choosing a new bookmark for a shortcut.
 */
public class QuickLaunchSettings extends PreferenceActivity implements
        AdapterView.OnItemLongClickListener, DialogInterface.OnClickListener {

    private static final String TAG = "QuickLaunchSettings";

    private static final String KEY_SHORTCUT_CATEGORY = "shortcut_category";

    private static final int DIALOG_CLEAR_SHORTCUT = 0;

    private static final int REQUEST_PICK_BOOKMARK = 1;

    private static final int COLUMN_SHORTCUT = 0;
    private static final int COLUMN_TITLE = 1;
    private static final int COLUMN_INTENT = 2;
    private static final String[] sProjection = new String[] {
            Bookmarks.SHORTCUT, Bookmarks.TITLE, Bookmarks.INTENT
    };
    private static final String sShortcutSelection = Bookmarks.SHORTCUT + "=?";
    
    private Handler mUiHandler = new Handler();
    
    private static final String DEFAULT_BOOKMARK_FOLDER = "@quicklaunch";
    /** Cursor for Bookmarks provider. */
    private Cursor mBookmarksCursor;
    /** Listens for changes to Bookmarks provider. */
    private BookmarksObserver mBookmarksObserver;
    /** Used to keep track of which shortcuts have bookmarks. */
    private SparseBooleanArray mBookmarkedShortcuts;
    
    /** Preference category to hold the shortcut preferences. */
    private PreferenceGroup mShortcutGroup;
    /** Mapping of a shortcut to its preference. */
    private SparseArray<ShortcutPreference> mShortcutToPreference;

    /** The bookmark title of the shortcut that is being cleared. */
    private CharSequence mClearDialogBookmarkTitle;
    private static final String CLEAR_DIALOG_BOOKMARK_TITLE = "CLEAR_DIALOG_BOOKMARK_TITLE";
    /** The shortcut that is being cleared. */
    private char mClearDialogShortcut;
    private static final String CLEAR_DIALOG_SHORTCUT = "CLEAR_DIALOG_SHORTCUT";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        addPreferencesFromResource(R.xml.quick_launch_settings);
        
        mShortcutGroup = (PreferenceGroup) findPreference(KEY_SHORTCUT_CATEGORY);
        mShortcutToPreference = new SparseArray<ShortcutPreference>();
        mBookmarksObserver = new BookmarksObserver(mUiHandler);
        initShortcutPreferences();
        mBookmarksCursor = managedQuery(Bookmarks.CONTENT_URI, sProjection, null, null);
        getListView().setOnItemLongClickListener(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        getContentResolver().registerContentObserver(Bookmarks.CONTENT_URI, true,
                mBookmarksObserver);
        refreshShortcuts();
    }
    
    @Override
    protected void onPause() {
        super.onPause();
        getContentResolver().unregisterContentObserver(mBookmarksObserver);
    }

    @Override
    protected void onRestoreInstanceState(Bundle state) {
        super.onRestoreInstanceState(state);
        
        // Restore the clear dialog's info
        mClearDialogBookmarkTitle = state.getString(CLEAR_DIALOG_BOOKMARK_TITLE);
        mClearDialogShortcut = (char) state.getInt(CLEAR_DIALOG_SHORTCUT, 0);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        
        // Save the clear dialog's info
        outState.putCharSequence(CLEAR_DIALOG_BOOKMARK_TITLE, mClearDialogBookmarkTitle);
        outState.putInt(CLEAR_DIALOG_SHORTCUT, mClearDialogShortcut);
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
            
            case DIALOG_CLEAR_SHORTCUT: {
                // Create the dialog for clearing a shortcut
                return new AlertDialog.Builder(this)
                        .setTitle(getString(R.string.quick_launch_clear_dialog_title))
                        .setIconAttribute(android.R.attr.alertDialogIcon)
                        .setMessage(getString(R.string.quick_launch_clear_dialog_message,
                                mClearDialogShortcut, mClearDialogBookmarkTitle))
                        .setPositiveButton(R.string.quick_launch_clear_ok_button, this)
                        .setNegativeButton(R.string.quick_launch_clear_cancel_button, this)
                        .create();
            }
        }
        
        return super.onCreateDialog(id);
    }
    
    @Override
    protected void onPrepareDialog(int id, Dialog dialog) {
        switch (id) {
            
            case DIALOG_CLEAR_SHORTCUT: {
                AlertDialog alertDialog = (AlertDialog) dialog;
                alertDialog.setMessage(getString(R.string.quick_launch_clear_dialog_message,
                        mClearDialogShortcut, mClearDialogBookmarkTitle));
            }
        }
    }

    private void showClearDialog(ShortcutPreference pref) {

        if (!pref.hasBookmark()) return;
        
        mClearDialogBookmarkTitle = pref.getTitle();
        mClearDialogShortcut = pref.getShortcut();
        showDialog(DIALOG_CLEAR_SHORTCUT);
    }
    
    public void onClick(DialogInterface dialog, int which) {
        if (mClearDialogShortcut > 0 && which == AlertDialog.BUTTON_POSITIVE) {
            // Clear the shortcut
            clearShortcut(mClearDialogShortcut);
        }
        mClearDialogBookmarkTitle = null;
        mClearDialogShortcut = 0;
    }

    private void clearShortcut(char shortcut) {
        getContentResolver().delete(Bookmarks.CONTENT_URI, sShortcutSelection,
                new String[] { String.valueOf((int) shortcut) });
    }
    
    @Override
    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
        if (!(preference instanceof ShortcutPreference)) return false;

        // Open the screen to pick a bookmark for this shortcut
        ShortcutPreference pref = (ShortcutPreference) preference;
        Intent intent = new Intent(this, BookmarkPicker.class);
        intent.putExtra(BookmarkPicker.EXTRA_SHORTCUT, pref.getShortcut());
        startActivityForResult(intent, REQUEST_PICK_BOOKMARK);
        
        return true;
    }

    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
        
        // Open the clear shortcut dialog
        Preference pref = (Preference) getPreferenceScreen().getRootAdapter().getItem(position);
        if (!(pref instanceof ShortcutPreference)) return false;
        showClearDialog((ShortcutPreference) pref);
        return true;
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != RESULT_OK) {
            return;
        }

        if (requestCode == REQUEST_PICK_BOOKMARK) {
            
            // Returned from the 'pick bookmark for this shortcut' screen
            if (data == null) {
                Log.w(TAG, "Result from bookmark picker does not have an intent.");
                return;
            }

            char shortcut = data.getCharExtra(BookmarkPicker.EXTRA_SHORTCUT, (char) 0);
            updateShortcut(shortcut, data);
            
        } else {
            super.onActivityResult(requestCode, resultCode, data);
        }
    }

    private void updateShortcut(char shortcut, Intent intent) {
        // Update the bookmark for a shortcut
        // Pass an empty title so it gets resolved each time this bookmark is
        // displayed (since the locale could change after we insert into the provider).
        Bookmarks.add(getContentResolver(), intent, "", DEFAULT_BOOKMARK_FOLDER, shortcut, 0);
    }
    
    private ShortcutPreference getOrCreatePreference(char shortcut) {
        ShortcutPreference pref = mShortcutToPreference.get(shortcut);
        if (pref != null) {
            return pref;
        } else {
            Log.w(TAG, "Unknown shortcut '" + shortcut + "', creating preference anyway");
            return createPreference(shortcut);
        }
    }
    
    private ShortcutPreference createPreference(char shortcut) {
        ShortcutPreference pref = new ShortcutPreference(QuickLaunchSettings.this, shortcut);
        mShortcutGroup.addPreference(pref);
        mShortcutToPreference.put(shortcut, pref);
        return pref;
    }

    private void initShortcutPreferences() {
        
        /** Whether the shortcut has been seen already.  The array index is the shortcut. */
        SparseBooleanArray shortcutSeen = new SparseBooleanArray();
        KeyCharacterMap keyMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);

        // Go through all the key codes and create a preference for the appropriate keys
        for (int keyCode = KeyEvent.getMaxKeyCode() - 1; keyCode >= 0; keyCode--) {
            // Get the label for the primary char on the key that produces this key code
            char shortcut = (char) Character.toLowerCase(keyMap.getDisplayLabel(keyCode));
            if (shortcut == 0 || shortcutSeen.get(shortcut, false)) continue;
            // TODO: need a to tell if the current keyboard can produce this key code, for now
            // only allow the letter or digits
            if (!Character.isLetterOrDigit(shortcut)) continue;
            shortcutSeen.put(shortcut, true);
            
            createPreference(shortcut);
        }
    }
    
    private synchronized void refreshShortcuts() {
        Cursor c = mBookmarksCursor;
        if (c == null) {
            // Haven't finished querying yet
            return;
        }
        
        if (!c.requery()) {
            Log.e(TAG, "Could not requery cursor when refreshing shortcuts.");
            return;
        }
        
        /**
         * We use the previous bookmarked shortcuts array to filter out those
         * shortcuts that had bookmarks before this method call, and don't after
         * (so we can set the preferences to be without bookmarks).
         */
        SparseBooleanArray noLongerBookmarkedShortcuts = mBookmarkedShortcuts;
        SparseBooleanArray newBookmarkedShortcuts = new SparseBooleanArray(); 
        while (c.moveToNext()) {
            char shortcut = Character.toLowerCase((char) c.getInt(COLUMN_SHORTCUT));
            if (shortcut == 0) continue;
            
            ShortcutPreference pref = getOrCreatePreference(shortcut);
            CharSequence title = Bookmarks.getTitle(this, c);

            /*
             * The title retrieved from Bookmarks.getTitle() will be in
             * the original boot locale, not the current locale.
             * Try to look up a localized title from the PackageManager.
             */
            int intentColumn = c.getColumnIndex(Bookmarks.INTENT);
            String intentUri = c.getString(intentColumn);
            PackageManager packageManager = getPackageManager();
            try {
                Intent intent = Intent.parseUri(intentUri, 0);
                ResolveInfo info = packageManager.resolveActivity(intent, 0);
                if (info != null) {
                    title = info.loadLabel(packageManager);
                }
            } catch (URISyntaxException e) {
                // Just use the non-localized title, then.
            }

            pref.setTitle(title);
            pref.setSummary(getString(R.string.quick_launch_shortcut,
                    String.valueOf(shortcut)));
            pref.setHasBookmark(true);
            
            newBookmarkedShortcuts.put(shortcut, true);
            if (noLongerBookmarkedShortcuts != null) {
                // After this loop, the shortcuts with value true in this array
                // will no longer have bookmarks
                noLongerBookmarkedShortcuts.put(shortcut, false);
            }
        }
        
        if (noLongerBookmarkedShortcuts != null) {
            for (int i = noLongerBookmarkedShortcuts.size() - 1; i >= 0; i--) {
                if (noLongerBookmarkedShortcuts.valueAt(i)) {
                    // True, so there is no longer a bookmark for this shortcut
                    char shortcut = (char) noLongerBookmarkedShortcuts.keyAt(i);
                    ShortcutPreference pref = mShortcutToPreference.get(shortcut);
                    if (pref != null) {
                        pref.setHasBookmark(false);
                    }
                }
            }
        }
        
        mBookmarkedShortcuts = newBookmarkedShortcuts;
        
        c.deactivate();
    }

    private class BookmarksObserver extends ContentObserver {

        public BookmarksObserver(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            
            refreshShortcuts();
        }
    }
}
