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

import com.android.gallery.R;

import com.android.camera.gallery.IImage;
import com.android.camera.gallery.IImageList;

import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.StatFs;
import android.provider.MediaStore;
import android.provider.MediaStore.Images;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuItem.OnMenuItemClickListener;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.AdapterContextMenuInfo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * The GalleryPicker activity.
 */
public class GalleryPicker extends NoSearchActivity {
    private static final String TAG = "GalleryPicker";

    Handler mHandler = new Handler();  // handler for the main thread
    Thread mWorkerThread;
    BroadcastReceiver mReceiver;
    ContentObserver mDbObserver;
    GridView mGridView;
    GalleryPickerAdapter mAdapter;  // mAdapter is only accessed in main thread.
    boolean mScanning;
    boolean mUnmounted;

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

        setContentView(R.layout.gallerypicker);

        mGridView = (GridView) findViewById(R.id.albums);

        mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view,
                                    int position, long id) {
                launchFolderGallery(position);
            }
        });

        mGridView.setOnCreateContextMenuListener(
                new View.OnCreateContextMenuListener() {
                    public void onCreateContextMenu(ContextMenu menu, View v,
                        final ContextMenuInfo menuInfo) {
                            onCreateGalleryPickerContextMenu(menu, menuInfo);
                    }
                });

        mReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                onReceiveMediaBroadcast(intent);
            }
        };

        mDbObserver = new ContentObserver(mHandler) {
            @Override
            public void onChange(boolean selfChange) {
                rebake(false, ImageManager.isMediaScannerScanning(
                        getContentResolver()));
            }
        };

        ImageManager.ensureOSXCompatibleFolder();
    }

    Dialog mMediaScanningDialog;

    // Display a dialog if the storage is being scanned now.
    public void updateScanningDialog(boolean scanning) {
        boolean prevScanning = (mMediaScanningDialog != null);
        if (prevScanning == scanning && mAdapter.mItems.size() == 0) return;
        // Now we are certain the state is changed.
        if (prevScanning) {
            mMediaScanningDialog.cancel();
            mMediaScanningDialog = null;
        } else if (scanning && mAdapter.mItems.size() == 0) {
            mMediaScanningDialog = ProgressDialog.show(
                    this,
                    null,
                    getResources().getString(R.string.wait),
                    true,
                    true);
        }
    }

    private View mNoImagesView;

    // Show/Hide the "no images" icon and text. Load resources on demand.
    private void showNoImagesView() {
        if (mNoImagesView == null) {
            ViewGroup root  = (ViewGroup) findViewById(R.id.root);
            getLayoutInflater().inflate(R.layout.gallerypicker_no_images, root);
            mNoImagesView = findViewById(R.id.no_images);
        }
        mNoImagesView.setVisibility(View.VISIBLE);
    }

    private void hideNoImagesView() {
        if (mNoImagesView != null) {
            mNoImagesView.setVisibility(View.GONE);
        }
    }

    // The storage status is changed, restart the worker or show "no images".
    private void rebake(boolean unmounted, boolean scanning) {
        if (unmounted == mUnmounted && scanning == mScanning) return;
        abortWorker();
        mUnmounted = unmounted;
        mScanning = scanning;
        updateScanningDialog(mScanning);
        if (mUnmounted) {
            showNoImagesView();
        } else {
            hideNoImagesView();
            startWorker();
        }
    }

    // This is called when we receive media-related broadcast.
    private void onReceiveMediaBroadcast(Intent intent) {
        String action = intent.getAction();
        if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
            // SD card available
            // TODO put up a "please wait" message
        } else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED)) {
            // SD card unavailable
            rebake(true, false);
        } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_STARTED)) {
            rebake(false, true);
        } else if (action.equals(
                Intent.ACTION_MEDIA_SCANNER_FINISHED)) {
            rebake(false, false);
        } else if (action.equals(Intent.ACTION_MEDIA_EJECT)) {
            rebake(true, false);
        }
    }

    private void launchFolderGallery(int position) {
        mAdapter.mItems.get(position).launch(this);
    }

    private void onCreateGalleryPickerContextMenu(ContextMenu menu,
            final ContextMenuInfo menuInfo) {
        int position = ((AdapterContextMenuInfo) menuInfo).position;
        menu.setHeaderTitle(mAdapter.baseTitleForPosition(position));
        // "Slide Show"
        if ((mAdapter.getIncludeMediaTypes(position)
                & ImageManager.INCLUDE_IMAGES) != 0) {
            menu.add(R.string.slide_show)
                    .setOnMenuItemClickListener(new OnMenuItemClickListener() {
                        public boolean onMenuItemClick(MenuItem item) {
                            return onSlideShowClicked(menuInfo);
                        }
                    });
        }
        // "View"
        menu.add(R.string.view)
                .setOnMenuItemClickListener(new OnMenuItemClickListener() {
                    public boolean onMenuItemClick(MenuItem item) {
                            return onViewClicked(menuInfo);
                    }
                });
    }

    // This is called when the user clicks "Slideshow" from the context menu.
    private boolean onSlideShowClicked(ContextMenuInfo menuInfo) {
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
        int position = info.position;

        if (position < 0 || position >= mAdapter.mItems.size()) {
            return true;
        }
        // Slide show starts from the first image on the list.
        Item item = mAdapter.mItems.get(position);
        Uri targetUri = item.mFirstImageUri;

        if (targetUri != null && item.mBucketId != null) {
            targetUri = targetUri.buildUpon()
                    .appendQueryParameter("bucketId", item.mBucketId)
                    .build();
        }
        Intent intent = new Intent(Intent.ACTION_VIEW, targetUri);
        intent.putExtra("slideshow", true);
        startActivity(intent);
        return true;
    }

    // This is called when the user clicks "View" from the context menu.
    private boolean onViewClicked(ContextMenuInfo menuInfo) {
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
        launchFolderGallery(info.position);
        return true;
    }

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

        abortWorker();

        unregisterReceiver(mReceiver);
        getContentResolver().unregisterContentObserver(mDbObserver);

        // free up some ram
        mAdapter = null;
        mGridView.setAdapter(null);
        unloadDrawable();
    }

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

        mAdapter = new GalleryPickerAdapter(getLayoutInflater());
        mGridView.setAdapter(mAdapter);

        // install an intent filter to receive SD card related events.
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
        intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
        intentFilter.addAction(Intent.ACTION_MEDIA_EJECT);
        intentFilter.addDataScheme("file");

        registerReceiver(mReceiver, intentFilter);

        getContentResolver().registerContentObserver(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                true, mDbObserver);

        // Assume the storage is mounted and not scanning.
        mUnmounted = false;
        mScanning = false;
        startWorker();
    }

    // This is used to stop the worker thread.
    volatile boolean mAbort = false;

    // Create the worker thread.
    private void startWorker() {
        mAbort = false;
        mWorkerThread = new Thread("GalleryPicker Worker") {
            @Override
            public void run() {
                workerRun();
            }
        };
        BitmapManager.instance().allowThreadDecoding(mWorkerThread);
        mWorkerThread.start();
    }

    private void abortWorker() {
        if (mWorkerThread != null) {
            BitmapManager.instance().cancelThreadDecoding(mWorkerThread, getContentResolver());
            mAbort = true;
            try {
                mWorkerThread.join();
            } catch (InterruptedException ex) {
                Log.e(TAG, "join interrupted");
            }
            mWorkerThread = null;
            // Remove all runnables in mHandler.
            // (We assume that the "what" field in the messages are 0
            // for runnables).
            mHandler.removeMessages(0);
            mAdapter.clear();
            mAdapter.updateDisplay();
            clearImageLists();
        }
    }

    // This is run in the worker thread.
    private void workerRun() {
        // We collect items from checkImageList() and checkBucketIds() and
        // put them in allItems. Later we give allItems to checkThumbBitmap()
        // and generated thumbnail bitmaps for each item. We do this instead of
        // generating thumbnail bitmaps in checkImageList() and checkBucketIds()
        // because we want to show all the folders first, then update them with
        // the thumb bitmaps. (Generating thumbnail bitmaps takes some time.)
        ArrayList<Item> allItems = new ArrayList<Item>();

        checkScanning();
        if (mAbort) return;

        checkImageList(allItems);
        if (mAbort) return;

        checkBucketIds(allItems);
        if (mAbort) return;

        checkThumbBitmap(allItems);
        if (mAbort) return;

        checkLowStorage();
    }

    // This is run in the worker thread.
    private void checkScanning() {
        ContentResolver cr = getContentResolver();
        final boolean scanning =
                ImageManager.isMediaScannerScanning(cr);
        mHandler.post(new Runnable() {
                    public void run() {
                        checkScanningFinished(scanning);
                    }
                });
    }

    // This is run in the main thread.
    private void checkScanningFinished(boolean scanning) {
        updateScanningDialog(scanning);
    }

    // This is run in the worker thread.
    private void checkImageList(ArrayList<Item> allItems) {
        int length = IMAGE_LIST_DATA.length;
        IImageList[] lists = new IImageList[length];
        for (int i = 0; i < length; i++) {
            ImageListData data = IMAGE_LIST_DATA[i];
            lists[i] = createImageList(data.mInclude, data.mBucketId,
                    getContentResolver());
            if (mAbort) return;
            Item item = null;

            if (lists[i].isEmpty()) continue;

            // i >= 3 means we are looking at All Images/All Videos.
            // lists[i-3] is the corresponding Camera Images/Camera Videos.
            // We want to add the "All" list only if it's different from
            // the "Camera" list.
            if (i >= 3 && lists[i].getCount() == lists[i - 3].getCount()) {
                continue;
            }

            item = new Item(data.mType,
                            data.mBucketId,
                            getResources().getString(data.mStringId),
                            lists[i]);

            allItems.add(item);

            final Item finalItem = item;
            mHandler.post(new Runnable() {
                        public void run() {
                            updateItem(finalItem);
                        }
                    });
        }
    }

    // This is run in the main thread.
    private void updateItem(Item item) {
        // Hide NoImageView if we are going to add the first item
        if (mAdapter.getCount() == 0) {
            hideNoImagesView();
        }
        mAdapter.addItem(item);
        mAdapter.updateDisplay();
    }

    private static final String CAMERA_BUCKET =
            ImageManager.CAMERA_IMAGE_BUCKET_ID;

    // This is run in the worker thread.
    private void checkBucketIds(ArrayList<Item> allItems) {
        final IImageList allImages;
        if (!mScanning && !mUnmounted) {
            allImages = ImageManager.makeImageList(
                    getContentResolver(),
                    ImageManager.DataLocation.ALL,
                    ImageManager.INCLUDE_IMAGES | ImageManager.INCLUDE_VIDEOS,
                    ImageManager.SORT_DESCENDING,
                    null);
        } else {
            allImages = ImageManager.makeEmptyImageList();
        }

        if (mAbort) {
            allImages.close();
            return;
        }

        HashMap<String, String> hashMap = allImages.getBucketIds();
        allImages.close();
        if (mAbort) return;

        for (Map.Entry<String, String> entry : hashMap.entrySet()) {
            String key = entry.getKey();
            if (key == null) {
                continue;
            }
            if (!key.equals(CAMERA_BUCKET)) {
                IImageList list = createImageList(
                        ImageManager.INCLUDE_IMAGES
                        | ImageManager.INCLUDE_VIDEOS, key,
                        getContentResolver());
                if (mAbort) return;

                Item item = new Item(Item.TYPE_NORMAL_FOLDERS, key,
                        entry.getValue(), list);

                allItems.add(item);

                final Item finalItem = item;
                mHandler.post(new Runnable() {
                            public void run() {
                                updateItem(finalItem);
                            }
                        });
            }
        }

        mHandler.post(new Runnable() {
                    public void run() {
                        checkBucketIdsFinished();
                    }
                });
    }

    // This is run in the main thread.
    private void checkBucketIdsFinished() {

        // If we just have one folder, open it.
        // If we have zero folder, show the "no images" icon.
        if (!mScanning) {
            int numItems = mAdapter.mItems.size();
            if (numItems == 0) {
                showNoImagesView();
            } else if (numItems == 1) {
                mAdapter.mItems.get(0).launch(this);
                finish();
                return;
            }
        }
    }

    private static final int THUMB_SIZE = 142;
    // This is run in the worker thread.
    private void checkThumbBitmap(ArrayList<Item> allItems) {
        for (Item item : allItems) {
            final Bitmap b = makeMiniThumbBitmap(THUMB_SIZE, THUMB_SIZE,
                    item.mImageList);
            if (mAbort) {
                if (b != null) b.recycle();
                return;
            }

            final Item finalItem = item;
            mHandler.post(new Runnable() {
                        public void run() {
                            updateThumbBitmap(finalItem, b);
                        }
                    });
        }
    }

    // This is run in the main thread.
    private void updateThumbBitmap(Item item, Bitmap b) {
        item.setThumbBitmap(b);
        mAdapter.updateDisplay();
    }

    private static final long LOW_STORAGE_THRESHOLD = 1024 * 1024 * 2;

    // This is run in the worker thread.
    private void checkLowStorage() {
        // Check available space only if we are writable
        if (ImageManager.hasStorage()) {
            String storageDirectory = Environment
                    .getExternalStorageDirectory().toString();
            StatFs stat = new StatFs(storageDirectory);
            long remaining = (long) stat.getAvailableBlocks()
                    * (long) stat.getBlockSize();
            if (remaining < LOW_STORAGE_THRESHOLD) {
                mHandler.post(new Runnable() {
                    public void run() {
                        checkLowStorageFinished();
                    }
                });
            }
        }
    }

    // This is run in the main thread.
    // This is called only if the storage is low.
    private void checkLowStorageFinished() {
        Toast.makeText(GalleryPicker.this, R.string.not_enough_space, 5000)
                .show();
    }

    // IMAGE_LIST_DATA stores the parameters for the four image lists
    // we are interested in. The order of the IMAGE_LIST_DATA array is
    // significant (See the implementation of GalleryPickerAdapter.init).
    private static final class ImageListData {
        ImageListData(int type, int include, String bucketId, int stringId) {
            mType = type;
            mInclude = include;
            mBucketId = bucketId;
            mStringId = stringId;
        }
        int mType;
        int mInclude;
        String mBucketId;
        int mStringId;
    }

    private static final ImageListData[] IMAGE_LIST_DATA = {
        // Camera Images
        new ImageListData(Item.TYPE_CAMERA_IMAGES,
                          ImageManager.INCLUDE_IMAGES,
                          ImageManager.CAMERA_IMAGE_BUCKET_ID,
                          R.string.gallery_camera_bucket_name),
        // Camera Videos
        new ImageListData(Item.TYPE_CAMERA_VIDEOS,
                          ImageManager.INCLUDE_VIDEOS,
                          ImageManager.CAMERA_IMAGE_BUCKET_ID,
                          R.string.gallery_camera_videos_bucket_name),

        // Camera Medias
        new ImageListData(Item.TYPE_CAMERA_MEDIAS,
                ImageManager.INCLUDE_VIDEOS | ImageManager.INCLUDE_IMAGES,
                ImageManager.CAMERA_IMAGE_BUCKET_ID,
                R.string.gallery_camera_media_bucket_name),

        // All Images
        new ImageListData(Item.TYPE_ALL_IMAGES,
                          ImageManager.INCLUDE_IMAGES,
                          null,
                          R.string.all_images),

        // All Videos
        new ImageListData(Item.TYPE_ALL_VIDEOS,
                          ImageManager.INCLUDE_VIDEOS,
                          null,
                          R.string.all_videos),
    };


    // These drawables are loaded on-demand.
    Drawable mFrameGalleryMask;
    Drawable mCellOutline;
    Drawable mVideoOverlay;

    private void loadDrawableIfNeeded() {
        if (mFrameGalleryMask != null) return;  // already loaded
        Resources r = getResources();
        mFrameGalleryMask = r.getDrawable(
                R.drawable.frame_gallery_preview_album_mask);
        mCellOutline = r.getDrawable(android.R.drawable.gallery_thumb);
        mVideoOverlay = r.getDrawable(R.drawable.ic_gallery_video_overlay);
    }

    private void unloadDrawable() {
        mFrameGalleryMask = null;
        mCellOutline = null;
        mVideoOverlay = null;
    }

    private static void placeImage(Bitmap image, Canvas c, Paint paint,
            int imageWidth, int widthPadding, int imageHeight,
            int heightPadding, int offsetX, int offsetY,
            int pos) {
        int row = pos / 2;
        int col = pos - (row * 2);

        int xPos = (col * (imageWidth + widthPadding)) - offsetX;
        int yPos = (row * (imageHeight + heightPadding)) - offsetY;

        c.drawBitmap(image, xPos, yPos, paint);
    }

    // This is run in worker thread.
    private Bitmap makeMiniThumbBitmap(int width, int height,
            IImageList images) {
        int count = images.getCount();
        // We draw three different version of the folder image depending on the
        // number of images in the folder.
        //    For a single image, that image draws over the whole folder.
        //    For two or three images, we draw the two most recent photos.
        //    For four or more images, we draw four photos.
        final int padding = 4;
        int imageWidth = width;
        int imageHeight = height;
        int offsetWidth = 0;
        int offsetHeight = 0;

        imageWidth = (imageWidth - padding) / 2;  // 2 here because we show two
                                                  // images
        imageHeight = (imageHeight - padding) / 2;  // per row and column

        final Paint p = new Paint();
        final Bitmap b = Bitmap.createBitmap(width, height,
                Bitmap.Config.ARGB_8888);
        final Canvas c = new Canvas(b);
        final Matrix m = new Matrix();

        // draw the whole canvas as transparent
        p.setColor(0x00000000);
        c.drawPaint(p);

        // load the drawables
        loadDrawableIfNeeded();

        // draw the mask normally
        p.setColor(0xFFFFFFFF);
        mFrameGalleryMask.setBounds(0, 0, width, height);
        mFrameGalleryMask.draw(c);

        Paint pdpaint = new Paint();
        pdpaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

        pdpaint.setStyle(Paint.Style.FILL);
        c.drawRect(0, 0, width, height, pdpaint);

        for (int i = 0; i < 4; i++) {
            if (mAbort) {
                return null;
            }

            Bitmap temp = null;
            IImage image = i < count ? images.getImageAt(i) : null;

            if (image != null) {
                temp = image.miniThumbBitmap();
            }

            if (temp != null) {
                if (ImageManager.isVideo(image)) {
                    Bitmap newMap = temp.copy(temp.getConfig(), true);
                    Canvas overlayCanvas = new Canvas(newMap);
                    int overlayWidth = mVideoOverlay.getIntrinsicWidth();
                    int overlayHeight = mVideoOverlay.getIntrinsicHeight();
                    int left = (newMap.getWidth() - overlayWidth) / 2;
                    int top = (newMap.getHeight() - overlayHeight) / 2;
                    Rect newBounds = new Rect(left, top, left + overlayWidth,
                            top + overlayHeight);
                    mVideoOverlay.setBounds(newBounds);
                    mVideoOverlay.draw(overlayCanvas);
                    temp.recycle();
                    temp = newMap;
                }

                temp = Util.transform(m, temp, imageWidth,
                        imageHeight, true, Util.RECYCLE_INPUT);
            }

            Bitmap thumb = Bitmap.createBitmap(imageWidth, imageHeight,
                                               Bitmap.Config.ARGB_8888);
            Canvas tempCanvas = new Canvas(thumb);
            if (temp != null) {
                tempCanvas.drawBitmap(temp, new Matrix(), new Paint());
            }
            mCellOutline.setBounds(0, 0, imageWidth, imageHeight);
            mCellOutline.draw(tempCanvas);

            placeImage(thumb, c, pdpaint, imageWidth, padding, imageHeight,
                       padding, offsetWidth, offsetHeight, i);

            thumb.recycle();

            if (temp != null) {
                temp.recycle();
            }
        }

        return b;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);

        MenuHelper.addCaptureMenuItems(menu, this);

        menu.add(Menu.NONE, Menu.NONE, MenuHelper.POSITION_GALLERY_SETTING,
                R.string.camerasettings)
                .setOnMenuItemClickListener(new OnMenuItemClickListener() {
                    public boolean onMenuItemClick(MenuItem item) {
                        Intent preferences = new Intent();
                        preferences.setClass(GalleryPicker.this,
                                             GallerySettings.class);
                        startActivity(preferences);
                        return true;
                    }
                })
                .setAlphabeticShortcut('p')
                .setIcon(android.R.drawable.ic_menu_preferences);

        return true;
    }

    // image lists created by createImageList() are collected in mAllLists.
    // They will be closed in clearImageList, so they don't hold open files
    // on SD card. We will be killed if we don't close files when the SD card
    // is unmounted.
    ArrayList<IImageList> mAllLists = new ArrayList<IImageList>();

    private IImageList createImageList(int mediaTypes, String bucketId,
            ContentResolver cr) {
        IImageList list = ImageManager.makeImageList(
                cr,
                ImageManager.DataLocation.ALL,
                mediaTypes,
                ImageManager.SORT_DESCENDING,
                bucketId);
        mAllLists.add(list);
        return list;
    }

    private void clearImageLists() {
        for (IImageList list : mAllLists) {
            list.close();
        }
        mAllLists.clear();
    }
}

// Item is the underlying data for GalleryPickerAdapter.
// It is passed from the activity to the adapter.
class Item {
    public static final int TYPE_NONE = -1;
    public static final int TYPE_ALL_IMAGES = 0;
    public static final int TYPE_ALL_VIDEOS = 1;
    public static final int TYPE_CAMERA_IMAGES = 2;
    public static final int TYPE_CAMERA_VIDEOS = 3;
    public static final int TYPE_CAMERA_MEDIAS = 4;
    public static final int TYPE_NORMAL_FOLDERS = 5;

    public final int mType;
    public final String mBucketId;
    public final String mName;
    public final IImageList mImageList;
    public final int mCount;
    public final Uri mFirstImageUri;  // could be null if the list is empty

    // The thumbnail bitmap is set by setThumbBitmap() later because we want
    // to let the user sees the folder icon as soon as possible (and possibly
    // select them), then present more detailed information when we have it.
    public Bitmap mThumbBitmap;  // the thumbnail bitmap for the image list

    public Item(int type, String bucketId, String name, IImageList list) {
        mType = type;
        mBucketId = bucketId;
        mName = name;
        mImageList = list;
        mCount = list.getCount();
        if (mCount > 0) {
            mFirstImageUri = list.getImageAt(0).fullSizeImageUri();
        } else {
            mFirstImageUri = null;
        }
    }

    public void setThumbBitmap(Bitmap thumbBitmap) {
        mThumbBitmap = thumbBitmap;
    }

    public boolean needsBucketId() {
        return mType >= TYPE_CAMERA_IMAGES;
    }

    public void launch(Activity activity) {
        Uri uri = Images.Media.INTERNAL_CONTENT_URI;
        if (needsBucketId()) {
            uri = uri.buildUpon()
                    .appendQueryParameter("bucketId", mBucketId).build();
        }
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        intent.putExtra("windowTitle", mName);
        intent.putExtra("mediaTypes", getIncludeMediaTypes());
        activity.startActivity(intent);
    }

    public int getIncludeMediaTypes() {
        return convertItemTypeToIncludedMediaType(mType);
    }

    public static int convertItemTypeToIncludedMediaType(int itemType) {
        switch (itemType) {
        case TYPE_ALL_IMAGES:
        case TYPE_CAMERA_IMAGES:
            return ImageManager.INCLUDE_IMAGES;
        case TYPE_ALL_VIDEOS:
        case TYPE_CAMERA_VIDEOS:
            return ImageManager.INCLUDE_VIDEOS;
        case TYPE_NORMAL_FOLDERS:
        case TYPE_CAMERA_MEDIAS:
        default:
            return ImageManager.INCLUDE_IMAGES
                    | ImageManager.INCLUDE_VIDEOS;
        }
    }

    public int getOverlay() {
        switch (mType) {
            case TYPE_ALL_IMAGES:
            case TYPE_CAMERA_IMAGES:
                return R.drawable.frame_overlay_gallery_camera;
            case TYPE_ALL_VIDEOS:
            case TYPE_CAMERA_VIDEOS:
            case TYPE_CAMERA_MEDIAS:
                return R.drawable.frame_overlay_gallery_video;
            case TYPE_NORMAL_FOLDERS:
            default:
                return R.drawable.frame_overlay_gallery_folder;
        }
    }
}

class GalleryPickerAdapter extends BaseAdapter {
    ArrayList<Item> mItems = new ArrayList<Item>();
    LayoutInflater mInflater;

    GalleryPickerAdapter(LayoutInflater inflater) {
        mInflater = inflater;
    }

    public void addItem(Item item) {
        mItems.add(item);
    }

    public void updateDisplay() {
        notifyDataSetChanged();
    }

    public void clear() {
        mItems.clear();
    }

    public int getCount() {
        return mItems.size();
    }

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

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

    public String baseTitleForPosition(int position) {
        return mItems.get(position).mName;
    }

    public int getIncludeMediaTypes(int position) {
        return mItems.get(position).getIncludeMediaTypes();
    }

    public View getView(final int position, View convertView,
                        ViewGroup parent) {
        View v;

        if (convertView == null) {
            v = mInflater.inflate(R.layout.gallery_picker_item, null);
        } else {
            v = convertView;
        }

        TextView titleView = (TextView) v.findViewById(R.id.title);

        GalleryPickerItem iv =
                (GalleryPickerItem) v.findViewById(R.id.thumbnail);
        Item item = mItems.get(position);
        iv.setOverlay(item.getOverlay());
        if (item.mThumbBitmap != null) {
            iv.setImageBitmap(item.mThumbBitmap);
            String title = item.mName + " (" + item.mCount + ")";
            titleView.setText(title);
        } else {
            iv.setImageResource(android.R.color.transparent);
            titleView.setText(item.mName);
        }

        // An workaround due to a bug in TextView. If the length of text is
        // different from the previous in convertView, the layout would be
        // wrong.
        titleView.requestLayout();

        return v;
    }
}
