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

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

import com.android.camera.app.CameraAppUI;
import com.android.camera.debug.Log;
import com.android.camera.util.Gusterpolator;
import com.android.camera2.R;

/**
 * This view is designed to handle all the animations during camera mode transition.
 * It should only be visible during mode switch.
 */
public class ModeTransitionView extends View {
    private static final Log.Tag TAG = new Log.Tag("ModeTransView");

    private static final int PEEP_HOLE_ANIMATION_DURATION_MS = 300;
    private static final int ICON_FADE_OUT_DURATION_MS = 850;
    private static final int FADE_OUT_DURATION_MS = 250;

    private static final int IDLE = 0;
    private static final int PULL_UP_SHADE = 1;
    private static final int PULL_DOWN_SHADE = 2;
    private static final int PEEP_HOLE_ANIMATION = 3;
    private static final int FADE_OUT = 4;

    private static final float SCROLL_DISTANCE_MULTIPLY_FACTOR = 2f;
    private static final int ALPHA_FULLY_TRANSPARENT = 0;
    private static final int ALPHA_FULLY_OPAQUE = 255;
    private static final int ALPHA_HALF_TRANSPARENT = 127;

    private final GestureDetector mGestureDetector;
    private final Paint mMaskPaint = new Paint();
    private final Rect mIconRect = new Rect();
    /** An empty drawable to fall back to when mIconDrawable set to null. */
    private final Drawable mDefaultDrawable = new ColorDrawable();

    private Drawable mIconDrawable;
    private int mBackgroundColor;
    private int mWidth = 0;
    private int mHeight = 0;
    private int mPeepHoleCenterX = 0;
    private int mPeepHoleCenterY = 0;
    private float mRadius = 0f;
    private int mIconSize;
    private AnimatorSet mPeepHoleAnimator;
    private int mAnimationType = PEEP_HOLE_ANIMATION;
    private float mScrollDistance = 0;
    private final Path mShadePath = new Path();
    private final Paint mShadePaint = new Paint();
    private CameraAppUI.AnimationFinishedListener mAnimationFinishedListener;
    private float mScrollTrend;

    public ModeTransitionView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mMaskPaint.setAlpha(0);
        mMaskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        mBackgroundColor = getResources().getColor(R.color.video_mode_color);
        mGestureDetector = new GestureDetector(getContext(),
                new GestureDetector.SimpleOnGestureListener() {
                    @Override
                    public boolean onDown(MotionEvent ev) {
                        setScrollDistance(0f);
                        mScrollTrend = 0f;
                        return true;
                    }

                    @Override
                    public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                            float distanceX, float distanceY) {
                        setScrollDistance(getScrollDistance()
                                + SCROLL_DISTANCE_MULTIPLY_FACTOR * distanceY);
                        mScrollTrend = 0.3f * mScrollTrend + 0.7f * distanceY;
                        return false;
                    }
                });
        mIconSize = getResources().getDimensionPixelSize(R.dimen.mode_transition_view_icon_size);
        setIconDrawable(mDefaultDrawable);
    }

    /**
     * Updates the size and shape of the shade
     */
    private void updateShade() {
        if (mAnimationType == PULL_UP_SHADE || mAnimationType == PULL_DOWN_SHADE) {
            mShadePath.reset();
            float shadeHeight;
            if (mAnimationType == PULL_UP_SHADE) {
                // Scroll distance > 0.
                mShadePath.addRect(0, mHeight - getScrollDistance(), mWidth, mHeight,
                        Path.Direction.CW);
                shadeHeight = getScrollDistance();
            } else {
                // Scroll distance < 0.
                mShadePath.addRect(0, 0, mWidth, - getScrollDistance(), Path.Direction.CW);
                shadeHeight = getScrollDistance() * (-1);
            }

            if (mIconDrawable != null) {
                if (shadeHeight < mHeight / 2 || mHeight == 0) {
                    mIconDrawable.setAlpha(ALPHA_FULLY_TRANSPARENT);
                } else {
                    int alpha  = ((int) shadeHeight - mHeight / 2)  * ALPHA_FULLY_OPAQUE
                            / (mHeight / 2);
                    mIconDrawable.setAlpha(alpha);
                }
            }
            invalidate();
        }
    }

    /**
     * Sets the scroll distance. Note this function gets called in every
     * frame during animation. It should be very light weight.
     *
     * @param scrollDistance the scaled distance that user has scrolled
     */
    public void setScrollDistance(float scrollDistance) {
        // First make sure scroll distance is clamped to the valid range.
        if (mAnimationType == PULL_UP_SHADE) {
            scrollDistance = Math.min(scrollDistance, mHeight);
            scrollDistance = Math.max(scrollDistance, 0);
        } else if (mAnimationType == PULL_DOWN_SHADE) {
            scrollDistance = Math.min(scrollDistance, 0);
            scrollDistance = Math.max(scrollDistance, -mHeight);
        }
        mScrollDistance = scrollDistance;
        updateShade();
    }

    public float getScrollDistance() {
        return mScrollDistance;
    }

    @Override
    public void onDraw(Canvas canvas) {
        if (mAnimationType == PEEP_HOLE_ANIMATION) {
            canvas.drawColor(mBackgroundColor);
            if (mPeepHoleAnimator != null) {
                // Draw a transparent circle using clear mode
                canvas.drawCircle(mPeepHoleCenterX, mPeepHoleCenterY, mRadius, mMaskPaint);
            }
        } else if (mAnimationType == PULL_UP_SHADE || mAnimationType == PULL_DOWN_SHADE) {
            canvas.drawPath(mShadePath, mShadePaint);
        } else if (mAnimationType == IDLE || mAnimationType == FADE_OUT) {
            canvas.drawColor(mBackgroundColor);
        }
        super.onDraw(canvas);
        mIconDrawable.draw(canvas);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        mWidth = right - left;
        mHeight = bottom - top;
        // Center the icon in the view.
        mIconRect.set(mWidth / 2 - mIconSize / 2, mHeight / 2 - mIconSize / 2,
                mWidth / 2 + mIconSize / 2, mHeight / 2 + mIconSize / 2);
        mIconDrawable.setBounds(mIconRect);
    }

    /**
     * This is an overloaded function. When no position is provided for the animation,
     * the peep hole will start at the default position (i.e. center of the view).
     */
    public void startPeepHoleAnimation() {
        float x = mWidth / 2;
        float y = mHeight / 2;
        startPeepHoleAnimation(x, y);
    }

    /**
     * Starts the peep hole animation where the circle is centered at position (x, y).
     */
    private void startPeepHoleAnimation(float x, float y) {
        if (mPeepHoleAnimator != null && mPeepHoleAnimator.isRunning()) {
            return;
        }
        mAnimationType = PEEP_HOLE_ANIMATION;
        mPeepHoleCenterX = (int) x;
        mPeepHoleCenterY = (int) y;

        int horizontalDistanceToFarEdge = Math.max(mPeepHoleCenterX, mWidth - mPeepHoleCenterX);
        int verticalDistanceToFarEdge = Math.max(mPeepHoleCenterY, mHeight - mPeepHoleCenterY);
        int endRadius = (int) (Math.sqrt(horizontalDistanceToFarEdge * horizontalDistanceToFarEdge
                + verticalDistanceToFarEdge * verticalDistanceToFarEdge));

        final ValueAnimator radiusAnimator = ValueAnimator.ofFloat(0, endRadius);
        radiusAnimator.setDuration(PEEP_HOLE_ANIMATION_DURATION_MS);

        final ValueAnimator  iconScaleAnimator = ValueAnimator.ofFloat(1f, 0.5f);
        iconScaleAnimator.setDuration(ICON_FADE_OUT_DURATION_MS);

        final ValueAnimator  iconAlphaAnimator = ValueAnimator.ofInt(ALPHA_HALF_TRANSPARENT,
                ALPHA_FULLY_TRANSPARENT);
        iconAlphaAnimator.setDuration(ICON_FADE_OUT_DURATION_MS);

        mPeepHoleAnimator = new AnimatorSet();
        mPeepHoleAnimator.playTogether(radiusAnimator, iconAlphaAnimator, iconScaleAnimator);
        mPeepHoleAnimator.setInterpolator(Gusterpolator.INSTANCE);

        iconAlphaAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                // Modify mask by enlarging the hole
                mRadius = (Float) radiusAnimator.getAnimatedValue();

                mIconDrawable.setAlpha((Integer) iconAlphaAnimator.getAnimatedValue());
                float scale = (Float) iconScaleAnimator.getAnimatedValue();
                int size = (int) (scale * (float) mIconSize);

                mIconDrawable.setBounds(mPeepHoleCenterX - size / 2,
                        mPeepHoleCenterY - size / 2,
                        mPeepHoleCenterX + size / 2,
                        mPeepHoleCenterY + size / 2);

                invalidate();
            }
        });

        mPeepHoleAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                mPeepHoleAnimator = null;
                mRadius = 0;
                mIconDrawable.setAlpha(ALPHA_FULLY_OPAQUE);
                mIconDrawable.setBounds(mIconRect);
                setVisibility(GONE);
                mAnimationType = IDLE;
                if (mAnimationFinishedListener != null) {
                    mAnimationFinishedListener.onAnimationFinished(true);
                    mAnimationFinishedListener = null;
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        mPeepHoleAnimator.start();

    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        boolean touchHandled = mGestureDetector.onTouchEvent(ev);
        if (ev.getActionMasked() == MotionEvent.ACTION_UP) {
            // TODO: Take into account fling
            snap();
        }
        return touchHandled;
    }

    /**
     * Snaps the shade to position at the end of a gesture.
     */
    private void snap() {
        if (mScrollTrend >= 0 && mAnimationType == PULL_UP_SHADE) {
            // Snap to full screen.
            snapShadeTo(mHeight, ALPHA_FULLY_OPAQUE);
        } else if (mScrollTrend <= 0 && mAnimationType == PULL_DOWN_SHADE) {
            // Snap to full screen.
            snapShadeTo(-mHeight, ALPHA_FULLY_OPAQUE);
        } else if (mScrollTrend < 0 && mAnimationType == PULL_UP_SHADE) {
            // Snap back.
            snapShadeTo(0, ALPHA_FULLY_TRANSPARENT, false);
        } else if (mScrollTrend > 0 && mAnimationType == PULL_DOWN_SHADE) {
            // Snap back.
            snapShadeTo(0, ALPHA_FULLY_TRANSPARENT, false);
        }
    }

    private void snapShadeTo(int scrollDistance, int alpha) {
        snapShadeTo(scrollDistance, alpha, true);
    }

    /**
     * Snaps the shade to a given scroll distance and sets the icon alpha. If the shade
     * is to snap back out, then hide the view after the animation.
     *
     * @param scrollDistance scaled user scroll distance
     * @param alpha ending alpha of the icon drawable
     * @param snapToFullScreen whether this snap animation snaps the shade to full screen
     */
    private void snapShadeTo(final int scrollDistance, final int alpha,
                             final boolean snapToFullScreen) {
        if (mAnimationType == PULL_UP_SHADE || mAnimationType == PULL_DOWN_SHADE) {
            ObjectAnimator scrollAnimator = ObjectAnimator.ofFloat(this, "scrollDistance",
                    scrollDistance);
            scrollAnimator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {

                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    setScrollDistance(scrollDistance);
                    mIconDrawable.setAlpha(alpha);
                    mAnimationType = IDLE;
                    if (!snapToFullScreen) {
                        setVisibility(GONE);
                    }
                    if (mAnimationFinishedListener != null) {
                        mAnimationFinishedListener.onAnimationFinished(snapToFullScreen);
                        mAnimationFinishedListener = null;
                    }
                }

                @Override
                public void onAnimationCancel(Animator animation) {

                }

                @Override
                public void onAnimationRepeat(Animator animation) {

                }
            });
            scrollAnimator.setInterpolator(Gusterpolator.INSTANCE);
            scrollAnimator.start();
        }
    }


    /**
     * Set the states for the animation that pulls up a shade with given shade color.
     *
     * @param shadeColorId color id of the shade that will be pulled up
     * @param iconId id of the icon that will appear on top the shade
     * @param listener a listener that will get notified when the animation
     *        is finished. Could be <code>null</code>.
     */
    public void prepareToPullUpShade(int shadeColorId, int iconId,
                                     CameraAppUI.AnimationFinishedListener listener) {
        prepareShadeAnimation(PULL_UP_SHADE, shadeColorId, iconId, listener);
    }

    /**
     * Set the states for the animation that pulls down a shade with given shade color.
     *
     * @param shadeColorId color id of the shade that will be pulled down
     * @param modeIconResourceId id of the icon that will appear on top the shade
     * @param listener a listener that will get notified when the animation
     *        is finished. Could be <code>null</code>.
     */
    public void prepareToPullDownShade(int shadeColorId, int modeIconResourceId,
                                       CameraAppUI.AnimationFinishedListener listener) {;
        prepareShadeAnimation(PULL_DOWN_SHADE, shadeColorId, modeIconResourceId, listener);
    }

    /**
     * Set the states for the animation that involves a shade.
     *
     * @param animationType type of animation that will happen to the shade
     * @param shadeColorId color id of the shade that will be animated
     * @param iconResId id of the icon that will appear on top the shade
     * @param listener a listener that will get notified when the animation
     *        is finished. Could be <code>null</code>.
     */
    private void prepareShadeAnimation(int animationType, int shadeColorId, int iconResId,
                                       CameraAppUI.AnimationFinishedListener listener) {
        mAnimationFinishedListener = listener;
        if (mPeepHoleAnimator != null && mPeepHoleAnimator.isRunning()) {
            mPeepHoleAnimator.end();
        }
        mAnimationType = animationType;
        resetShade(shadeColorId, iconResId);
    }

    /**
     * Reset the shade with the given shade color and icon drawable.
     *
     * @param shadeColorId id of the shade color
     * @param modeIconResourceId resource id of the icon drawable
     */
    private void resetShade(int shadeColorId, int modeIconResourceId) {
        // Sets color for the shade.
        int shadeColor = getResources().getColor(shadeColorId);
        mBackgroundColor = shadeColor;
        mShadePaint.setColor(shadeColor);
        // Reset scroll distance.
        setScrollDistance(0f);
        // Sets new drawable.
        updateIconDrawableByResourceId(modeIconResourceId);
        mIconDrawable.setAlpha(0);
        setVisibility(VISIBLE);
    }

    /**
     * By default, all drawables instances loaded from the same resource share a
     * common state; if you modify the state of one instance, all the other
     * instances will receive the same modification. So here we need to make sure
     * we mutate the drawable loaded from resource.
     *
     * @param modeIconResourceId resource id of the icon drawable
     */
    private void updateIconDrawableByResourceId(int modeIconResourceId) {
        Drawable iconDrawable = getResources().getDrawable(modeIconResourceId);
        if (iconDrawable == null) {
            // Resource id not found
            Log.e(TAG, "Invalid resource id for icon drawable. Setting icon drawable to null.");
            setIconDrawable(null);
            return;
        }
        // Mutate the drawable loaded from resource so modifying its states does
        // not affect other drawable instances loaded from the same resource.
        setIconDrawable(iconDrawable.mutate());
    }

    /**
     * In order to make sure icon drawable is never set to null. Fall back to an
     * empty drawable when icon needs to get reset.
     *
     * @param iconDrawable new drawable for icon. A value of <code>null</code> sets
     *        the icon drawable to the default drawable.
     */
    private void setIconDrawable(Drawable iconDrawable) {
        if (iconDrawable == null) {
            mIconDrawable = mDefaultDrawable;
        } else {
            mIconDrawable = iconDrawable;
        }
    }

    /**
     * Initialize the mode cover with a mode theme color and a mode icon.
     *
     * @param colorId resource id of the mode theme color
     * @param modeIconResourceId resource id of the icon drawable
     */
    public void setupModeCover(int colorId, int modeIconResourceId) {
        // Stop ongoing animation.
        if (mPeepHoleAnimator != null && mPeepHoleAnimator.isRunning()) {
            mPeepHoleAnimator.cancel();
        }
        mAnimationType = IDLE;
        mBackgroundColor = getResources().getColor(colorId);
        // Sets new drawable.
        updateIconDrawableByResourceId(modeIconResourceId);
        mIconDrawable.setAlpha(ALPHA_FULLY_OPAQUE);
        setVisibility(VISIBLE);
    }

    /**
     * Hides the cover view and notifies the
     * {@link com.android.camera.app.CameraAppUI.AnimationFinishedListener} of whether
     * the hide animation is successfully finished.
     *
     * @param animationFinishedListener a listener that will get notified when the
     *        animation is finished. Could be <code>null</code>.
     */
    public void hideModeCover(
            final CameraAppUI.AnimationFinishedListener animationFinishedListener) {
        if (mAnimationType != IDLE) {
            // Nothing to hide.
            if (animationFinishedListener != null) {
                // Animation not successful.
                animationFinishedListener.onAnimationFinished(false);
            }
        } else {
            // Start fade out animation.
            mAnimationType = FADE_OUT;
            ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(this, "alpha", 1f, 0f);
            alphaAnimator.setDuration(FADE_OUT_DURATION_MS);
            // Linear interpolation.
            alphaAnimator.setInterpolator(null);
            alphaAnimator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {

                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    setVisibility(GONE);
                    setAlpha(1f);
                    if (animationFinishedListener != null) {
                        animationFinishedListener.onAnimationFinished(true);
                        mAnimationType = IDLE;
                    }
                }

                @Override
                public void onAnimationCancel(Animator animation) {

                }

                @Override
                public void onAnimationRepeat(Animator animation) {

                }
            });
            alphaAnimator.start();
        }
    }

    @Override
    public void setAlpha(float alpha) {
        super.setAlpha(alpha);
        int alphaScaled = (int) (255f * getAlpha());
        mBackgroundColor = (mBackgroundColor & 0xFFFFFF) | (alphaScaled << 24);
        mIconDrawable.setAlpha(alphaScaled);
    }
}

