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

import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import static android.util.Log.*;
import android.os.Process;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Comparator;
import java.util.concurrent.atomic.AtomicInteger;
import java.lang.ref.WeakReference;
import java.text.Collator;
import java.net.URISyntaxException;

/**
 * Maintains in-memory state of the Launcher. It is expected that there should be only one
 * LauncherModel object held in a static. Also provide APIs for updating the database state
 * for the Launcher.
 */
public class LauncherModel {
    static final boolean DEBUG_LOADERS = true;
    static final String LOG_TAG = "HomeLoaders";

    private static final int UI_NOTIFICATION_RATE = 4;
    private static final int DEFAULT_APPLICATIONS_NUMBER = 42;
    private static final long APPLICATION_NOT_RESPONDING_TIMEOUT = 5000;
    private static final int INITIAL_ICON_CACHE_CAPACITY = 50;

    private static final Collator sCollator = Collator.getInstance();

    private boolean mApplicationsLoaded;
    private boolean mDesktopItemsLoaded;

    private ArrayList<ItemInfo> mDesktopItems;
    private ArrayList<LauncherAppWidgetInfo> mDesktopAppWidgets;
    private HashMap<Long, FolderInfo> mFolders;

    private ArrayList<ApplicationInfo> mApplications;
    private ApplicationsAdapter mApplicationsAdapter;
    private ApplicationsLoader mApplicationsLoader;
    private DesktopItemsLoader mDesktopItemsLoader;
    private Thread mApplicationsLoaderThread;
    private Thread mDesktopLoaderThread;

    private final HashMap<ComponentName, ApplicationInfo> mAppInfoCache =
            new HashMap<ComponentName, ApplicationInfo>(INITIAL_ICON_CACHE_CAPACITY);

    synchronized void abortLoaders() {
        if (mApplicationsLoader != null && mApplicationsLoader.isRunning()) {
            mApplicationsLoader.stop();
            mApplicationsLoaded = false;
        }

        if (mDesktopItemsLoader != null && mDesktopItemsLoader.isRunning()) {
            mDesktopItemsLoader.stop();
            mDesktopItemsLoaded = false;
        }
    }

    /**
     * Drop our cache of components to their lables & icons.  We do
     * this from Launcher when applications are added/removed.  It's a
     * bit overkill, but it's a rare operation anyway.
     */
    synchronized void dropApplicationCache() {
        mAppInfoCache.clear();
    }

    /**
     * Loads the list of installed applications in mApplications.
     *
     * @return true if the applications loader must be started
     *         (see startApplicationsLoader()), false otherwise.
     */
    synchronized boolean loadApplications(boolean isLaunching, Launcher launcher,
            boolean localeChanged) {

        if (DEBUG_LOADERS) d(LOG_TAG, "load applications");

        if (isLaunching && mApplicationsLoaded && !localeChanged) {
            mApplicationsAdapter = new ApplicationsAdapter(launcher, mApplications);
            if (DEBUG_LOADERS) d(LOG_TAG, "  --> applications loaded, return");
            return false;
        }

        stopAndWaitForApplicationsLoader();

        if (localeChanged) {
            dropApplicationCache();
        }

        if (mApplicationsAdapter == null || isLaunching || localeChanged) {
            mApplications = new ArrayList<ApplicationInfo>(DEFAULT_APPLICATIONS_NUMBER);
            mApplicationsAdapter = new ApplicationsAdapter(launcher, mApplications);
        }

        mApplicationsLoaded = false;

        if (!isLaunching) {
            startApplicationsLoaderLocked(launcher, false);
            return false;
        }

        return true;
    }

    private synchronized void stopAndWaitForApplicationsLoader() {
        if (mApplicationsLoader != null && mApplicationsLoader.isRunning()) {
            if (DEBUG_LOADERS) {
                d(LOG_TAG, "  --> wait for applications loader (" + mApplicationsLoader.mId + ")");
            }

            mApplicationsLoader.stop();
            // Wait for the currently running thread to finish, this can take a little
            // time but it should be well below the timeout limit
            try {
                mApplicationsLoaderThread.join(APPLICATION_NOT_RESPONDING_TIMEOUT);
            } catch (InterruptedException e) {
                // Empty
            }
        }
    }

    private synchronized void startApplicationsLoader(Launcher launcher, boolean isLaunching) {
        if (DEBUG_LOADERS) d(LOG_TAG, "  --> starting applications loader unlocked");
        startApplicationsLoaderLocked(launcher, isLaunching);
    }

    private void startApplicationsLoaderLocked(Launcher launcher, boolean isLaunching) {
        if (DEBUG_LOADERS) d(LOG_TAG, "  --> starting applications loader");

        stopAndWaitForApplicationsLoader();

        mApplicationsLoader = new ApplicationsLoader(launcher, isLaunching);
        mApplicationsLoaderThread = new Thread(mApplicationsLoader, "Applications Loader");
        mApplicationsLoaderThread.start();
    }

    synchronized void addPackage(Launcher launcher, String packageName) {
        if (mApplicationsLoader != null && mApplicationsLoader.isRunning()) {
            startApplicationsLoaderLocked(launcher, false);
            return;
        }

        if (packageName != null && packageName.length() > 0) {
            final PackageManager packageManager = launcher.getPackageManager();
            final List<ResolveInfo> matches = findActivitiesForPackage(packageManager, packageName);

            if (matches.size() > 0) {
                final ApplicationsAdapter adapter = mApplicationsAdapter;
                final HashMap<ComponentName, ApplicationInfo> cache = mAppInfoCache;

                for (ResolveInfo info : matches) {
                    adapter.setNotifyOnChange(false);
                    adapter.add(makeAndCacheApplicationInfo(packageManager, cache, info, launcher));
                }

                adapter.sort(new ApplicationInfoComparator());
                adapter.notifyDataSetChanged();
            }
        }
    }

    synchronized void removePackage(Launcher launcher, String packageName) {
        if (mApplicationsLoader != null && mApplicationsLoader.isRunning()) {
            dropApplicationCache(); // TODO: this could be optimized
            startApplicationsLoaderLocked(launcher, false);
            return;
        }

        if (packageName != null && packageName.length() > 0) {
            final ApplicationsAdapter adapter = mApplicationsAdapter;

            final List<ApplicationInfo> toRemove = new ArrayList<ApplicationInfo>();
            final int count = adapter.getCount();

            for (int i = 0; i < count; i++) {
                final ApplicationInfo applicationInfo = adapter.getItem(i);
                final Intent intent = applicationInfo.intent;
                final ComponentName component = intent.getComponent();
                if (packageName.equals(component.getPackageName())) {
                    toRemove.add(applicationInfo);
                }
            }

            final HashMap<ComponentName, ApplicationInfo> cache = mAppInfoCache;
            for (ApplicationInfo info : toRemove) {
                adapter.setNotifyOnChange(false);
                adapter.remove(info);
                cache.remove(info.intent.getComponent());
            }

            if (toRemove.size() > 0) {
                adapter.sort(new ApplicationInfoComparator());
                adapter.notifyDataSetChanged();
            }
        }
    }

    synchronized void updatePackage(Launcher launcher, String packageName) {
        if (mApplicationsLoader != null && mApplicationsLoader.isRunning()) {
            startApplicationsLoaderLocked(launcher, false);
            return;
        }

        if (packageName != null && packageName.length() > 0) {
            final PackageManager packageManager = launcher.getPackageManager();
            final ApplicationsAdapter adapter = mApplicationsAdapter;

            final List<ResolveInfo> matches = findActivitiesForPackage(packageManager, packageName);
            final int count = matches.size();

            boolean changed = false;

            for (int i = 0; i < count; i++) {
                final ResolveInfo info = matches.get(i);
                final ApplicationInfo applicationInfo = findIntent(adapter,
                        info.activityInfo.applicationInfo.packageName, info.activityInfo.name);
                if (applicationInfo != null) {
                    updateAndCacheApplicationInfo(packageManager, info, applicationInfo, launcher);
                    changed = true;
                }
            }

            if (syncLocked(launcher, packageName)) changed = true;

            if (changed) {
                adapter.sort(new ApplicationInfoComparator());
                adapter.notifyDataSetChanged();
            }
        }
    }

    private void updateAndCacheApplicationInfo(PackageManager packageManager, ResolveInfo info,
            ApplicationInfo applicationInfo, Context context) {

        updateApplicationInfoTitleAndIcon(packageManager, info, applicationInfo, context);

        ComponentName componentName = new ComponentName(
                info.activityInfo.applicationInfo.packageName, info.activityInfo.name);
        mAppInfoCache.put(componentName, applicationInfo);
    }

    synchronized void syncPackage(Launcher launcher, String packageName) {
        if (mApplicationsLoader != null && mApplicationsLoader.isRunning()) {
            startApplicationsLoaderLocked(launcher, false);
            return;
        }

        if (packageName != null && packageName.length() > 0) {
            if (syncLocked(launcher, packageName)) {
                final ApplicationsAdapter adapter = mApplicationsAdapter;
                adapter.sort(new ApplicationInfoComparator());
                adapter.notifyDataSetChanged();                
            }
        }
    }

    private boolean syncLocked(Launcher launcher, String packageName) {
        final PackageManager packageManager = launcher.getPackageManager();
        final List<ResolveInfo> matches = findActivitiesForPackage(packageManager, packageName);

        if (matches.size() > 0) {
            final ApplicationsAdapter adapter = mApplicationsAdapter;

            // Find disabled activities and remove them from the adapter
            boolean removed = removeDisabledActivities(packageName, matches, adapter);
            // Find enable activities and add them to the adapter
            // Also updates existing activities with new labels/icons
            boolean added = addEnabledAndUpdateActivities(matches, adapter, launcher);

            return added || removed;
        }

        return false;
    }

    private static List<ResolveInfo> findActivitiesForPackage(PackageManager packageManager,
            String packageName) {

        final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
        mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);

        final List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);
        final List<ResolveInfo> matches = new ArrayList<ResolveInfo>();

        if (apps != null) {
            // Find all activities that match the packageName
            int count = apps.size();
            for (int i = 0; i < count; i++) {
                final ResolveInfo info = apps.get(i);
                final ActivityInfo activityInfo = info.activityInfo;
                if (packageName.equals(activityInfo.packageName)) {
                    matches.add(info);
                }
            }
        }

        return matches;
    }

    private boolean addEnabledAndUpdateActivities(List<ResolveInfo> matches,
            ApplicationsAdapter adapter, Launcher launcher) {

        final List<ApplicationInfo> toAdd = new ArrayList<ApplicationInfo>();
        final int count = matches.size();

        boolean changed = false;

        for (int i = 0; i < count; i++) {
            final ResolveInfo info = matches.get(i);
            final ApplicationInfo applicationInfo = findIntent(adapter,
                    info.activityInfo.applicationInfo.packageName, info.activityInfo.name);
            if (applicationInfo == null) {
                toAdd.add(makeAndCacheApplicationInfo(launcher.getPackageManager(),
                        mAppInfoCache, info, launcher));
                changed = true;
            } else {
                updateAndCacheApplicationInfo(
                        launcher.getPackageManager(), info, applicationInfo, launcher);
                changed = true;
            }
        }

        for (ApplicationInfo info : toAdd) {
            adapter.setNotifyOnChange(false);
            adapter.add(info);
        }

        return changed;
    }

    private boolean removeDisabledActivities(String packageName, List<ResolveInfo> matches,
            ApplicationsAdapter adapter) {

        final List<ApplicationInfo> toRemove = new ArrayList<ApplicationInfo>();
        final int count = adapter.getCount();

        boolean changed = false;

        for (int i = 0; i < count; i++) {
            final ApplicationInfo applicationInfo = adapter.getItem(i);
            final Intent intent = applicationInfo.intent;
            final ComponentName component = intent.getComponent();
            if (packageName.equals(component.getPackageName())) {
                if (!findIntent(matches, component)) {
                    toRemove.add(applicationInfo);
                    changed = true;
                }
            }
        }

        final HashMap<ComponentName, ApplicationInfo> cache = mAppInfoCache;
        for (ApplicationInfo info : toRemove) {
            adapter.setNotifyOnChange(false);
            adapter.remove(info);
            cache.remove(info.intent.getComponent());
        }

        return changed;
    }

    private static ApplicationInfo findIntent(ApplicationsAdapter adapter, String packageName,
            String name) {

        final int count = adapter.getCount();
        for (int i = 0; i < count; i++) {
            final ApplicationInfo applicationInfo = adapter.getItem(i);
            final Intent intent = applicationInfo.intent;
            final ComponentName component = intent.getComponent();
            if (packageName.equals(component.getPackageName()) &&
                    name.equals(component.getClassName())) {
                return applicationInfo;
            }
        }

        return null;
    }

    private static boolean findIntent(List<ResolveInfo> apps, ComponentName component) {
        final String className = component.getClassName();
        for (ResolveInfo info : apps) {
            final ActivityInfo activityInfo = info.activityInfo;
            if (activityInfo.name.equals(className)) {
                return true;
            }
        }
        return false;
    }

    Drawable getApplicationInfoIcon(PackageManager manager, ApplicationInfo info) {
        final ResolveInfo resolveInfo = manager.resolveActivity(info.intent, 0);
        if (resolveInfo == null) {
            return null;
        }

        ComponentName componentName = new ComponentName(
                resolveInfo.activityInfo.applicationInfo.packageName,
                resolveInfo.activityInfo.name);
        ApplicationInfo application = mAppInfoCache.get(componentName);

        if (application == null) {
            return resolveInfo.activityInfo.loadIcon(manager);
        }

        return application.icon;
    }

    private static ApplicationInfo makeAndCacheApplicationInfo(PackageManager manager,
            HashMap<ComponentName, ApplicationInfo> appInfoCache, ResolveInfo info,
            Context context) {

        ComponentName componentName = new ComponentName(
                info.activityInfo.applicationInfo.packageName,
                info.activityInfo.name);
        ApplicationInfo application = appInfoCache.get(componentName);

        if (application == null) {
            application = new ApplicationInfo();
            application.container = ItemInfo.NO_ID;

            updateApplicationInfoTitleAndIcon(manager, info, application, context);

            application.setActivity(componentName,
                    Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

            appInfoCache.put(componentName, application);
        }

        return application;
    }

    private static void updateApplicationInfoTitleAndIcon(PackageManager manager, ResolveInfo info,
            ApplicationInfo application, Context context) {

        application.title = info.loadLabel(manager);
        if (application.title == null) {
            application.title = info.activityInfo.name;
        }

        application.icon =
                Utilities.createIconThumbnail(info.activityInfo.loadIcon(manager), context);
        application.filtered = false;
    }

    private static final AtomicInteger sAppsLoaderCount = new AtomicInteger(1);

    private class ApplicationsLoader implements Runnable {
        private final WeakReference<Launcher> mLauncher;

        private volatile boolean mStopped;
        private volatile boolean mRunning;
        private final boolean mIsLaunching;
        private final int mId;

        ApplicationsLoader(Launcher launcher, boolean isLaunching) {
            mIsLaunching = isLaunching;
            mLauncher = new WeakReference<Launcher>(launcher);
            mRunning = true;
            mId = sAppsLoaderCount.getAndIncrement();
        }

        void stop() {
            mStopped = true;
        }

        boolean isRunning() {
            return mRunning;
        }

        public void run() {
            if (DEBUG_LOADERS) d(LOG_TAG, "  ----> running applications loader (" + mId + ")");

            // Elevate priority when Home launches for the first time to avoid
            // starving at boot time. Staring at a blank home is not cool.
            android.os.Process.setThreadPriority(mIsLaunching ? Process.THREAD_PRIORITY_DEFAULT :
                    Process.THREAD_PRIORITY_BACKGROUND);

            final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
            mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);

            final Launcher launcher = mLauncher.get();
            final PackageManager manager = launcher.getPackageManager();
            final List<ResolveInfo> apps = manager.queryIntentActivities(mainIntent, 0);

            if (apps != null && !mStopped) {
                final int count = apps.size();
                // Can be set to null on the UI thread by the unbind() method
                // Do not access without checking for null first
                final ApplicationsAdapter applicationList = mApplicationsAdapter;

                ChangeNotifier action = new ChangeNotifier(applicationList, true);
                final HashMap<ComponentName, ApplicationInfo> appInfoCache = mAppInfoCache;

                for (int i = 0; i < count && !mStopped; i++) {
                    ResolveInfo info = apps.get(i);
                    ApplicationInfo application =
                        makeAndCacheApplicationInfo(manager, appInfoCache, info, launcher);

                    if (action.add(application) && !mStopped) {
                        launcher.runOnUiThread(action);
                        action = new ChangeNotifier(applicationList, false);
                    }
                }

                launcher.runOnUiThread(action);
            }

            if (!mStopped) {
                mApplicationsLoaded = true;
            } else {
                if (DEBUG_LOADERS) d(LOG_TAG, "  ----> applications loader stopped (" + mId + ")");                                
            }
            mRunning = false;
        }
    }

    private static class ChangeNotifier implements Runnable {
        private final ApplicationsAdapter mApplicationList;
        private final ArrayList<ApplicationInfo> mBuffer;

        private boolean mFirst = true;

        ChangeNotifier(ApplicationsAdapter applicationList, boolean first) {
            mApplicationList = applicationList;
            mFirst = first;
            mBuffer = new ArrayList<ApplicationInfo>(UI_NOTIFICATION_RATE);
        }

        public void run() {
            final ApplicationsAdapter applicationList = mApplicationList;
            // Can be set to null on the UI thread by the unbind() method
            if (applicationList == null) return;

            if (mFirst) {
                applicationList.setNotifyOnChange(false);
                applicationList.clear();
                if (DEBUG_LOADERS) d(LOG_TAG, "  ----> cleared application list");
                mFirst = false;
            }

            final ArrayList<ApplicationInfo> buffer = mBuffer;
            final int count = buffer.size();

            for (int i = 0; i < count; i++) {
                applicationList.setNotifyOnChange(false);
                applicationList.add(buffer.get(i));
            }

            buffer.clear();

            applicationList.sort(new ApplicationInfoComparator());
            applicationList.notifyDataSetChanged();
        }

        boolean add(ApplicationInfo application) {
            final ArrayList<ApplicationInfo> buffer = mBuffer;
            buffer.add(application);
            return buffer.size() >= UI_NOTIFICATION_RATE;
        }
    }

    static class ApplicationInfoComparator implements Comparator<ApplicationInfo> {
        public final int compare(ApplicationInfo a, ApplicationInfo b) {
            return sCollator.compare(a.title.toString(), b.title.toString());
        }
    }

    boolean isDesktopLoaded() {
        return mDesktopItems != null && mDesktopAppWidgets != null && mDesktopItemsLoaded;
    }

    /**
     * Loads all of the items on the desktop, in folders, or in the dock.
     * These can be apps, shortcuts or widgets
     */
    void loadUserItems(boolean isLaunching, Launcher launcher, boolean localeChanged,
            boolean loadApplications) {
        if (DEBUG_LOADERS) d(LOG_TAG, "loading user items");

        if (isLaunching && isDesktopLoaded()) {
            if (DEBUG_LOADERS) d(LOG_TAG, "  --> items loaded, return");
            if (loadApplications) startApplicationsLoader(launcher, true);
            // We have already loaded our data from the DB
            launcher.onDesktopItemsLoaded();
            return;
        }

        if (mDesktopItemsLoader != null && mDesktopItemsLoader.isRunning()) {
            if (DEBUG_LOADERS) d(LOG_TAG, "  --> stopping workspace loader");
            mDesktopItemsLoader.stop();
            // Wait for the currently running thread to finish, this can take a little
            // time but it should be well below the timeout limit
            try {
                mDesktopLoaderThread.join(APPLICATION_NOT_RESPONDING_TIMEOUT);
            } catch (InterruptedException e) {
                // Empty
            }

            // If the thread we are interrupting was tasked to load the list of
            // applications make sure we keep that information in the new loader
            // spawned below
            // note: we don't apply this to localeChanged because the thread can
            // only be stopped *after* the localeChanged handling has occured
            loadApplications = mDesktopItemsLoader.mLoadApplications;
        }

        if (DEBUG_LOADERS) d(LOG_TAG, "  --> starting workspace loader");
        mDesktopItemsLoaded = false;
        mDesktopItemsLoader = new DesktopItemsLoader(launcher, localeChanged, loadApplications,
                isLaunching);
        mDesktopLoaderThread = new Thread(mDesktopItemsLoader, "Desktop Items Loader");
        mDesktopLoaderThread.start();
    }

    private static void updateShortcutLabels(ContentResolver resolver, PackageManager manager) {
        final Cursor c = resolver.query(LauncherSettings.Favorites.CONTENT_URI,
                new String[] { LauncherSettings.Favorites._ID, LauncherSettings.Favorites.TITLE,
                        LauncherSettings.Favorites.INTENT, LauncherSettings.Favorites.ITEM_TYPE },
                null, null, null);

        final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
        final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
        final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
        final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);

        // boolean changed = false;

        try {
            while (c.moveToNext()) {
                try {
                    if (c.getInt(itemTypeIndex) !=
                            LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
                        continue;
                    }

                    final String intentUri = c.getString(intentIndex);
                    if (intentUri != null) {
                        final Intent shortcut = Intent.parseUri(intentUri, 0);
                        if (Intent.ACTION_MAIN.equals(shortcut.getAction())) {
                            final ComponentName name = shortcut.getComponent();
                            if (name != null) {
                                final ActivityInfo activityInfo = manager.getActivityInfo(name, 0);
                                final String title = c.getString(titleIndex);
                                String label = getLabel(manager, activityInfo);

                                if (title == null || !title.equals(label)) {
                                    final ContentValues values = new ContentValues();
                                    values.put(LauncherSettings.Favorites.TITLE, label);

                                    resolver.update(
                                            LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION,
                                            values, "_id=?",
                                            new String[] { String.valueOf(c.getLong(idIndex)) });

                                    // changed = true;
                                }
                            }
                        }
                    }
                } catch (URISyntaxException e) {
                    // Ignore
                } catch (PackageManager.NameNotFoundException e) {
                    // Ignore
                }
            }
        } finally {
            c.close();
        }

        // if (changed) resolver.notifyChange(Settings.Favorites.CONTENT_URI, null);
    }

    private static String getLabel(PackageManager manager, ActivityInfo activityInfo) {
        String label = activityInfo.loadLabel(manager).toString();
        if (label == null) {
            label = manager.getApplicationLabel(activityInfo.applicationInfo).toString();
            if (label == null) {
                label = activityInfo.name;
            }
        }
        return label;
    }

    private class DesktopItemsLoader implements Runnable {
        private volatile boolean mStopped;
        private volatile boolean mRunning;

        private final WeakReference<Launcher> mLauncher;
        private final boolean mLocaleChanged;
        private final boolean mLoadApplications;
        private final boolean mIsLaunching;

        DesktopItemsLoader(Launcher launcher, boolean localeChanged, boolean loadApplications,
                boolean isLaunching) {
            mLoadApplications = loadApplications;
            mIsLaunching = isLaunching;
            mLauncher = new WeakReference<Launcher>(launcher);
            mLocaleChanged = localeChanged;
        }

        void stop() {
            mStopped = true;
        }

        boolean isRunning() {
            return mRunning;
        }

        public void run() {
            mRunning = true;

            android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);

            final Launcher launcher = mLauncher.get();
            final ContentResolver contentResolver = launcher.getContentResolver();
            final PackageManager manager = launcher.getPackageManager();

            if (mLocaleChanged) {
                updateShortcutLabels(contentResolver, manager);
            }

            mDesktopItems = new ArrayList<ItemInfo>();
            mDesktopAppWidgets = new ArrayList<LauncherAppWidgetInfo>();
            mFolders = new HashMap<Long, FolderInfo>();

            final ArrayList<ItemInfo> desktopItems = mDesktopItems;
            final ArrayList<LauncherAppWidgetInfo> desktopAppWidgets = mDesktopAppWidgets;

            final Cursor c = contentResolver.query(
                    LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);

            try {
                final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
                final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
                final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
                final int iconTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_TYPE);
                final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
                final int iconPackageIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_PACKAGE);
                final int iconResourceIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_RESOURCE);
                final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
                final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
                final int appWidgetIdIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.APPWIDGET_ID);
                final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
                final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
                final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
                final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);
                final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);
                final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);
                final int displayModeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.DISPLAY_MODE);

                ApplicationInfo info;
                String intentDescription;
                Widget widgetInfo;
                LauncherAppWidgetInfo appWidgetInfo;
                int container;
                long id;
                Intent intent;

                final HashMap<Long, FolderInfo> folders = mFolders;

                while (!mStopped && c.moveToNext()) {
                    try {
                        int itemType = c.getInt(itemTypeIndex);

                        switch (itemType) {
                        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
                        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                            intentDescription = c.getString(intentIndex);
                            try {
                                intent = Intent.parseUri(intentDescription, 0);
                            } catch (java.net.URISyntaxException e) {
                                continue;
                            }

                            if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
                                info = getApplicationInfo(manager, intent, launcher);
                            } else {
                                info = getApplicationInfoShortcut(c, launcher, iconTypeIndex,
                                        iconPackageIndex, iconResourceIndex, iconIndex);
                            }

                            if (info == null) {
                                info = new ApplicationInfo();
                                info.icon = manager.getDefaultActivityIcon();
                            }

                            if (info != null) {
                                info.title = c.getString(titleIndex);
                                info.intent = intent;

                                info.id = c.getLong(idIndex);
                                container = c.getInt(containerIndex);
                                info.container = container;
                                info.screen = c.getInt(screenIndex);
                                info.cellX = c.getInt(cellXIndex);
                                info.cellY = c.getInt(cellYIndex);

                                switch (container) {
                                case LauncherSettings.Favorites.CONTAINER_DESKTOP:
                                    desktopItems.add(info);
                                    break;
                                default:
                                    // Item is in a user folder
                                    UserFolderInfo folderInfo =
                                            findOrMakeUserFolder(folders, container);
                                    folderInfo.add(info);
                                    break;
                                }
                            }
                            break;
                        case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:

                            id = c.getLong(idIndex);
                            UserFolderInfo folderInfo = findOrMakeUserFolder(folders, id);

                            folderInfo.title = c.getString(titleIndex);

                            folderInfo.id = id;
                            container = c.getInt(containerIndex);
                            folderInfo.container = container;
                            folderInfo.screen = c.getInt(screenIndex);
                            folderInfo.cellX = c.getInt(cellXIndex);
                            folderInfo.cellY = c.getInt(cellYIndex);

                            switch (container) {
                                case LauncherSettings.Favorites.CONTAINER_DESKTOP:
                                    desktopItems.add(folderInfo);
                                    break;
                            }
                            break;
                        case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:

                            id = c.getLong(idIndex);
                            LiveFolderInfo liveFolderInfo = findOrMakeLiveFolder(folders, id);

                            intentDescription = c.getString(intentIndex);
                            intent = null;
                            if (intentDescription != null) {
                                try {
                                    intent = Intent.parseUri(intentDescription, 0);
                                } catch (java.net.URISyntaxException e) {
                                    // Ignore, a live folder might not have a base intent
                                }
                            }

                            liveFolderInfo.title = c.getString(titleIndex);
                            liveFolderInfo.id = id;
                            container = c.getInt(containerIndex);
                            liveFolderInfo.container = container;
                            liveFolderInfo.screen = c.getInt(screenIndex);
                            liveFolderInfo.cellX = c.getInt(cellXIndex);
                            liveFolderInfo.cellY = c.getInt(cellYIndex);
                            liveFolderInfo.uri = Uri.parse(c.getString(uriIndex));
                            liveFolderInfo.baseIntent = intent;
                            liveFolderInfo.displayMode = c.getInt(displayModeIndex);

                            loadLiveFolderIcon(launcher, c, iconTypeIndex, iconPackageIndex,
                                    iconResourceIndex, liveFolderInfo);

                            switch (container) {
                                case LauncherSettings.Favorites.CONTAINER_DESKTOP:
                                    desktopItems.add(liveFolderInfo);
                                    break;
                            }
                            break;
                        case LauncherSettings.Favorites.ITEM_TYPE_WIDGET_SEARCH:
                            widgetInfo = Widget.makeSearch();

                            container = c.getInt(containerIndex);
                            if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
                                e(Launcher.LOG_TAG, "Widget found where container "
                                        + "!= CONTAINER_DESKTOP  ignoring!");
                                continue;
                            }

                            widgetInfo.id = c.getLong(idIndex);
                            widgetInfo.screen = c.getInt(screenIndex);
                            widgetInfo.container = container;
                            widgetInfo.cellX = c.getInt(cellXIndex);
                            widgetInfo.cellY = c.getInt(cellYIndex);

                            desktopItems.add(widgetInfo);
                            break;
                        case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
                            // Read all Launcher-specific widget details
                            int appWidgetId = c.getInt(appWidgetIdIndex);
                            appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId);
                            appWidgetInfo.id = c.getLong(idIndex);
                            appWidgetInfo.screen = c.getInt(screenIndex);
                            appWidgetInfo.cellX = c.getInt(cellXIndex);
                            appWidgetInfo.cellY = c.getInt(cellYIndex);
                            appWidgetInfo.spanX = c.getInt(spanXIndex);
                            appWidgetInfo.spanY = c.getInt(spanYIndex);

                            container = c.getInt(containerIndex);
                            if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
                                e(Launcher.LOG_TAG, "Widget found where container "
                                        + "!= CONTAINER_DESKTOP -- ignoring!");
                                continue;
                            }
                            appWidgetInfo.container = c.getInt(containerIndex);

                            desktopAppWidgets.add(appWidgetInfo);
                            break;
                        }
                    } catch (Exception e) {
                        w(Launcher.LOG_TAG, "Desktop items loading interrupted:", e);
                    }
                }
            } finally {
                c.close();
            }

            if (!mStopped) {
                launcher.runOnUiThread(new Runnable() {
                    public void run() {
                        launcher.onDesktopItemsLoaded();
                    }
                });
                if (mLoadApplications) startApplicationsLoader(launcher, mIsLaunching);
            }

            if (!mStopped) {
                mDesktopItemsLoaded = true;
            }
            mRunning = false;
        }
    }

    private static void loadLiveFolderIcon(Launcher launcher, Cursor c, int iconTypeIndex,
            int iconPackageIndex, int iconResourceIndex, LiveFolderInfo liveFolderInfo) {

        int iconType = c.getInt(iconTypeIndex);
        switch (iconType) {
            case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:
                String packageName = c.getString(iconPackageIndex);
                String resourceName = c.getString(iconResourceIndex);
                PackageManager packageManager = launcher.getPackageManager();
                try {
                    Resources resources = packageManager.getResourcesForApplication(packageName);
                    final int id = resources.getIdentifier(resourceName, null, null);
                    liveFolderInfo.icon = resources.getDrawable(id);
                } catch (Exception e) {
                    liveFolderInfo.icon =
                            launcher.getResources().getDrawable(R.drawable.ic_launcher_folder);
                }
                liveFolderInfo.iconResource = new Intent.ShortcutIconResource();
                liveFolderInfo.iconResource.packageName = packageName;
                liveFolderInfo.iconResource.resourceName = resourceName;
                break;
            default:
                liveFolderInfo.icon =
                        launcher.getResources().getDrawable(R.drawable.ic_launcher_folder);
        }
    }

    /**
     * Finds the user folder defined by the specified id.
     *
     * @param id The id of the folder to look for.
     *
     * @return A UserFolderInfo if the folder exists or null otherwise.
     */
    FolderInfo findFolderById(long id) {
        return mFolders.get(id);
    }

    void addFolder(FolderInfo info) {
        mFolders.put(info.id, info);
    }

    /**
     * Return an existing UserFolderInfo object if we have encountered this ID previously, or make a
     * new one.
     */
    private UserFolderInfo findOrMakeUserFolder(HashMap<Long, FolderInfo> folders, long id) {
        // See if a placeholder was created for us already
        FolderInfo folderInfo = folders.get(id);
        if (folderInfo == null || !(folderInfo instanceof UserFolderInfo)) {
            // No placeholder -- create a new instance
            folderInfo = new UserFolderInfo();
            folders.put(id, folderInfo);
        }
        return (UserFolderInfo) folderInfo;
    }

    /**
     * Return an existing UserFolderInfo object if we have encountered this ID previously, or make a
     * new one.
     */
    private LiveFolderInfo findOrMakeLiveFolder(HashMap<Long, FolderInfo> folders, long id) {
        // See if a placeholder was created for us already
        FolderInfo folderInfo = folders.get(id);
        if (folderInfo == null || !(folderInfo instanceof LiveFolderInfo)) {
            // No placeholder -- create a new instance
            folderInfo = new LiveFolderInfo();
            folders.put(id, folderInfo);
        }
        return (LiveFolderInfo) folderInfo;
    }

    /**
     * Remove the callback for the cached drawables or we leak the previous
     * Home screen on orientation change.
     */
    void unbind() {
        // Interrupt the applications loader before setting the adapter to null
        stopAndWaitForApplicationsLoader();
        mApplicationsAdapter = null;
        unbindAppDrawables(mApplications);
        unbindDrawables(mDesktopItems);
        unbindAppWidgetHostViews(mDesktopAppWidgets);
        unbindCachedIconDrawables();
    }

    /**
     * Remove the callback for the cached drawables or we leak the previous
     * Home screen on orientation change.
     */
    private void unbindDrawables(ArrayList<ItemInfo> desktopItems) {
        if (desktopItems != null) {
            final int count = desktopItems.size();
            for (int i = 0; i < count; i++) {
                ItemInfo item = desktopItems.get(i);
                switch (item.itemType) {
                case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
                case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                    ((ApplicationInfo)item).icon.setCallback(null);
                    break;
                }
            }
        }
    }

    /**
     * Remove the callback for the cached drawables or we leak the previous
     * Home screen on orientation change.
     */
    private void unbindAppDrawables(ArrayList<ApplicationInfo> applications) {
        if (applications != null) {
            final int count = applications.size();
            for (int i = 0; i < count; i++) {
                applications.get(i).icon.setCallback(null);
            }
        }
    }

    /**
     * Remove any {@link LauncherAppWidgetHostView} references in our widgets.
     */
    private void unbindAppWidgetHostViews(ArrayList<LauncherAppWidgetInfo> appWidgets) {
        if (appWidgets != null) {
            final int count = appWidgets.size();
            for (int i = 0; i < count; i++) {
                LauncherAppWidgetInfo launcherInfo = appWidgets.get(i);
                launcherInfo.hostView = null;
            }
        }
    }

    /**
     * Remove the callback for the cached drawables or we leak the previous
     * Home screen on orientation change.
     */
    private void unbindCachedIconDrawables() {
        for (ApplicationInfo appInfo : mAppInfoCache.values()) {
            appInfo.icon.setCallback(null);
        }
    }

    /**
     * @return The current list of applications
     */
    ApplicationsAdapter getApplicationsAdapter() {
        return mApplicationsAdapter;
    }

    /**
     * @return The current list of desktop items
     */
    ArrayList<ItemInfo> getDesktopItems() {
        return mDesktopItems;
    }

    /**
     * @return The current list of desktop items
     */
    ArrayList<LauncherAppWidgetInfo> getDesktopAppWidgets() {
        return mDesktopAppWidgets;
    }

    /**
     * Add an item to the desktop
     * @param info
     */
    void addDesktopItem(ItemInfo info) {
        // TODO: write to DB; also check that folder has been added to folders list
        mDesktopItems.add(info);
    }

    /**
     * Remove an item from the desktop
     * @param info
     */
    void removeDesktopItem(ItemInfo info) {
        // TODO: write to DB; figure out if we should remove folder from folders list
        mDesktopItems.remove(info);
    }

    /**
     * Add a widget to the desktop
     */
    void addDesktopAppWidget(LauncherAppWidgetInfo info) {
        mDesktopAppWidgets.add(info);
    }

    /**
     * Remove a widget from the desktop
     */
    void removeDesktopAppWidget(LauncherAppWidgetInfo info) {
        mDesktopAppWidgets.remove(info);
    }

    /**
     * Make an ApplicationInfo object for an application
     */
    private static ApplicationInfo getApplicationInfo(PackageManager manager, Intent intent,
                                                      Context context) {
        final ResolveInfo resolveInfo = manager.resolveActivity(intent, 0);

        if (resolveInfo == null) {
            return null;
        }

        final ApplicationInfo info = new ApplicationInfo();
        final ActivityInfo activityInfo = resolveInfo.activityInfo;
        info.icon = Utilities.createIconThumbnail(activityInfo.loadIcon(manager), context);
        if (info.title == null || info.title.length() == 0) {
            info.title = activityInfo.loadLabel(manager);
        }
        if (info.title == null) {
            info.title = "";
        }
        info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
        return info;
    }

    /**
     * Make an ApplicationInfo object for a sortcut
     */
    private ApplicationInfo getApplicationInfoShortcut(Cursor c, Context context,
            int iconTypeIndex, int iconPackageIndex, int iconResourceIndex, int iconIndex) {

        final ApplicationInfo info = new ApplicationInfo();
        info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;

        int iconType = c.getInt(iconTypeIndex);
        switch (iconType) {
            case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:
                String packageName = c.getString(iconPackageIndex);
                String resourceName = c.getString(iconResourceIndex);
                PackageManager packageManager = context.getPackageManager();
                try {
                    Resources resources = packageManager.getResourcesForApplication(packageName);
                    final int id = resources.getIdentifier(resourceName, null, null);
                    info.icon = Utilities.createIconThumbnail(resources.getDrawable(id), context);
                } catch (Exception e) {
                    info.icon = packageManager.getDefaultActivityIcon();
                }
                info.iconResource = new Intent.ShortcutIconResource();
                info.iconResource.packageName = packageName;
                info.iconResource.resourceName = resourceName;
                info.customIcon = false;
                break;
            case LauncherSettings.Favorites.ICON_TYPE_BITMAP:
                byte[] data = c.getBlob(iconIndex);
                try {
                    Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                    info.icon = new FastBitmapDrawable(
                            Utilities.createBitmapThumbnail(bitmap, context));
                } catch (Exception e) {
                    packageManager = context.getPackageManager();
                    info.icon = packageManager.getDefaultActivityIcon();
                }
                info.filtered = true;
                info.customIcon = true;
                break;
            default:
                info.icon = context.getPackageManager().getDefaultActivityIcon();
                info.customIcon = false;
                break;
        }
        return info;
    }

    /**
     * Remove an item from the in-memory represention of a user folder. Does not change the DB.
     */
    void removeUserFolderItem(UserFolderInfo folder, ItemInfo info) {
        //noinspection SuspiciousMethodCalls
        folder.contents.remove(info);
    }

    /**
     * Removes a UserFolder from the in-memory list of folders. Does not change the DB.
     * @param userFolderInfo
     */
    void removeUserFolder(UserFolderInfo userFolderInfo) {
        mFolders.remove(userFolderInfo.id);
    }

    /**
     * Adds an item to the DB if it was not created previously, or move it to a new
     * <container, screen, cellX, cellY>
     */
    static void addOrMoveItemInDatabase(Context context, ItemInfo item, long container,
            int screen, int cellX, int cellY) {
        if (item.container == ItemInfo.NO_ID) {
            // From all apps
            addItemToDatabase(context, item, container, screen, cellX, cellY, false);
        } else {
            // From somewhere else
            moveItemInDatabase(context, item, container, screen, cellX, cellY);
        }
    }

    /**
     * Move an item in the DB to a new <container, screen, cellX, cellY>
     */
    static void moveItemInDatabase(Context context, ItemInfo item, long container, int screen,
            int cellX, int cellY) {
        item.container = container;
        item.screen = screen;
        item.cellX = cellX;
        item.cellY = cellY;

        final ContentValues values = new ContentValues();
        final ContentResolver cr = context.getContentResolver();

        values.put(LauncherSettings.Favorites.CONTAINER, item.container);
        values.put(LauncherSettings.Favorites.CELLX, item.cellX);
        values.put(LauncherSettings.Favorites.CELLY, item.cellY);
        values.put(LauncherSettings.Favorites.SCREEN, item.screen);

        cr.update(LauncherSettings.Favorites.getContentUri(item.id, false), values, null, null);
    }

    /**
     * Returns true if the shortcuts already exists in the database.
     * we identify a shortcut by its title and intent.
     */
    static boolean shortcutExists(Context context, String title, Intent intent) {
        final ContentResolver cr = context.getContentResolver();
        Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,
            new String[] { "title", "intent" }, "title=? and intent=?",
            new String[] { title, intent.toUri(0) }, null);
        boolean result = false;
        try {
            result = c.moveToFirst();
        } finally {
            c.close();
        }
        return result;
    }

    FolderInfo getFolderById(Context context, long id) {
        final ContentResolver cr = context.getContentResolver();
        Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, null,
                "_id=? and (itemType=? or itemType=?)",
                new String[] { String.valueOf(id),
                        String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER),
                        String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER) }, null);

        try {
            if (c.moveToFirst()) {
                final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
                final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
                final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
                final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
                final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
                final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);

                FolderInfo folderInfo = null;
                switch (c.getInt(itemTypeIndex)) {
                    case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
                        folderInfo = findOrMakeUserFolder(mFolders, id);
                        break;
                    case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
                        folderInfo = findOrMakeLiveFolder(mFolders, id);
                        break;
                }

                folderInfo.title = c.getString(titleIndex);
                folderInfo.id = id;
                folderInfo.container = c.getInt(containerIndex);
                folderInfo.screen = c.getInt(screenIndex);
                folderInfo.cellX = c.getInt(cellXIndex);
                folderInfo.cellY = c.getInt(cellYIndex);

                return folderInfo;
            }
        } finally {
            c.close();
        }

        return null;
    }

    /**
     * Add an item to the database in a specified container. Sets the container, screen, cellX and
     * cellY fields of the item. Also assigns an ID to the item.
     */
    static void addItemToDatabase(Context context, ItemInfo item, long container,
            int screen, int cellX, int cellY, boolean notify) {
        item.container = container;
        item.screen = screen;
        item.cellX = cellX;
        item.cellY = cellY;

        final ContentValues values = new ContentValues();
        final ContentResolver cr = context.getContentResolver();

        item.onAddToDatabase(values);

        Uri result = cr.insert(notify ? LauncherSettings.Favorites.CONTENT_URI :
                LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION, values);

        if (result != null) {
            item.id = Integer.parseInt(result.getPathSegments().get(1));
        }
    }

    /**
     * Add an item to the database in a specified container. Sets the container, screen, cellX and
     * cellY fields of the item. Also assigns an ID to the item.
     */
    static boolean addGestureToDatabase(Context context, ItemInfo item, boolean notify) {
        final ContentValues values = new ContentValues();
        final ContentResolver cr = context.getContentResolver();

        item.onAddToDatabase(values);

        Uri result = cr.insert(notify ? LauncherSettings.Gestures.CONTENT_URI :
                LauncherSettings.Gestures.CONTENT_URI_NO_NOTIFICATION, values);

        if (result != null) {
            item.id = Integer.parseInt(result.getPathSegments().get(1));
        }

        return result != null;
    }

    /**
     * Update an item to the database in a specified container.
     */
    static void updateItemInDatabase(Context context, ItemInfo item) {
        final ContentValues values = new ContentValues();
        final ContentResolver cr = context.getContentResolver();

        item.onAddToDatabase(values);

        cr.update(LauncherSettings.Favorites.getContentUri(item.id, false), values, null, null);
    }

    /**
     * Removes the specified item from the database
     * @param context
     * @param item
     */
    static void deleteItemFromDatabase(Context context, ItemInfo item) {
        final ContentResolver cr = context.getContentResolver();

        cr.delete(LauncherSettings.Favorites.getContentUri(item.id, false), null, null);
    }


    /**
     * Remove the contents of the specified folder from the database
     */
    static void deleteUserFolderContentsFromDatabase(Context context, UserFolderInfo info) {
        final ContentResolver cr = context.getContentResolver();

        cr.delete(LauncherSettings.Favorites.getContentUri(info.id, false), null, null);
        cr.delete(LauncherSettings.Favorites.CONTENT_URI,
                LauncherSettings.Favorites.CONTAINER + "=" + info.id, null);
    }

    static void deleteGestureFromDatabase(Context context, ItemInfo item) {
        final ContentResolver cr = context.getContentResolver();

        cr.delete(LauncherSettings.Gestures.getContentUri(item.id, false), null, null);
    }

    static void updateGestureInDatabase(Context context, ItemInfo item) {
        final ContentValues values = new ContentValues();
        final ContentResolver cr = context.getContentResolver();

        item.onAddToDatabase(values);

        cr.update(LauncherSettings.Gestures.getContentUri(item.id, false), values, null, null);
    }


    ApplicationInfo queryGesture(Context context, String id) {
        final ContentResolver contentResolver = context.getContentResolver();
        final PackageManager manager = context.getPackageManager();
        final Cursor c = contentResolver.query(
                LauncherSettings.Gestures.CONTENT_URI, null, LauncherSettings.Gestures._ID + "=?",
                new String[] { id }, null);

        ApplicationInfo info = null;

        try {
            final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Gestures._ID);
            final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Gestures.INTENT);
            final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Gestures.TITLE);
            final int iconTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Gestures.ICON_TYPE);
            final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Gestures.ICON);
            final int iconPackageIndex = c.getColumnIndexOrThrow(LauncherSettings.Gestures.ICON_PACKAGE);
            final int iconResourceIndex = c.getColumnIndexOrThrow(LauncherSettings.Gestures.ICON_RESOURCE);
            final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Gestures.ITEM_TYPE);

            String intentDescription;
            Intent intent;

            if (c.moveToNext()) {
                int itemType = c.getInt(itemTypeIndex);

                switch (itemType) {
                    case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
                    case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                        intentDescription = c.getString(intentIndex);
                        try {
                            intent = Intent.parseUri(intentDescription, 0);
                        } catch (java.net.URISyntaxException e) {
                            return null;
                        }

                        if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
                            info = getApplicationInfo(manager, intent, context);
                        } else {
                            info = getApplicationInfoShortcut(c, context, iconTypeIndex,
                                    iconPackageIndex, iconResourceIndex, iconIndex);
                        }

                        if (info == null) {
                            info = new ApplicationInfo();
                            info.icon = manager.getDefaultActivityIcon();
                        }

                        info.isGesture = true;
                        info.title = c.getString(titleIndex);
                        info.intent = intent;
                        info.id = c.getLong(idIndex);

                        break;
                }
            }
        } catch (Exception e) {
            w(LOG_TAG, "Could not load gesture with name " + id);
        } finally {
            c.close();
        }

        return info;
    }
}
