/*
 * 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.assist.ui;

import android.animation.ArgbEvaluator;
import android.annotation.ColorInt;
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.util.MathUtils;
import android.view.ContextThemeWrapper;
import android.view.View;

import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.NavigationBarController;
import com.android.systemui.statusbar.phone.NavigationBarFragment;
import com.android.systemui.statusbar.phone.NavigationBarTransitions;

import java.util.ArrayList;

/**
 * Shows lights at the bottom of the phone, marking the invocation progress.
 */
public class InvocationLightsView extends View
        implements NavigationBarTransitions.DarkIntensityListener {

    private static final String TAG = "InvocationLightsView";

    private static final int LIGHT_HEIGHT_DP = 3;
    // minimum light length as a fraction of the corner length
    private static final float MINIMUM_CORNER_RATIO = .6f;

    protected final ArrayList<EdgeLight> mAssistInvocationLights = new ArrayList<>();
    protected final PerimeterPathGuide mGuide;

    private final Paint mPaint = new Paint();
    // Path used to render lights. One instance is used to draw all lights and is cached to avoid
    // allocation on each frame.
    private final Path mPath = new Path();
    private final int mViewHeight;
    private final int mStrokeWidth;
    @ColorInt
    private final int mLightColor;
    @ColorInt
    private final int mDarkColor;

    // Allocate variable for screen location lookup to avoid memory alloc onDraw()
    private int[] mScreenLocation = new int[2];
    private boolean mRegistered = false;
    private boolean mUseNavBarColor = true;

    public InvocationLightsView(Context context) {
        this(context, null);
    }

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

    public InvocationLightsView(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public InvocationLightsView(Context context, AttributeSet attrs, int defStyleAttr,
            int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);

        mStrokeWidth = DisplayUtils.convertDpToPx(LIGHT_HEIGHT_DP, context);
        mPaint.setStrokeWidth(mStrokeWidth);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.MITER);
        mPaint.setAntiAlias(true);


        int displayWidth = DisplayUtils.getWidth(context);
        int displayHeight = DisplayUtils.getHeight(context);
        mGuide = new PerimeterPathGuide(context, createCornerPathRenderer(context),
                mStrokeWidth / 2, displayWidth, displayHeight);

        int cornerRadiusBottom = DisplayUtils.getCornerRadiusBottom(context);
        int cornerRadiusTop = DisplayUtils.getCornerRadiusTop(context);
        mViewHeight = Math.max(cornerRadiusBottom, cornerRadiusTop);

        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);

        for (int i = 0; i < 4; i++) {
            mAssistInvocationLights.add(new EdgeLight(Color.TRANSPARENT, 0, 0));
        }
    }

    /**
     * Updates positions of the invocation lights based on the progress (a float between 0 and 1).
     * The lights begin at the device corners and expand inward until they meet at the center.
     */
    public void onInvocationProgress(float progress) {
        if (progress == 0) {
            setVisibility(View.GONE);
        } else {
            attemptRegisterNavBarListener();

            float cornerLengthNormalized =
                    mGuide.getRegionWidth(PerimeterPathGuide.Region.BOTTOM_LEFT);
            float arcLengthNormalized = cornerLengthNormalized * MINIMUM_CORNER_RATIO;
            float arcOffsetNormalized = (cornerLengthNormalized - arcLengthNormalized) / 2f;

            float minLightLength = arcLengthNormalized / 2;
            float maxLightLength = mGuide.getRegionWidth(PerimeterPathGuide.Region.BOTTOM) / 4f;

            float lightLength = MathUtils.lerp(minLightLength, maxLightLength, progress);

            float leftStart = (-cornerLengthNormalized + arcOffsetNormalized) * (1 - progress);
            float rightStart = mGuide.getRegionWidth(PerimeterPathGuide.Region.BOTTOM)
                    + (cornerLengthNormalized - arcOffsetNormalized) * (1 - progress);

            setLight(0, leftStart, lightLength);
            setLight(1, leftStart + lightLength, lightLength);
            setLight(2, rightStart - (lightLength * 2), lightLength);
            setLight(3, rightStart - lightLength, lightLength);
            setVisibility(View.VISIBLE);
        }
        invalidate();
    }

    /**
     * Hides and resets the invocation lights.
     */
    public void hide() {
        setVisibility(GONE);
        for (EdgeLight light : mAssistInvocationLights) {
            light.setLength(0);
        }
        attemptUnregisterNavBarListener();
    }

    /**
     * Sets all invocation lights to a single color. If color is null, uses the navigation bar
     * color (updated when the nav bar color changes).
     */
    public void setColors(@Nullable @ColorInt Integer color) {
        if (color == null) {
            mUseNavBarColor = true;
            mPaint.setStrokeCap(Paint.Cap.BUTT);
            attemptRegisterNavBarListener();
        } else {
            setColors(color, color, color, color);
        }
    }

    /**
     * Sets the invocation light colors, from left to right.
     */
    public void setColors(@ColorInt int color1, @ColorInt int color2,
            @ColorInt int color3, @ColorInt int color4) {
        mUseNavBarColor = false;
        attemptUnregisterNavBarListener();
        mAssistInvocationLights.get(0).setColor(color1);
        mAssistInvocationLights.get(1).setColor(color2);
        mAssistInvocationLights.get(2).setColor(color3);
        mAssistInvocationLights.get(3).setColor(color4);
    }

    /**
     * Reacts to changes in the navigation bar color
     *
     * @param darkIntensity 0 is the lightest color, 1 is the darkest.
     */
    @Override // NavigationBarTransitions.DarkIntensityListener
    public void onDarkIntensity(float darkIntensity) {
        updateDarkness(darkIntensity);
    }


    @Override
    protected void onFinishInflate() {
        getLayoutParams().height = mViewHeight;
        requestLayout();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        int rotation = getContext().getDisplay().getRotation();
        mGuide.setRotation(rotation);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // If the view doesn't take up the whole screen, offset the canvas by its translation
        // distance such that PerimeterPathGuide's paths are drawn properly based upon the actual
        // screen edges.
        getLocationOnScreen(mScreenLocation);
        canvas.translate(-mScreenLocation[0], -mScreenLocation[1]);

        if (mUseNavBarColor) {
            for (EdgeLight light : mAssistInvocationLights) {
                renderLight(light, canvas);
            }
        } else {
            mPaint.setStrokeCap(Paint.Cap.ROUND);
            renderLight(mAssistInvocationLights.get(0), canvas);
            renderLight(mAssistInvocationLights.get(3), canvas);

            mPaint.setStrokeCap(Paint.Cap.BUTT);
            renderLight(mAssistInvocationLights.get(1), canvas);
            renderLight(mAssistInvocationLights.get(2), canvas);
        }
    }

    protected void setLight(int index, float offset, float length) {
        if (index < 0 || index >= 4) {
            Log.w(TAG, "invalid invocation light index: " + index);
        }
        mAssistInvocationLights.get(index).setOffset(offset);
        mAssistInvocationLights.get(index).setLength(length);
    }

    /**
     * Returns CornerPathRenderer to be used for rendering invocation lights.
     *
     * To render corners that aren't circular, override this method in a subclass.
     */
    protected CornerPathRenderer createCornerPathRenderer(Context context) {
        int displayWidth = DisplayUtils.getWidth(context);
        int displayHeight = DisplayUtils.getHeight(context);
        int cornerRadiusBottom = DisplayUtils.getCornerRadiusBottom(context);
        int cornerRadiusTop = DisplayUtils.getCornerRadiusTop(context);
        return new CircularCornerPathRenderer(
                cornerRadiusBottom, cornerRadiusTop, displayWidth, displayHeight);
    }
    /**
     * Receives an intensity from 0 (lightest) to 1 (darkest) and sets the handle color
     * appropriately. Intention is to match the home handle color.
     */
    protected void updateDarkness(float darkIntensity) {
        if (mUseNavBarColor) {
            @ColorInt int invocationColor = (int) ArgbEvaluator.getInstance().evaluate(
                    darkIntensity, mLightColor, mDarkColor);
            for (EdgeLight light : mAssistInvocationLights) {
                light.setColor(invocationColor);
            }
            invalidate();
        }
    }

    private void renderLight(EdgeLight light, Canvas canvas) {
        mGuide.strokeSegment(mPath, light.getOffset(), light.getOffset() + light.getLength());
        mPaint.setColor(light.getColor());
        canvas.drawPath(mPath, mPaint);
    }

    private void attemptRegisterNavBarListener() {
        if (!mRegistered) {
            NavigationBarController controller = Dependency.get(NavigationBarController.class);
            if (controller == null) {
                return;
            }

            NavigationBarFragment navBar = controller.getDefaultNavigationBarFragment();
            if (navBar == null) {
                return;
            }

            updateDarkness(navBar.getBarTransitions().addDarkIntensityListener(this));
            mRegistered = true;
        }
    }

    private void attemptUnregisterNavBarListener() {
        if (mRegistered) {
            NavigationBarController controller = Dependency.get(NavigationBarController.class);
            if (controller == null) {
                return;
            }

            NavigationBarFragment navBar = controller.getDefaultNavigationBarFragment();
            if (navBar == null) {
                return;
            }

            navBar.getBarTransitions().removeDarkIntensityListener(this);
            mRegistered = false;
        }
    }
}
