/*
 * Copyright (C) 2014 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.systemui.statusbar;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Outline;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewOutlineProvider;

import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.PropertyAnimator;
import com.android.systemui.statusbar.stack.AnimationProperties;
import com.android.systemui.statusbar.stack.StackStateAnimator;

/**
 * Like {@link ExpandableView}, but setting an outline for the height and clipping.
 */
public abstract class ExpandableOutlineView extends ExpandableView {

    private static final AnimatableProperty TOP_ROUNDNESS = AnimatableProperty.from(
            "topRoundness",
            ExpandableOutlineView::setTopRoundnessInternal,
            ExpandableOutlineView::getCurrentTopRoundness,
            R.id.top_roundess_animator_tag,
            R.id.top_roundess_animator_end_tag,
            R.id.top_roundess_animator_start_tag);
    private static final AnimatableProperty BOTTOM_ROUNDNESS = AnimatableProperty.from(
            "bottomRoundness",
            ExpandableOutlineView::setBottomRoundnessInternal,
            ExpandableOutlineView::getCurrentBottomRoundness,
            R.id.bottom_roundess_animator_tag,
            R.id.bottom_roundess_animator_end_tag,
            R.id.bottom_roundess_animator_start_tag);
    private static final AnimationProperties ROUNDNESS_PROPERTIES =
            new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
    private static final Path EMPTY_PATH = new Path();

    private final Rect mOutlineRect = new Rect();
    private final Path mClipPath = new Path();
    private boolean mCustomOutline;
    private float mOutlineAlpha = -1f;
    protected float mOutlineRadius;
    private boolean mAlwaysRoundBothCorners;
    private Path mTmpPath = new Path();
    private Path mTmpPath2 = new Path();
    private float mCurrentBottomRoundness;
    private float mCurrentTopRoundness;
    private float mBottomRoundness;
    private float mTopRoundness;
    private int mBackgroundTop;

    /**
     * {@code true} if the children views of the {@link ExpandableOutlineView} are translated when
     * it is moved. Otherwise, the translation is set on the {@code ExpandableOutlineView} itself.
     */
    protected boolean mShouldTranslateContents;
    private boolean mClipRoundedToClipTopAmount;
    private float mDistanceToTopRoundness = -1;
    private float mExtraWidthForClipping;
    private int mMinimumHeightForClipping = 0;

    private final ViewOutlineProvider mProvider = new ViewOutlineProvider() {
        @Override
        public void getOutline(View view, Outline outline) {
            if (!mCustomOutline && mCurrentTopRoundness == 0.0f
                    && mCurrentBottomRoundness == 0.0f && !mAlwaysRoundBothCorners) {
                int translation = mShouldTranslateContents ? (int) getTranslation() : 0;
                int left = Math.max(translation, 0);
                int top = mClipTopAmount + mBackgroundTop;
                int right = getWidth() + Math.min(translation, 0);
                int bottom = Math.max(getActualHeight() - mClipBottomAmount, top);
                outline.setRect(left, top, right, bottom);
            } else {
                Path clipPath = getClipPath();
                if (clipPath != null && clipPath.isConvex()) {
                    // The path might not be convex in border cases where the view is small and
                    // clipped
                    outline.setConvexPath(clipPath);
                }
            }
            outline.setAlpha(mOutlineAlpha);
        }
    };

    private Path getClipPath() {
        return getClipPath(false, /* ignoreTranslation */
                false /* clipRoundedToBottom */);
    }

    protected Path getClipPath(boolean ignoreTranslation, boolean clipRoundedToBottom) {
        int left;
        int top;
        int right;
        int bottom;
        int height;
        Path intersectPath = null;
        if (!mCustomOutline) {
            int translation = mShouldTranslateContents && !ignoreTranslation
                    ? (int) getTranslation() : 0;
            left = Math.max(translation, 0);
            top = mClipTopAmount + mBackgroundTop;
            right = getWidth() + Math.min(translation, 0);
            bottom = Math.max(getActualHeight(), top);
            int intersectBottom = Math.max(getActualHeight() - mClipBottomAmount, top);
            if (bottom != intersectBottom) {
                if (clipRoundedToBottom) {
                    bottom = intersectBottom;
                } else {
                    getRoundedRectPath(left, top, right,
                            intersectBottom, 0.0f,
                            0.0f, mTmpPath2);
                    intersectPath = mTmpPath2;
                }
            }
        } else {
            left = mOutlineRect.left;
            top = mOutlineRect.top;
            right = mOutlineRect.right;
            bottom = mOutlineRect.bottom;
        }
        height = bottom - top;
        if (height == 0) {
            return EMPTY_PATH;
        }
        float topRoundness = mAlwaysRoundBothCorners
                ? mOutlineRadius : mCurrentTopRoundness * mOutlineRadius;
        float bottomRoundness = mAlwaysRoundBothCorners
                ? mOutlineRadius : mCurrentBottomRoundness * mOutlineRadius;
        if (topRoundness + bottomRoundness > height) {
            float overShoot = topRoundness + bottomRoundness - height;
            topRoundness -= overShoot * mCurrentTopRoundness
                    / (mCurrentTopRoundness + mCurrentBottomRoundness);
            bottomRoundness -= overShoot * mCurrentBottomRoundness
                    / (mCurrentTopRoundness + mCurrentBottomRoundness);
        }
        getRoundedRectPath(left, top, right, bottom, topRoundness,
                bottomRoundness, mTmpPath);
        Path roundedRectPath = mTmpPath;
        if (intersectPath != null) {
            roundedRectPath.op(intersectPath, Path.Op.INTERSECT);
        }
        return roundedRectPath;
    }

    public static void getRoundedRectPath(int left, int top, int right, int bottom,
            float topRoundness, float bottomRoundness, Path outPath) {
        outPath.reset();
        int width = right - left;
        float topRoundnessX = topRoundness;
        float bottomRoundnessX = bottomRoundness;
        topRoundnessX = Math.min(width / 2, topRoundnessX);
        bottomRoundnessX = Math.min(width / 2, bottomRoundnessX);
        if (topRoundness > 0.0f) {
            outPath.moveTo(left, top + topRoundness);
            outPath.quadTo(left, top, left + topRoundnessX, top);
            outPath.lineTo(right - topRoundnessX, top);
            outPath.quadTo(right, top, right, top + topRoundness);
        } else {
            outPath.moveTo(left, top);
            outPath.lineTo(right, top);
        }
        if (bottomRoundness > 0.0f) {
            outPath.lineTo(right, bottom - bottomRoundness);
            outPath.quadTo(right, bottom, right - bottomRoundnessX, bottom);
            outPath.lineTo(left + bottomRoundnessX, bottom);
            outPath.quadTo(left, bottom, left, bottom - bottomRoundness);
        } else {
            outPath.lineTo(right, bottom);
            outPath.lineTo(left, bottom);
        }
        outPath.close();
    }

    public ExpandableOutlineView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setOutlineProvider(mProvider);
        initDimens();
    }

    @Override
    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
        canvas.save();
        Path intersectPath = null;
        if (mClipRoundedToClipTopAmount) {
            int left = (int) (- mExtraWidthForClipping / 2.0f);
            int top = (int) (mClipTopAmount - mDistanceToTopRoundness);
            int right = getWidth() + (int) (mExtraWidthForClipping + left);
            int bottom = (int) Math.max(mMinimumHeightForClipping,
                    Math.max(getActualHeight() - mClipBottomAmount, top + mOutlineRadius));
            ExpandableOutlineView.getRoundedRectPath(left, top, right, bottom, mOutlineRadius,
                    0.0f,
                    mClipPath);
            intersectPath = mClipPath;
        }
        boolean clipped = false;
        if (childNeedsClipping(child)) {
            Path clipPath = getCustomClipPath(child);
            if (clipPath == null) {
                clipPath = getClipPath();
            }
            if (clipPath != null) {
                if (intersectPath != null) {
                    clipPath.op(intersectPath, Path.Op.INTERSECT);
                }
                canvas.clipPath(clipPath);
                clipped = true;
            }
        }
        if (!clipped && intersectPath != null) {
            canvas.clipPath(intersectPath);
        }
        boolean result = super.drawChild(canvas, child, drawingTime);
        canvas.restore();
        return result;
    }

    public void setExtraWidthForClipping(float extraWidthForClipping) {
        mExtraWidthForClipping = extraWidthForClipping;
    }

    public void setMinimumHeightForClipping(int minimumHeightForClipping) {
        mMinimumHeightForClipping = minimumHeightForClipping;
    }

    @Override
    public void setDistanceToTopRoundness(float distanceToTopRoundness) {
        super.setDistanceToTopRoundness(distanceToTopRoundness);
        if (distanceToTopRoundness != mDistanceToTopRoundness) {
            mClipRoundedToClipTopAmount = distanceToTopRoundness >= 0;
            mDistanceToTopRoundness = distanceToTopRoundness;
            invalidate();
        }
    }

    protected boolean childNeedsClipping(View child) {
        return false;
    }

    protected boolean isClippingNeeded() {
        return mAlwaysRoundBothCorners || mCustomOutline || getTranslation() != 0 ;

    }

    private void initDimens() {
        Resources res = getResources();
        mShouldTranslateContents =
                res.getBoolean(R.bool.config_translateNotificationContentsOnSwipe);
        mOutlineRadius = res.getDimension(R.dimen.notification_shadow_radius);
        mAlwaysRoundBothCorners = res.getBoolean(R.bool.config_clipNotificationsToOutline);
        if (!mAlwaysRoundBothCorners) {
            mOutlineRadius = res.getDimensionPixelSize(
                    Utils.getThemeAttr(mContext, android.R.attr.dialogCornerRadius));
        }
        setClipToOutline(mAlwaysRoundBothCorners);
    }

    public void setTopRoundness(float topRoundness, boolean animate) {
        if (mTopRoundness != topRoundness) {
            mTopRoundness = topRoundness;
            PropertyAnimator.setProperty(this, TOP_ROUNDNESS, topRoundness,
                    ROUNDNESS_PROPERTIES, animate);
        }
    }

    protected void applyRoundness() {
        invalidateOutline();
        invalidate();
    }

    public float getCurrentBackgroundRadiusTop() {
        return mCurrentTopRoundness * mOutlineRadius;
    }

    public float getCurrentTopRoundness() {
        return mCurrentTopRoundness;
    }

    public float getCurrentBottomRoundness() {
        return mCurrentBottomRoundness;
    }

    protected float getCurrentBackgroundRadiusBottom() {
        return mCurrentBottomRoundness * mOutlineRadius;
    }

    public void setBottomRoundness(float bottomRoundness, boolean animate) {
        if (mBottomRoundness != bottomRoundness) {
            mBottomRoundness = bottomRoundness;
            PropertyAnimator.setProperty(this, BOTTOM_ROUNDNESS, bottomRoundness,
                    ROUNDNESS_PROPERTIES, animate);
        }
    }

    protected void setBackgroundTop(int backgroundTop) {
        if (mBackgroundTop != backgroundTop) {
            mBackgroundTop = backgroundTop;
            invalidateOutline();
        }
    }

    private void setTopRoundnessInternal(float topRoundness) {
        mCurrentTopRoundness = topRoundness;
        applyRoundness();
    }

    private void setBottomRoundnessInternal(float bottomRoundness) {
        mCurrentBottomRoundness = bottomRoundness;
        applyRoundness();
    }

    public void onDensityOrFontScaleChanged() {
        initDimens();
        applyRoundness();
    }

    @Override
    public void setActualHeight(int actualHeight, boolean notifyListeners) {
        int previousHeight = getActualHeight();
        super.setActualHeight(actualHeight, notifyListeners);
        if (previousHeight != actualHeight) {
            applyRoundness();
        }
    }

    @Override
    public void setClipTopAmount(int clipTopAmount) {
        int previousAmount = getClipTopAmount();
        super.setClipTopAmount(clipTopAmount);
        if (previousAmount != clipTopAmount) {
            applyRoundness();
        }
    }

    @Override
    public void setClipBottomAmount(int clipBottomAmount) {
        int previousAmount = getClipBottomAmount();
        super.setClipBottomAmount(clipBottomAmount);
        if (previousAmount != clipBottomAmount) {
            applyRoundness();
        }
    }

    protected void setOutlineAlpha(float alpha) {
        if (alpha != mOutlineAlpha) {
            mOutlineAlpha = alpha;
            applyRoundness();
        }
    }

    @Override
    public float getOutlineAlpha() {
        return mOutlineAlpha;
    }

    protected void setOutlineRect(RectF rect) {
        if (rect != null) {
            setOutlineRect(rect.left, rect.top, rect.right, rect.bottom);
        } else {
            mCustomOutline = false;
            applyRoundness();
        }
    }

    @Override
    public int getOutlineTranslation() {
        return mCustomOutline ? mOutlineRect.left : (int) getTranslation();
    }

    public void updateOutline() {
        if (mCustomOutline) {
            return;
        }
        boolean hasOutline = needsOutline();
        setOutlineProvider(hasOutline ? mProvider : null);
    }

    /**
     * @return Whether the view currently needs an outline. This is usually {@code false} in case
     * it doesn't have a background.
     */
    protected boolean needsOutline() {
        if (isChildInGroup()) {
            return isGroupExpanded() && !isGroupExpansionChanging();
        } else if (isSummaryWithChildren()) {
            return !isGroupExpanded() || isGroupExpansionChanging();
        }
        return true;
    }

    public boolean isOutlineShowing() {
        ViewOutlineProvider op = getOutlineProvider();
        return op != null;
    }

    protected void setOutlineRect(float left, float top, float right, float bottom) {
        mCustomOutline = true;

        mOutlineRect.set((int) left, (int) top, (int) right, (int) bottom);

        // Outlines need to be at least 1 dp
        mOutlineRect.bottom = (int) Math.max(top, mOutlineRect.bottom);
        mOutlineRect.right = (int) Math.max(left, mOutlineRect.right);
        applyRoundness();
    }

    public Path getCustomClipPath(View child) {
        return null;
    }
}
