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

import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;

public class KeyguardWidgetFrame extends FrameLayout {
    private final static PorterDuffXfermode sAddBlendMode =
            new PorterDuffXfermode(PorterDuff.Mode.ADD);

    static final float OUTLINE_ALPHA_MULTIPLIER = 0.6f;
    static final int HOVER_OVER_DELETE_DROP_TARGET_OVERLAY_COLOR = 0x99FF0000;

    // Temporarily disable this for the time being until we know why the gfx is messing up
    static final boolean ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY = true;

    private int mGradientColor;
    private LinearGradient mForegroundGradient;
    private LinearGradient mLeftToRightGradient;
    private LinearGradient mRightToLeftGradient;
    private Paint mGradientPaint = new Paint();
    boolean mLeftToRight = true;

    private float mOverScrollAmount = 0f;
    private final Rect mForegroundRect = new Rect();
    private int mForegroundAlpha = 0;
    private CheckLongPressHelper mLongPressHelper;
    private Animator mFrameFade;
    private boolean mIsSmall = false;
    private Handler mWorkerHandler;

    private float mBackgroundAlpha;
    private float mContentAlpha;
    private float mBackgroundAlphaMultiplier = 1.0f;
    private Drawable mBackgroundDrawable;
    private Rect mBackgroundRect = new Rect();

    // These variables are all needed in order to size things properly before we're actually
    // measured.
    private int mSmallWidgetHeight;
    private int mSmallFrameHeight;
    private boolean mWidgetLockedSmall = false;
    private int mMaxChallengeTop = -1;
    private int mFrameStrokeAdjustment;
    private boolean mPerformAppWidgetSizeUpdateOnBootComplete;

    // This will hold the width value before we've actually been measured
    private int mFrameHeight;

    private boolean mIsHoveringOverDeleteDropTarget;

    // Multiple callers may try and adjust the alpha of the frame. When a caller shows
    // the outlines, we give that caller control, and nobody else can fade them out.
    // This prevents animation conflicts.
    private Object mBgAlphaController;

    public KeyguardWidgetFrame(Context context) {
        this(context, null, 0);
    }

    public KeyguardWidgetFrame(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public KeyguardWidgetFrame(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        mLongPressHelper = new CheckLongPressHelper(this);

        Resources res = context.getResources();
        // TODO: this padding should really correspond to the padding embedded in the background
        // drawable (ie. outlines).
        float density = res.getDisplayMetrics().density;
        int padding = (int) (res.getDisplayMetrics().density * 8);
        setPadding(padding, padding, padding, padding);

        mFrameStrokeAdjustment = 2 + (int) (2 * density);

        // This will be overriden on phones based on the current security mode, however on tablets
        // we need to specify a height.
        mSmallWidgetHeight =
                res.getDimensionPixelSize(R.dimen.kg_small_widget_height);
        mBackgroundDrawable = res.getDrawable(R.drawable.kg_widget_bg_padded);
        mGradientColor = res.getColor(R.color.kg_widget_pager_gradient);
        mGradientPaint.setXfermode(sAddBlendMode);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        cancelLongPress();
        KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitorCallbacks);

    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallbacks);
    }

    private KeyguardUpdateMonitorCallback mUpdateMonitorCallbacks =
            new KeyguardUpdateMonitorCallback() {
        @Override
        public void onBootCompleted() {
            if (mPerformAppWidgetSizeUpdateOnBootComplete) {
                performAppWidgetSizeCallbacksIfNecessary();
                mPerformAppWidgetSizeUpdateOnBootComplete = false;
            }
        }
    };

    void setIsHoveringOverDeleteDropTarget(boolean isHovering) {
        if (ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY) {
            if (mIsHoveringOverDeleteDropTarget != isHovering) {
                mIsHoveringOverDeleteDropTarget = isHovering;
                int resId = isHovering ? R.string.keyguard_accessibility_delete_widget_start
                        : R.string.keyguard_accessibility_delete_widget_end;
                String text = getContext().getResources().getString(resId, getContentDescription());
                announceForAccessibility(text);
                invalidate();
            }
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        // Watch for longpress events at this level to make sure
        // users can always pick up this widget
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mLongPressHelper.postCheckForLongPress(ev);
                break;
            case MotionEvent.ACTION_MOVE:
                mLongPressHelper.onMove(ev);
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mLongPressHelper.cancelLongPress();
                break;
        }

        // Otherwise continue letting touch events fall through to children
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        // Watch for longpress events at this level to make sure
        // users can always pick up this widget
        switch (ev.getAction()) {
            case MotionEvent.ACTION_MOVE:
                mLongPressHelper.onMove(ev);
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mLongPressHelper.cancelLongPress();
                break;
        }

        // We return true here to ensure that we will get cancel / up signal
        // even if none of our children have requested touch.
        return true;
    }

    @Override
    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
        super.requestDisallowInterceptTouchEvent(disallowIntercept);
        cancelLongPress();
    }

    @Override
    public void cancelLongPress() {
        super.cancelLongPress();
        mLongPressHelper.cancelLongPress();
    }


    private void drawGradientOverlay(Canvas c) {
        mGradientPaint.setShader(mForegroundGradient);
        mGradientPaint.setAlpha(mForegroundAlpha);
        c.drawRect(mForegroundRect, mGradientPaint);
    }

    private void drawHoveringOverDeleteOverlay(Canvas c) {
        if (mIsHoveringOverDeleteDropTarget) {
            c.drawColor(HOVER_OVER_DELETE_DROP_TARGET_OVERLAY_COLOR);
        }
    }

    protected void drawBg(Canvas canvas) {
        if (mBackgroundAlpha > 0.0f) {
            Drawable bg = mBackgroundDrawable;

            bg.setAlpha((int) (mBackgroundAlpha * mBackgroundAlphaMultiplier * 255));
            bg.setBounds(mBackgroundRect);
            bg.draw(canvas);
        }
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        if (ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY) {
            canvas.save();
        }
        drawBg(canvas);
        super.dispatchDraw(canvas);
        drawGradientOverlay(canvas);
        if (ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY) {
            drawHoveringOverDeleteOverlay(canvas);
            canvas.restore();
        }
    }

    /**
     * Because this view has fading outlines, it is essential that we enable hardware
     * layers on the content (child) so that updating the alpha of the outlines doesn't
     * result in the content layer being recreated.
     */
    public void enableHardwareLayersForContent() {
        View widget = getContent();
        if (widget != null && widget.isHardwareAccelerated()) {
            widget.setLayerType(LAYER_TYPE_HARDWARE, null);
        }
    }

    /**
     * Because this view has fading outlines, it is essential that we enable hardware
     * layers on the content (child) so that updating the alpha of the outlines doesn't
     * result in the content layer being recreated.
     */
    public void disableHardwareLayersForContent() {
        View widget = getContent();
        if (widget != null) {
            widget.setLayerType(LAYER_TYPE_NONE, null);
        }
    }

    public View getContent() {
        return getChildAt(0);
    }

    public int getContentAppWidgetId() {
        View content = getContent();
        if (content instanceof AppWidgetHostView) {
            return ((AppWidgetHostView) content).getAppWidgetId();
        } else if (content instanceof KeyguardStatusView) {
            return ((KeyguardStatusView) content).getAppWidgetId();
        } else {
            return AppWidgetManager.INVALID_APPWIDGET_ID;
        }
    }

    public float getBackgroundAlpha() {
        return mBackgroundAlpha;
    }

    public void setBackgroundAlphaMultiplier(float multiplier) {
        if (Float.compare(mBackgroundAlphaMultiplier, multiplier) != 0) {
            mBackgroundAlphaMultiplier = multiplier;
            invalidate();
        }
    }

    public float getBackgroundAlphaMultiplier() {
        return mBackgroundAlphaMultiplier;
    }

    public void setBackgroundAlpha(float alpha) {
        if (Float.compare(mBackgroundAlpha, alpha) != 0) {
            mBackgroundAlpha = alpha;
            invalidate();
        }
    }

    public float getContentAlpha() {
        return mContentAlpha;
    }

    public void setContentAlpha(float alpha) {
        mContentAlpha = alpha;
        View content = getContent();
        if (content != null) {
            content.setAlpha(alpha);
        }
    }

    /**
     * Depending on whether the security is up, the widget size needs to change
     *
     * @param height The height of the widget, -1 for full height
     */
    private void setWidgetHeight(int height) {
        boolean needLayout = false;
        View widget = getContent();
        if (widget != null) {
            LayoutParams lp = (LayoutParams) widget.getLayoutParams();
            if (lp.height != height) {
                needLayout = true;
                lp.height = height;
            }
        }
        if (needLayout) {
            requestLayout();
        }
    }

    public void setMaxChallengeTop(int top) {
        boolean dirty = mMaxChallengeTop != top;
        mMaxChallengeTop = top;
        mSmallWidgetHeight = top - getPaddingTop();
        mSmallFrameHeight = top + getPaddingBottom();
        if (dirty && mIsSmall) {
            setWidgetHeight(mSmallWidgetHeight);
            setFrameHeight(mSmallFrameHeight);
        } else if (dirty && mWidgetLockedSmall) {
            setWidgetHeight(mSmallWidgetHeight);
        }
    }

    public boolean isSmall() {
        return mIsSmall;
    }

    public void adjustFrame(int challengeTop) {
        int frameHeight = challengeTop + getPaddingBottom();
        setFrameHeight(frameHeight);
    }

    public void shrinkWidget(boolean alsoShrinkFrame) {
        mIsSmall = true;
        setWidgetHeight(mSmallWidgetHeight);

        if (alsoShrinkFrame) {
            setFrameHeight(mSmallFrameHeight);
        }
    }

    public int getSmallFrameHeight() {
        return mSmallFrameHeight;
    }

    public void setWidgetLockedSmall(boolean locked) {
        if (locked) {
            setWidgetHeight(mSmallWidgetHeight);
        }
        mWidgetLockedSmall = locked;
    }

    public void resetSize() {
        mIsSmall = false;
        if (!mWidgetLockedSmall) {
            setWidgetHeight(LayoutParams.MATCH_PARENT);
        }
        setFrameHeight(getMeasuredHeight());
    }

    public void setFrameHeight(int height) {
        mFrameHeight = height;
        mBackgroundRect.set(0, 0, getMeasuredWidth(), Math.min(mFrameHeight, getMeasuredHeight()));
        mForegroundRect.set(mFrameStrokeAdjustment, mFrameStrokeAdjustment,getMeasuredWidth() -
                mFrameStrokeAdjustment, Math.min(getMeasuredHeight(), mFrameHeight) -
                mFrameStrokeAdjustment);
        updateGradient();
        invalidate();
    }

    public void hideFrame(Object caller) {
        fadeFrame(caller, false, 0f, KeyguardWidgetPager.CHILDREN_OUTLINE_FADE_OUT_DURATION);
    }

    public void showFrame(Object caller) {
        fadeFrame(caller, true, OUTLINE_ALPHA_MULTIPLIER,
                KeyguardWidgetPager.CHILDREN_OUTLINE_FADE_IN_DURATION);
    }

    public void fadeFrame(Object caller, boolean takeControl, float alpha, int duration) {
        if (takeControl) {
            mBgAlphaController = caller;
        }

        if (mBgAlphaController != caller && mBgAlphaController != null) {
            return;
        }

        if (mFrameFade != null) {
            mFrameFade.cancel();
            mFrameFade = null;
        }
        PropertyValuesHolder bgAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", alpha);
        mFrameFade = ObjectAnimator.ofPropertyValuesHolder(this, bgAlpha);
        mFrameFade.setDuration(duration);
        mFrameFade.start();
    }

    private void updateGradient() {
        float x0 = mLeftToRight ? 0 : mForegroundRect.width();
        float x1 = mLeftToRight ? mForegroundRect.width(): 0;
        mLeftToRightGradient = new LinearGradient(x0, 0f, x1, 0f,
                mGradientColor, 0, Shader.TileMode.CLAMP);
        mRightToLeftGradient = new LinearGradient(x1, 0f, x0, 0f,
                mGradientColor, 0, Shader.TileMode.CLAMP);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        if (!mIsSmall) {
            mFrameHeight = h;
        }

        // mFrameStrokeAdjustment is a cludge to prevent the overlay from drawing outside the
        // rounded rect background.
        mForegroundRect.set(mFrameStrokeAdjustment, mFrameStrokeAdjustment,
                w - mFrameStrokeAdjustment, Math.min(h, mFrameHeight) - mFrameStrokeAdjustment);

        mBackgroundRect.set(0, 0, getMeasuredWidth(), Math.min(h, mFrameHeight));
        updateGradient();
        invalidate();
    }

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        performAppWidgetSizeCallbacksIfNecessary();
    }

    private void performAppWidgetSizeCallbacksIfNecessary() {
        View content = getContent();
        if (!(content instanceof AppWidgetHostView)) return;

        if (!KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
            mPerformAppWidgetSizeUpdateOnBootComplete = true;
            return;
        }

        // TODO: there's no reason to force the AppWidgetHostView to catch duplicate size calls.
        // We can do that even more cheaply here. It's not an issue right now since we're in the
        // system process and hence no binder calls.
        AppWidgetHostView awhv = (AppWidgetHostView) content;
        float density = getResources().getDisplayMetrics().density;

        int width = (int) (content.getMeasuredWidth() / density);
        int height = (int) (content.getMeasuredHeight() / density);
        awhv.updateAppWidgetSize(null, width, height, width, height, true);
    }

    void setOverScrollAmount(float r, boolean left) {
        if (Float.compare(mOverScrollAmount, r) != 0) {
            mOverScrollAmount = r;
            mForegroundGradient = left ? mLeftToRightGradient : mRightToLeftGradient;
            mForegroundAlpha = (int) Math.round((0.5f * r * 255));

            // We bump up the alpha of the outline to hide the fact that the overlay is drawing
            // over the rounded part of the frame.
            float bgAlpha = Math.min(OUTLINE_ALPHA_MULTIPLIER + r * (1 - OUTLINE_ALPHA_MULTIPLIER),
                    1f);
            setBackgroundAlpha(bgAlpha);
            invalidate();
        }
    }

    public void onActive(boolean isActive) {
        // hook for subclasses
    }

    public boolean onUserInteraction(MotionEvent event) {
        // hook for subclasses
        return false;
    }

    public void onBouncerShowing(boolean showing) {
        // hook for subclasses
    }

    public void setWorkerHandler(Handler workerHandler) {
        mWorkerHandler = workerHandler;
    }

    public Handler getWorkerHandler() {
        return mWorkerHandler;
    }

}
