/*
 * 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 static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;

import android.content.Context;
import android.graphics.Matrix;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.util.Log;
import android.util.Pair;
import android.view.Surface;

import androidx.core.math.MathUtils;

/**
 * PerimeterPathGuide establishes a coordinate system for drawing paths along the perimeter of the
 * screen. All positions around the perimeter have a coordinate [0, 1). The origin is the bottom
 * left corner of the screen, to the right of the curved corner, if any. Coordinates increase
 * counter-clockwise around the screen.
 *
 * Non-square screens require PerimeterPathGuide to be notified when the rotation changes, such that
 * it can recompute the edge lengths for the coordinate system.
 */
public class PerimeterPathGuide {

    private static final String TAG = "PerimeterPathGuide";

    /**
     * For convenience, labels sections of the device perimeter.
     *
     * Must be listed in CCW order.
     */
    public enum Region {
        BOTTOM,
        BOTTOM_RIGHT,
        RIGHT,
        TOP_RIGHT,
        TOP,
        TOP_LEFT,
        LEFT,
        BOTTOM_LEFT
    }

    private final int mDeviceWidthPx;
    private final int mDeviceHeightPx;
    private final int mTopCornerRadiusPx;
    private final int mBottomCornerRadiusPx;

    private class RegionAttributes {
        public float absoluteLength;
        public float normalizedLength;
        public float endCoordinate;
        public Path path;
    }

    // Allocate a Path and PathMeasure for use by intermediate operations that would otherwise have
    // to allocate. reset() must be called before using this path, this ensures state from previous
    // operations is cleared.
    private final Path mScratchPath = new Path();
    private final CornerPathRenderer mCornerPathRenderer;
    private final PathMeasure mScratchPathMeasure = new PathMeasure(mScratchPath, false);
    private RegionAttributes[] mRegions;
    private final int mEdgeInset;
    private int mRotation = ROTATION_0;

    public PerimeterPathGuide(Context context, CornerPathRenderer cornerPathRenderer,
            int edgeInset, int screenWidth, int screenHeight) {
        mCornerPathRenderer = cornerPathRenderer;
        mDeviceWidthPx = screenWidth;
        mDeviceHeightPx = screenHeight;
        mTopCornerRadiusPx = DisplayUtils.getCornerRadiusTop(context);
        mBottomCornerRadiusPx = DisplayUtils.getCornerRadiusBottom(context);
        mEdgeInset = edgeInset;

        mRegions = new RegionAttributes[8];
        for (int i = 0; i < mRegions.length; i++) {
            mRegions[i] = new RegionAttributes();
        }
        computeRegions();
    }

    /**
     * Sets the rotation.
     *
     * @param rotation one of Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_180,
     *                  Surface.ROTATION_270
     */
    public void setRotation(int rotation) {
        if (rotation != mRotation) {
            switch (rotation) {
                case ROTATION_0:
                case ROTATION_90:
                case ROTATION_180:
                case ROTATION_270:
                    mRotation = rotation;
                    computeRegions();
                    break;
                default:
                    Log.e(TAG, "Invalid rotation provided: " + rotation);
            }
        }
    }

    /**
     * Sets path to the section of the perimeter between startCoord and endCoord (measured
     * counter-clockwise from the bottom left).
     */
    public void strokeSegment(Path path, float startCoord, float endCoord) {
        path.reset();

        startCoord = ((startCoord % 1) + 1) % 1;  // Wrap to the range [0, 1).
        endCoord = ((endCoord % 1) + 1) % 1;  // Wrap to the range [0, 1).
        boolean outOfOrder = startCoord > endCoord;

        if (outOfOrder) {
            strokeSegmentInternal(path, startCoord, 1f);
            startCoord = 0;
        }
        strokeSegmentInternal(path, startCoord, endCoord);
    }

    /**
     * Returns the device perimeter in pixels.
     */
    public float getPerimeterPx() {
        float total = 0;
        for (RegionAttributes region : mRegions) {
            total += region.absoluteLength;
        }
        return total;
    }

    /**
     * Returns the bottom corner radius in pixels.
     */
    public float getBottomCornerRadiusPx() {
        return mBottomCornerRadiusPx;
    }

    /**
     * Given a region and a progress value [0,1] indicating the counter-clockwise progress within
     * that region, compute the global [0,1) coordinate.
     */
    public float getCoord(Region region, float progress) {
        RegionAttributes regionAttributes = mRegions[region.ordinal()];
        progress = MathUtils.clamp(progress, 0, 1);
        return regionAttributes.endCoordinate - (1 - progress) * regionAttributes.normalizedLength;
    }

    /**
     * Returns the center of the provided region, relative to the entire perimeter.
     */
    public float getRegionCenter(Region region) {
        return getCoord(region, 0.5f);
    }

    /**
     * Returns the width of the provided region, in units relative to the entire perimeter.
     */
    public float getRegionWidth(Region region) {
        return mRegions[region.ordinal()].normalizedLength;
    }

    /**
     * Points are expressed in terms of their relative position on the perimeter of the display,
     * moving counter-clockwise. This method converts a point to clockwise, assisting use cases
     * such as animating to a point clockwise instead of counter-clockwise.
     *
     * @param point A point in the range from 0 to 1.
     * @return A point in the range of -1 to 0 that represents the same location as {@code point}.
     */
    public static float makeClockwise(float point) {
        return point - 1;
    }

    private int getPhysicalCornerRadius(CircularCornerPathRenderer.Corner corner) {
        if (corner == CircularCornerPathRenderer.Corner.BOTTOM_LEFT
                || corner == CircularCornerPathRenderer.Corner.BOTTOM_RIGHT) {
            return mBottomCornerRadiusPx;
        }
        return mTopCornerRadiusPx;
    }

    // Populate mRegions based upon the current rotation value.
    private void computeRegions() {
        int screenWidth = mDeviceWidthPx;
        int screenHeight = mDeviceHeightPx;

        int rotateMatrix = 0;

        switch (mRotation) {
            case ROTATION_90:
                rotateMatrix = -90;
                break;
            case ROTATION_180:
                rotateMatrix = -180;
                break;
            case Surface.ROTATION_270:
                rotateMatrix = -270;
                break;
        }

        Matrix matrix = new Matrix();
        matrix.postRotate(rotateMatrix, mDeviceWidthPx / 2, mDeviceHeightPx / 2);

        if (mRotation == ROTATION_90 || mRotation == Surface.ROTATION_270) {
            screenHeight = mDeviceWidthPx;
            screenWidth = mDeviceHeightPx;
            matrix.postTranslate((mDeviceHeightPx
                    - mDeviceWidthPx) / 2, (mDeviceWidthPx - mDeviceHeightPx) / 2);
        }

        CircularCornerPathRenderer.Corner screenBottomLeft = getRotatedCorner(
                CircularCornerPathRenderer.Corner.BOTTOM_LEFT);
        CircularCornerPathRenderer.Corner screenBottomRight = getRotatedCorner(
                CircularCornerPathRenderer.Corner.BOTTOM_RIGHT);
        CircularCornerPathRenderer.Corner screenTopLeft = getRotatedCorner(
                CircularCornerPathRenderer.Corner.TOP_LEFT);
        CircularCornerPathRenderer.Corner screenTopRight = getRotatedCorner(
                CircularCornerPathRenderer.Corner.TOP_RIGHT);

        mRegions[Region.BOTTOM_LEFT.ordinal()].path =
                mCornerPathRenderer.getInsetPath(screenBottomLeft, mEdgeInset);
        mRegions[Region.BOTTOM_RIGHT.ordinal()].path =
                mCornerPathRenderer.getInsetPath(screenBottomRight, mEdgeInset);
        mRegions[Region.TOP_RIGHT.ordinal()].path =
                mCornerPathRenderer.getInsetPath(screenTopRight, mEdgeInset);
        mRegions[Region.TOP_LEFT.ordinal()].path =
                mCornerPathRenderer.getInsetPath(screenTopLeft, mEdgeInset);

        mRegions[Region.BOTTOM_LEFT.ordinal()].path.transform(matrix);
        mRegions[Region.BOTTOM_RIGHT.ordinal()].path.transform(matrix);
        mRegions[Region.TOP_RIGHT.ordinal()].path.transform(matrix);
        mRegions[Region.TOP_LEFT.ordinal()].path.transform(matrix);


        Path bottomPath = new Path();
        bottomPath.moveTo(getPhysicalCornerRadius(screenBottomLeft), screenHeight - mEdgeInset);
        bottomPath.lineTo(screenWidth - getPhysicalCornerRadius(screenBottomRight),
                screenHeight - mEdgeInset);
        mRegions[Region.BOTTOM.ordinal()].path = bottomPath;

        Path topPath = new Path();
        topPath.moveTo(screenWidth - getPhysicalCornerRadius(screenTopRight), mEdgeInset);
        topPath.lineTo(getPhysicalCornerRadius(screenTopLeft), mEdgeInset);
        mRegions[Region.TOP.ordinal()].path = topPath;

        Path rightPath = new Path();
        rightPath.moveTo(screenWidth - mEdgeInset,
                screenHeight - getPhysicalCornerRadius(screenBottomRight));
        rightPath.lineTo(screenWidth - mEdgeInset, getPhysicalCornerRadius(screenTopRight));
        mRegions[Region.RIGHT.ordinal()].path = rightPath;

        Path leftPath = new Path();
        leftPath.moveTo(mEdgeInset,
                getPhysicalCornerRadius(screenTopLeft));
        leftPath.lineTo(mEdgeInset, screenHeight - getPhysicalCornerRadius(screenBottomLeft));
        mRegions[Region.LEFT.ordinal()].path = leftPath;

        float perimeterLength = 0;
        PathMeasure pathMeasure = new PathMeasure();
        for (int i = 0; i < mRegions.length; i++) {
            pathMeasure.setPath(mRegions[i].path, false);
            mRegions[i].absoluteLength = pathMeasure.getLength();
            perimeterLength += mRegions[i].absoluteLength;
        }

        float accum = 0;
        for (int i = 0; i < mRegions.length; i++) {
            mRegions[i].normalizedLength = mRegions[i].absoluteLength / perimeterLength;
            accum += mRegions[i].normalizedLength;
            mRegions[i].endCoordinate = accum;
        }
    }

    private CircularCornerPathRenderer.Corner getRotatedCorner(
            CircularCornerPathRenderer.Corner screenCorner) {
        int corner = screenCorner.ordinal();
        switch (mRotation) {
            case ROTATION_90:
                corner += 3;
                break;
            case ROTATION_180:
                corner += 2;
                break;
            case Surface.ROTATION_270:
                corner += 1;
                break;
        }
        return CircularCornerPathRenderer.Corner.values()[corner % 4];
    }

    private void strokeSegmentInternal(Path path, float startCoord, float endCoord) {
        Pair<Region, Float> startPoint = placePoint(startCoord);
        Pair<Region, Float> endPoint = placePoint(endCoord);

        if (startPoint.first.equals(endPoint.first)) {
            strokeRegion(path, startPoint.first, startPoint.second, endPoint.second);
        } else {
            strokeRegion(path, startPoint.first, startPoint.second, 1f);
            boolean hitStart = false;
            for (Region r : Region.values()) {
                if (r.equals(startPoint.first)) {
                    hitStart = true;
                    continue;
                }
                if (hitStart) {
                    if (!r.equals(endPoint.first)) {
                        strokeRegion(path, r, 0f, 1f);
                    } else {
                        strokeRegion(path, r, 0f, endPoint.second);
                        break;
                    }
                }
            }
        }
    }

    private void strokeRegion(Path path, Region r, float relativeStart, float relativeEnd) {
        if (relativeStart == relativeEnd) {
            return;
        }

        mScratchPathMeasure.setPath(mRegions[r.ordinal()].path, false);
        mScratchPathMeasure.getSegment(relativeStart * mScratchPathMeasure.getLength(),
                relativeEnd * mScratchPathMeasure.getLength(), path, true);
    }

    /**
     * Return the Region where the point is located, and its relative position within that region
     * (from 0 to 1).
     * Note that we move counterclockwise around the perimeter; for example, a relative position of
     * 0 in
     * the BOTTOM region is on the left side of the screen, but in the TOP region it’s on the
     * right.
     */
    private Pair<Region, Float> placePoint(float coord) {
        if (0 > coord || coord > 1) {
            coord = ((coord % 1) + 1)
                    % 1;  // Wrap to the range [0, 1). Inputs of exactly 1 are preserved.
        }

        Region r = getRegionForPoint(coord);
        if (r.equals(Region.BOTTOM)) {
            return Pair.create(r, coord / mRegions[r.ordinal()].normalizedLength);
        } else {
            float coordOffsetInRegion = coord - mRegions[r.ordinal() - 1].endCoordinate;
            float coordRelativeToRegion =
                    coordOffsetInRegion / mRegions[r.ordinal()].normalizedLength;
            return Pair.create(r, coordRelativeToRegion);
        }
    }

    private Region getRegionForPoint(float coord) {
        // If coord is outside of [0,1], wrap to [0,1).
        if (coord < 0 || coord > 1) {
            coord = ((coord % 1) + 1) % 1;
        }

        for (Region region : Region.values()) {
            if (coord <= mRegions[region.ordinal()].endCoordinate) {
                return region;
            }
        }

        // Should never happen.
        Log.e(TAG, "Fell out of getRegionForPoint");
        return Region.BOTTOM;
    }
}
