package com.android.gallery3d.ui;

import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;

import java.util.ArrayList;

public class DisplayItemPanel extends GLView {

    private static final int TRANSITION_DURATION = 1000;

    // The state of the display item.
    // The state of those items to be removed
    private static final int STATE_REMOVED = 1;

    // The state of the items that is just added to this panel
    private static final int STATE_NEWBIE = 2;

    // The state of the items that changed position
    private static final int STATE_MOVED = 3;

    private static final long NO_ANIMATION = -1;
    private static final long START_ANIMATION = 0;

    private ArrayList<DisplayItem> mItems = new ArrayList<DisplayItem>();

    private long mAnimationStartTime = NO_ANIMATION;
    private boolean mPrepareTransition = false;
    private final Interpolator mInterpolator = new DecelerateInterpolator(4);

    /**
     * Puts the item center at the given position and angle.
     */
    public void putDisplayItem(
            DisplayItem item, float x, float y, float theata) {
        if (item.mPanel != this && item.mPanel != null) {
            throw new IllegalArgumentException();
        }
        item.mTarget.set(x, y, theata);

        if (item.mPanel != this) {
            item.mPanel = this;
            item.mState = STATE_NEWBIE;
            mItems.add(item);
            item.mCurrent.set(x, y, theata);
        } else {
            item.mState = STATE_MOVED;
            if (mPrepareTransition) {
                item.mSource.set(item.mCurrent);
            } else {
                item.mCurrent.set(x, y, theata);
            }
        }
        if (!mPrepareTransition) invalidate();
    }

    public void removeDisplayItem(DisplayItem item) {
        if (item.mPanel != this) throw new IllegalArgumentException();
        mItems.remove(item);
        item.mPanel = null;
    }

    public void prepareTransition() {
        mPrepareTransition = true;
        for (DisplayItem item : mItems) {
            item.mState = STATE_REMOVED;
        }
    }

    public void startTransition() {
        mPrepareTransition = false;
        mAnimationStartTime = START_ANIMATION;
        invalidate();
    }

    private void onTransitionComplete() {
        ArrayList<DisplayItem> list = new ArrayList<DisplayItem>();
        for (DisplayItem item: mItems) {
            if (item.mState == STATE_REMOVED) {
                item.mPanel = null;
            } else {
                list.add(item);
            }
        }
        mItems = list;
    }

    @Override
    protected void render(GLCanvas canvas) {
        canvas.translate(-mScrollX, 0, 0);
        if (mAnimationStartTime == NO_ANIMATION) {
            for (DisplayItem item: mItems) {
                renderItem(canvas, item);
            }
        } else {
            long now = canvas.currentAnimationTimeMillis();
            if (mAnimationStartTime == START_ANIMATION) {
                mAnimationStartTime = now;
            }
            float timeRatio = Util.clamp((float)
                    (now - mAnimationStartTime) / TRANSITION_DURATION,  0, 1);
            float interpolate = mInterpolator.getInterpolation(timeRatio);
            for (DisplayItem item: mItems) {
                renderItem(canvas, item, interpolate);
            }
            if (timeRatio == 1.0f) {
                onTransitionComplete();
                mAnimationStartTime = NO_ANIMATION;
            } else {
                invalidate();
            }
        }
        canvas.translate(mScrollX, 0, 0);
    }

    private void renderItem(GLCanvas canvas, DisplayItem item) {
        canvas.save(GLCanvas.ALPHA_SAVE_FLAG | GLCanvas.MATRIX_SAVE_FLAG);
        item.mCurrent.apply(canvas);
        item.render(canvas);
        canvas.restore();
    }

    private void renderItem(
            GLCanvas canvas, DisplayItem item, float interpolate) {
        canvas.save(GLCanvas.ALPHA_SAVE_FLAG | GLCanvas.MATRIX_SAVE_FLAG);
        switch (item.mState) {
            case STATE_MOVED:
                item.updateCurrentPosition(interpolate);
                break;
            case STATE_NEWBIE:
                canvas.multiplyAlpha(interpolate);
                break;
            case STATE_REMOVED:
                canvas.multiplyAlpha(1.0f - interpolate);
                break;
        }
        item.mCurrent.apply(canvas);
        item.render(canvas);
        canvas.restore();
    }
}
