/*
 * 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))
                        .setIcon(android.R.drawable.ic_dialog_alert)
                        .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();
        }
    }
}
