/*
 * 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 = 0;
            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) {
        return new CircularCornerPathRenderer(context);
    }

    /**
     * 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;
        }
    }
}
