/*
 * Copyright (C) 2010 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.gallery3d.ui;

import android.graphics.Bitmap;
import android.os.Message;
import android.util.FloatMath;

import com.android.gallery3d.app.GalleryActivity;
import com.android.gallery3d.common.BitmapUtils;
import com.android.gallery3d.common.LruCache;
import com.android.gallery3d.common.Utils;
import com.android.gallery3d.data.MediaItem;
import com.android.gallery3d.data.Path;
import com.android.gallery3d.util.Future;
import com.android.gallery3d.util.FutureListener;
import com.android.gallery3d.util.GalleryUtils;
import com.android.gallery3d.util.JobLimiter;
import com.android.gallery3d.util.ThreadPool.Job;
import com.android.gallery3d.util.ThreadPool.JobContext;

public class AlbumSlidingWindow implements AlbumView.ModelListener {
    @SuppressWarnings("unused")
    private static final String TAG = "AlbumSlidingWindow";

    private static final int MSG_LOAD_BITMAP_DONE = 0;
    private static final int MSG_UPDATE_SLOT = 1;
    private static final int JOB_LIMIT = 2;
    private static final int PLACEHOLDER_COLOR = 0xFF222222;

    public static interface Listener {
        public void onSizeChanged(int size);
        public void onContentChanged();
    }

    private final AlbumView.Model mSource;
    private int mSize;

    private int mContentStart = 0;
    private int mContentEnd = 0;

    private int mActiveStart = 0;
    private int mActiveEnd = 0;

    private Listener mListener;
    private int mFocusIndex = -1;

    private final AlbumDisplayItem mData[];
    private final ColorTexture mWaitLoadingTexture;
    private SelectionDrawer mSelectionDrawer;

    private SynchronizedHandler mHandler;
    private JobLimiter mThreadPool;

    private int mActiveRequestCount = 0;
    private boolean mIsActive = false;

    private int mCacheThumbSize;  // 0: Don't cache the thumbnails
    private LruCache<Path, Bitmap> mImageCache = new LruCache<Path, Bitmap>(1000);

    public AlbumSlidingWindow(GalleryActivity activity,
            AlbumView.Model source, int cacheSize,
            int cacheThumbSize) {
        source.setModelListener(this);
        mSource = source;
        mData = new AlbumDisplayItem[cacheSize];
        mSize = source.size();

        mWaitLoadingTexture = new ColorTexture(PLACEHOLDER_COLOR);
        mWaitLoadingTexture.setSize(1, 1);
        mCacheThumbSize = cacheThumbSize;

        mHandler = new SynchronizedHandler(activity.getGLRoot()) {
            @Override
            public void handleMessage(Message message) {
                switch (message.what) {
                    case MSG_LOAD_BITMAP_DONE: {
                        ((AlbumDisplayItem) message.obj).onLoadBitmapDone();
                        break;
                    }
                    case MSG_UPDATE_SLOT: {
                        updateSlotContent(message.arg1);
                        break;
                    }
                }
            }
        };

        mThreadPool = new JobLimiter(activity.getThreadPool(), JOB_LIMIT);
    }

    public void setSelectionDrawer(SelectionDrawer drawer) {
        mSelectionDrawer = drawer;
    }

    public void setListener(Listener listener) {
        mListener = listener;
    }

    public void setFocusIndex(int slotIndex) {
        mFocusIndex = slotIndex;
    }

    public DisplayItem get(int slotIndex) {
        if (!isActiveSlot(slotIndex)) {
            Utils.fail("invalid slot: %s outsides (%s, %s)",
                    slotIndex, mActiveStart, mActiveEnd);
        }
        return mData[slotIndex % mData.length];
    }

    public boolean isActiveSlot(int slotIndex) {
        return slotIndex >= mActiveStart && slotIndex < mActiveEnd;
    }

    private void setContentWindow(int contentStart, int contentEnd) {
        if (contentStart == mContentStart && contentEnd == mContentEnd) return;

        if (!mIsActive) {
            mContentStart = contentStart;
            mContentEnd = contentEnd;
            mSource.setActiveWindow(contentStart, contentEnd);
            return;
        }

        if (contentStart >= mContentEnd || mContentStart >= contentEnd) {
            for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
                freeSlotContent(i);
            }
            mSource.setActiveWindow(contentStart, contentEnd);
            for (int i = contentStart; i < contentEnd; ++i) {
                prepareSlotContent(i);
            }
        } else {
            for (int i = mContentStart; i < contentStart; ++i) {
                freeSlotContent(i);
            }
            for (int i = contentEnd, n = mContentEnd; i < n; ++i) {
                freeSlotContent(i);
            }
            mSource.setActiveWindow(contentStart, contentEnd);
            for (int i = contentStart, n = mContentStart; i < n; ++i) {
                prepareSlotContent(i);
            }
            for (int i = mContentEnd; i < contentEnd; ++i) {
                prepareSlotContent(i);
            }
        }

        mContentStart = contentStart;
        mContentEnd = contentEnd;
    }

    public void setActiveWindow(int start, int end) {
        if (!(start <= end && end - start <= mData.length && end <= mSize)) {
            Utils.fail("%s, %s, %s, %s", start, end, mData.length, mSize);
        }
        DisplayItem data[] = mData;

        mActiveStart = start;
        mActiveEnd = end;

        int contentStart = Utils.clamp((start + end) / 2 - data.length / 2,
                0, Math.max(0, mSize - data.length));
        int contentEnd = Math.min(contentStart + data.length, mSize);
        setContentWindow(contentStart, contentEnd);
        if (mIsActive) updateAllImageRequests();
    }

    // We would like to request non active slots in the following order:
    // Order:    8 6 4 2                   1 3 5 7
    //         |---------|---------------|---------|
    //                   |<-  active  ->|
    //         |<-------- cached range ----------->|
    private void requestNonactiveImages() {
        int range = Math.max(
                (mContentEnd - mActiveEnd), (mActiveStart - mContentStart));
        for (int i = 0 ;i < range; ++i) {
            requestSlotImage(mActiveEnd + i, false);
            requestSlotImage(mActiveStart - 1 - i, false);
        }
    }

    private void requestSlotImage(int slotIndex, boolean isActive) {
        if (slotIndex < mContentStart || slotIndex >= mContentEnd) return;
        AlbumDisplayItem item = mData[slotIndex % mData.length];
        item.requestImage();
    }

    private void cancelNonactiveImages() {
        int range = Math.max(
                (mContentEnd - mActiveEnd), (mActiveStart - mContentStart));
        for (int i = 0 ;i < range; ++i) {
            cancelSlotImage(mActiveEnd + i, false);
            cancelSlotImage(mActiveStart - 1 - i, false);
        }
    }

    private void cancelSlotImage(int slotIndex, boolean isActive) {
        if (slotIndex < mContentStart || slotIndex >= mContentEnd) return;
        AlbumDisplayItem item = mData[slotIndex % mData.length];
        item.cancelImageRequest();
    }

    private void freeSlotContent(int slotIndex) {
        AlbumDisplayItem data[] = mData;
        int index = slotIndex % data.length;
        AlbumDisplayItem original = data[index];
        if (original != null) {
            original.recycle();
            data[index] = null;
        }
    }

    private void prepareSlotContent(final int slotIndex) {
        mData[slotIndex % mData.length] = new AlbumDisplayItem(
                slotIndex, mSource.get(slotIndex));
    }

    private void updateSlotContent(final int slotIndex) {
        MediaItem item = mSource.get(slotIndex);
        AlbumDisplayItem data[] = mData;
        int index = slotIndex % data.length;
        AlbumDisplayItem original = data[index];
        AlbumDisplayItem update = new AlbumDisplayItem(slotIndex, item);
        data[index] = update;
        boolean isActive = isActiveSlot(slotIndex);
        if (mListener != null && isActive) {
            mListener.onContentChanged();
        }
        if (original != null) {
            if (isActive && original.isRequestInProgress()) {
                --mActiveRequestCount;
            }
            original.recycle();
        }
        if (isActive) {
            if (mActiveRequestCount == 0) cancelNonactiveImages();
            ++mActiveRequestCount;
            update.requestImage();
        } else {
            if (mActiveRequestCount == 0) update.requestImage();
        }
    }

    private void updateAllImageRequests() {
        mActiveRequestCount = 0;
        AlbumDisplayItem data[] = mData;
        for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) {
            AlbumDisplayItem item = data[i % data.length];
            item.requestImage();
            if (item.isRequestInProgress()) ++mActiveRequestCount;
        }
        if (mActiveRequestCount == 0) {
            requestNonactiveImages();
        } else {
            cancelNonactiveImages();
        }
    }

    private class AlbumDisplayItem extends AbstractDisplayItem
            implements FutureListener<Bitmap>, Job<Bitmap> {
        private Future<Bitmap> mFuture;
        private final int mSlotIndex;
        private final int mMediaType;
        private Texture mContent;
        private boolean mIsPanorama;
        private boolean mWaitLoadingDisplayed;

        public AlbumDisplayItem(int slotIndex, MediaItem item) {
            super(item);
            mMediaType = (item == null)
                    ? MediaItem.MEDIA_TYPE_UNKNOWN
                    : item.getMediaType();
            mSlotIndex = slotIndex;
            mIsPanorama = GalleryUtils.isPanorama(item);
            updateContent(mWaitLoadingTexture);
        }

        @Override
        protected void recycleBitmap(Bitmap bitmap) {
            // if mCacheThumbSize > 0, we will keep images in cache so that
            // we cannot recycle the bitmap
            if (mCacheThumbSize == 0) {
                BitmapPool.recycle(BitmapPool.TYPE_MICRO_THUMB, bitmap);
            }
        }

        @Override
        protected void onBitmapAvailable(Bitmap bitmap) {
            boolean isActiveSlot = isActiveSlot(mSlotIndex);
            if (isActiveSlot) {
                --mActiveRequestCount;
                if (mActiveRequestCount == 0) requestNonactiveImages();
            }
            if (bitmap != null) {
                BitmapTexture texture = new BitmapTexture(bitmap, true);
                texture.setThrottled(true);
                if (mWaitLoadingDisplayed) {
                    updateContent(new FadeInTexture(PLACEHOLDER_COLOR, texture));
                } else {
                    updateContent(texture);
                }
                if (mListener != null && isActiveSlot) {
                    mListener.onContentChanged();
                }
            }
        }

        private void updateContent(Texture content) {
            mContent = content;
        }

        @Override
        public int render(GLCanvas canvas, int pass) {
            // Fit the content into the box
            int width = mContent.getWidth();
            int height = mContent.getHeight();

            float scalex = mBoxWidth / (float) width;
            float scaley = mBoxHeight / (float) height;
            float scale = Math.min(scalex, scaley);

            width = (int) FloatMath.floor(width * scale);
            height = (int) FloatMath.floor(height * scale);

            // Now draw it
            if (pass == 0) {
                Path path = null;
                if (mMediaItem != null) path = mMediaItem.getPath();
                mSelectionDrawer.draw(canvas, mContent, width, height,
                        getRotation(), path, mMediaType, mIsPanorama);
                if (mContent == mWaitLoadingTexture) {
                       mWaitLoadingDisplayed = true;
                }
                int result = 0;
                if (mFocusIndex == mSlotIndex) {
                    result |= SlotView.RENDER_MORE_PASS;
                }
                if ((mContent instanceof FadeInTexture) &&
                        ((FadeInTexture) mContent).isAnimating()) {
                    result |= SlotView.RENDER_MORE_FRAME;
                }
                return result;
            } else if (pass == 1) {
                mSelectionDrawer.drawFocus(canvas, width, height);
            }
            return 0;
        }

        @Override
        public void startLoadBitmap() {
            if (mCacheThumbSize > 0) {
                Path path = mMediaItem.getPath();
                if (mImageCache.containsKey(path)) {
                    Bitmap bitmap = mImageCache.get(path);
                    updateImage(bitmap, false);
                    return;
                }
                mFuture = mThreadPool.submit(this, this);
            } else {
                mFuture = mThreadPool.submit(mMediaItem.requestImage(
                        MediaItem.TYPE_MICROTHUMBNAIL), this);
            }
        }

        // This gets the bitmap and scale it down.
        public Bitmap run(JobContext jc) {
            Job<Bitmap> job = mMediaItem.requestImage(
                    MediaItem.TYPE_MICROTHUMBNAIL);
            Bitmap bitmap = job.run(jc);
            if (bitmap != null) {
                bitmap = BitmapUtils.resizeDownBySideLength(
                        bitmap, mCacheThumbSize, true);
            }
            return bitmap;
        }

        @Override
        public void cancelLoadBitmap() {
            if (mFuture != null) {
                mFuture.cancel();
            }
        }

        @Override
        public void onFutureDone(Future<Bitmap> bitmap) {
            mHandler.sendMessage(mHandler.obtainMessage(MSG_LOAD_BITMAP_DONE, this));
        }

        private void onLoadBitmapDone() {
            Future<Bitmap> future = mFuture;
            mFuture = null;
            Bitmap bitmap = future.get();
            boolean isCancelled = future.isCancelled();
            if (mCacheThumbSize > 0 && (bitmap != null || !isCancelled)) {
                Path path = mMediaItem.getPath();
                mImageCache.put(path, bitmap);
            }
            updateImage(bitmap, isCancelled);
        }

        @Override
        public String toString() {
            return String.format("AlbumDisplayItem[%s]", mSlotIndex);
        }
    }

    public void onSizeChanged(int size) {
        if (mSize != size) {
            mSize = size;
            if (mListener != null) mListener.onSizeChanged(mSize);
        }
    }

    public void onWindowContentChanged(int index) {
        if (index >= mContentStart && index < mContentEnd && mIsActive) {
            updateSlotContent(index);
        }
    }

    public void resume() {
        mIsActive = true;
        for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
            prepareSlotContent(i);
        }
        updateAllImageRequests();
    }

    public void pause() {
        mIsActive = false;
        for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
            freeSlotContent(i);
        }
        mImageCache.clear();
    }
}
