/*
 * Copyright (C) 2019 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;

import android.animation.ArgbEvaluator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.ContextThemeWrapper;
import android.view.View;

import com.android.settingslib.Utils;

/**
 * CornerHandleView draws an inset arc intended to be displayed within the screen decoration
 * corners.
 */
public class CornerHandleView extends View {
    private static final float STROKE_DP_LARGE = 2f;
    private static final float STROKE_DP_SMALL = 1.95f;
    // Radius to use if none is available.
    private static final int FALLBACK_RADIUS_DP = 15;
    private static final float MARGIN_DP = 8;
    private static final int MAX_ARC_DEGREES = 90;
    // Arc length along the phone's perimeter used to measure the desired angle.
    private static final float ARC_LENGTH_DP = 31f;

    private Paint mPaint;
    private int mLightColor;
    private int mDarkColor;
    private Path mPath;
    private boolean mRequiresInvalidate;

    public CornerHandleView(Context context, AttributeSet attrs) {
        super(context, attrs);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(getStrokePx());

        final int dualToneDarkTheme = Utils.getThemeAttr(mContext, R.attr.darkIconTheme);
        final int dualToneLightTheme = Utils.getThemeAttr(mContext, R.attr.lightIconTheme);
        Context lightContext = new ContextThemeWrapper(mContext, dualToneLightTheme);
        Context darkContext = new ContextThemeWrapper(mContext, dualToneDarkTheme);
        mLightColor = Utils.getColorAttrDefaultColor(lightContext, R.attr.singleToneColor);
        mDarkColor = Utils.getColorAttrDefaultColor(darkContext, R.attr.singleToneColor);

        updatePath();
    }

    @Override
    public void setAlpha(float alpha) {
        super.setAlpha(alpha);
        if (alpha > 0f && mRequiresInvalidate) {
            mRequiresInvalidate = false;
            invalidate();
        }
    }

    private void updatePath() {
        mPath = new Path();

        float marginPx = getMarginPx();
        float radiusPx = getInnerRadiusPx();
        float halfStrokePx = getStrokePx() / 2f;
        float angle = getAngle();
        float startAngle = 180 + ((90 - angle) / 2);
        RectF circle = new RectF(marginPx + halfStrokePx,
                marginPx + halfStrokePx,
                marginPx + 2 * radiusPx - halfStrokePx,
                marginPx + 2 * radiusPx - halfStrokePx);

        if (angle >= 90f) {
            float innerCircumferenceDp = convertPixelToDp(radiusPx * 2 * (float) Math.PI,
                    mContext);
            float arcDp = innerCircumferenceDp * getAngle() / 360f;
            // Add additional "arms" to the two ends of the arc. The length computation is
            // hand-tuned.
            float lineLengthPx = convertDpToPixel((ARC_LENGTH_DP - arcDp - MARGIN_DP) / 2,
                    mContext);

            mPath.moveTo(marginPx + halfStrokePx, marginPx + radiusPx + lineLengthPx);
            mPath.lineTo(marginPx + halfStrokePx, marginPx + radiusPx);
            mPath.arcTo(circle, startAngle, angle);
            mPath.moveTo(marginPx + radiusPx, marginPx + halfStrokePx);
            mPath.lineTo(marginPx + radiusPx + lineLengthPx, marginPx + halfStrokePx);
        } else {
            mPath.arcTo(circle, startAngle, angle);
        }
    }

    /**
     * Receives an intensity from 0 (lightest) to 1 (darkest) and sets the handle color
     * appropriately. Intention is to match the home handle color.
     */
    public void updateDarkness(float darkIntensity) {
        // Handle color is same as home handle color.
        int color = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
                mLightColor, mDarkColor);
        if (mPaint.getColor() != color) {
            mPaint.setColor(color);
            if (getVisibility() == VISIBLE && getAlpha() > 0) {
                invalidate();
            } else {
                // If we are currently invisible, then invalidate when we are next made visible
                mRequiresInvalidate = true;
            }
        }
    }

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawPath(mPath, mPaint);
    }

    private static float convertDpToPixel(float dp, Context context) {
        return dp * ((float) context.getResources().getDisplayMetrics().densityDpi
                / DisplayMetrics.DENSITY_DEFAULT);
    }

    private static float convertPixelToDp(float px, Context context) {
        return px * DisplayMetrics.DENSITY_DEFAULT
                / ((float) context.getResources().getDisplayMetrics().densityDpi);
    }

    private float getAngle() {
        // Measure a length of ARC_LENGTH_DP along the *screen's* perimeter, get the angle and cap
        // it at 90.
        float circumferenceDp = convertPixelToDp((
                getOuterRadiusPx()) * 2 * (float) Math.PI, mContext);
        float angleDeg = (ARC_LENGTH_DP / circumferenceDp) * 360;
        if (angleDeg > MAX_ARC_DEGREES) {
            angleDeg = MAX_ARC_DEGREES;
        }
        return angleDeg;
    }

    private float getMarginPx() {
        return convertDpToPixel(MARGIN_DP, mContext);
    }

    private float getInnerRadiusPx() {
        return getOuterRadiusPx() - getMarginPx();
    }

    private float getOuterRadiusPx() {
        // Attempt to get the bottom corner radius, otherwise fall back on the generic or top
        // values. If none are available, use the FALLBACK_RADIUS_DP.
        int radius = getResources().getDimensionPixelSize(
                com.android.systemui.R.dimen.config_rounded_mask_size_bottom);
        if (radius == 0) {
            radius = getResources().getDimensionPixelSize(
                    com.android.systemui.R.dimen.config_rounded_mask_size);
        }
        if (radius == 0) {
            radius = getResources().getDimensionPixelSize(
                    com.android.systemui.R.dimen.config_rounded_mask_size_top);
        }
        if (radius == 0) {
            radius = (int) convertDpToPixel(FALLBACK_RADIUS_DP, mContext);
        }
        return radius;
    }

    private float getStrokePx() {
        // Use a slightly smaller stroke if we need to cover the full corner angle.
        return convertDpToPixel((getAngle() < 90) ? STROKE_DP_LARGE : STROKE_DP_SMALL,
                getContext());
    }
}
