/*
 * Copyright (C) 2012 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.gallery3d.filtershow.crop;

import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;

import com.android.gallery3d.filtershow.imageshow.GeometryMath;

import java.util.Arrays;

/**
 * Maintains invariant that inner rectangle is constrained to be within the
 * outer, rotated rectangle.
 */
public class BoundedRect {
    private float rot;
    private RectF outer;
    private RectF inner;
    private float[] innerRotated;

    public BoundedRect(float rotation, Rect outerRect, Rect innerRect) {
        rot = rotation;
        outer = new RectF(outerRect);
        inner = new RectF(innerRect);
        innerRotated = CropMath.getCornersFromRect(inner);
        rotateInner();
        if (!isConstrained())
            reconstrain();
    }

    public BoundedRect(float rotation, RectF outerRect, RectF innerRect) {
        rot = rotation;
        outer = new RectF(outerRect);
        inner = new RectF(innerRect);
        innerRotated = CropMath.getCornersFromRect(inner);
        rotateInner();
        if (!isConstrained())
            reconstrain();
    }

    public void resetTo(float rotation, RectF outerRect, RectF innerRect) {
        rot = rotation;
        outer.set(outerRect);
        inner.set(innerRect);
        innerRotated = CropMath.getCornersFromRect(inner);
        rotateInner();
        if (!isConstrained())
            reconstrain();
    }

    /**
     * Sets inner, and re-constrains it to fit within the rotated bounding rect.
     */
    public void setInner(RectF newInner) {
        if (inner.equals(newInner))
            return;
        inner = newInner;
        innerRotated = CropMath.getCornersFromRect(inner);
        rotateInner();
        if (!isConstrained())
            reconstrain();
    }

    /**
     * Sets rotation, and re-constrains inner to fit within the rotated bounding rect.
     */
    public void setRotation(float rotation) {
        if (rotation == rot)
            return;
        rot = rotation;
        innerRotated = CropMath.getCornersFromRect(inner);
        rotateInner();
        if (!isConstrained())
            reconstrain();
    }

    public void setToInner(RectF r) {
        r.set(inner);
    }

    public void setToOuter(RectF r) {
        r.set(outer);
    }

    public RectF getInner() {
        return new RectF(inner);
    }

    public RectF getOuter() {
        return new RectF(outer);
    }

    /**
     * Tries to move the inner rectangle by (dx, dy).  If this would cause it to leave
     * the bounding rectangle, snaps the inner rectangle to the edge of the bounding
     * rectangle.
     */
    public void moveInner(float dx, float dy) {
        Matrix m0 = getInverseRotMatrix();

        RectF translatedInner = new RectF(inner);
        translatedInner.offset(dx, dy);

        float[] translatedInnerCorners = CropMath.getCornersFromRect(translatedInner);
        float[] outerCorners = CropMath.getCornersFromRect(outer);

        m0.mapPoints(translatedInnerCorners);
        float[] correction = {
                0, 0
        };

        // find correction vectors for corners that have moved out of bounds
        for (int i = 0; i < translatedInnerCorners.length; i += 2) {
            float correctedInnerX = translatedInnerCorners[i] + correction[0];
            float correctedInnerY = translatedInnerCorners[i + 1] + correction[1];
            if (!CropMath.inclusiveContains(outer, correctedInnerX, correctedInnerY)) {
                float[] badCorner = {
                        correctedInnerX, correctedInnerY
                };
                float[] nearestSide = CropMath.closestSide(badCorner, outerCorners);
                float[] correctionVec =
                        GeometryMath.shortestVectorFromPointToLine(badCorner, nearestSide);
                correction[0] += correctionVec[0];
                correction[1] += correctionVec[1];
            }
        }

        for (int i = 0; i < translatedInnerCorners.length; i += 2) {
            float correctedInnerX = translatedInnerCorners[i] + correction[0];
            float correctedInnerY = translatedInnerCorners[i + 1] + correction[1];
            if (!CropMath.inclusiveContains(outer, correctedInnerX, correctedInnerY)) {
                float[] correctionVec = {
                        correctedInnerX, correctedInnerY
                };
                CropMath.getEdgePoints(outer, correctionVec);
                correctionVec[0] -= correctedInnerX;
                correctionVec[1] -= correctedInnerY;
                correction[0] += correctionVec[0];
                correction[1] += correctionVec[1];
            }
        }

        // Set correction
        for (int i = 0; i < translatedInnerCorners.length; i += 2) {
            float correctedInnerX = translatedInnerCorners[i] + correction[0];
            float correctedInnerY = translatedInnerCorners[i + 1] + correction[1];
            // update translated corners with correction vectors
            translatedInnerCorners[i] = correctedInnerX;
            translatedInnerCorners[i + 1] = correctedInnerY;
        }

        innerRotated = translatedInnerCorners;
        // reconstrain to update inner
        reconstrain();
    }

    /**
     * Attempts to resize the inner rectangle.  If this would cause it to leave
     * the bounding rect, clips the inner rectangle to fit.
     */
    public void resizeInner(RectF newInner) {
        Matrix m = getRotMatrix();
        Matrix m0 = getInverseRotMatrix();

        float[] outerCorners = CropMath.getCornersFromRect(outer);
        m.mapPoints(outerCorners);
        float[] oldInnerCorners = CropMath.getCornersFromRect(inner);
        float[] newInnerCorners = CropMath.getCornersFromRect(newInner);
        RectF ret = new RectF(newInner);

        for (int i = 0; i < newInnerCorners.length; i += 2) {
            float[] c = {
                    newInnerCorners[i], newInnerCorners[i + 1]
            };
            float[] c0 = Arrays.copyOf(c, 2);
            m0.mapPoints(c0);
            if (!CropMath.inclusiveContains(outer, c0[0], c0[1])) {
                float[] outerSide = CropMath.closestSide(c, outerCorners);
                float[] pathOfCorner = {
                        newInnerCorners[i], newInnerCorners[i + 1],
                        oldInnerCorners[i], oldInnerCorners[i + 1]
                };
                float[] p = GeometryMath.lineIntersect(pathOfCorner, outerSide);
                if (p == null) {
                    // lines are parallel or not well defined, so don't resize
                    p = new float[2];
                    p[0] = oldInnerCorners[i];
                    p[1] = oldInnerCorners[i + 1];
                }
                // relies on corners being in same order as method
                // getCornersFromRect
                switch (i) {
                    case 0:
                    case 1:
                        ret.left = (p[0] > ret.left) ? p[0] : ret.left;
                        ret.top = (p[1] > ret.top) ? p[1] : ret.top;
                        break;
                    case 2:
                    case 3:
                        ret.right = (p[0] < ret.right) ? p[0] : ret.right;
                        ret.top = (p[1] > ret.top) ? p[1] : ret.top;
                        break;
                    case 4:
                    case 5:
                        ret.right = (p[0] < ret.right) ? p[0] : ret.right;
                        ret.bottom = (p[1] < ret.bottom) ? p[1] : ret.bottom;
                        break;
                    case 6:
                    case 7:
                        ret.left = (p[0] > ret.left) ? p[0] : ret.left;
                        ret.bottom = (p[1] < ret.bottom) ? p[1] : ret.bottom;
                        break;
                    default:
                        break;
                }
            }
        }
        float[] retCorners = CropMath.getCornersFromRect(ret);
        m0.mapPoints(retCorners);
        innerRotated = retCorners;
        // reconstrain to update inner
        reconstrain();
    }

    /**
     * Attempts to resize the inner rectangle.  If this would cause it to leave
     * the bounding rect, clips the inner rectangle to fit while maintaining
     * aspect ratio.
     */
    public void fixedAspectResizeInner(RectF newInner) {
        Matrix m = getRotMatrix();
        Matrix m0 = getInverseRotMatrix();

        float aspectW = inner.width();
        float aspectH = inner.height();
        float aspRatio = aspectW / aspectH;
        float[] corners = CropMath.getCornersFromRect(outer);

        m.mapPoints(corners);
        float[] oldInnerCorners = CropMath.getCornersFromRect(inner);
        float[] newInnerCorners = CropMath.getCornersFromRect(newInner);

        // find fixed corner
        int fixed = -1;
        if (inner.top == newInner.top) {
            if (inner.left == newInner.left)
                fixed = 0; // top left
            else if (inner.right == newInner.right)
                fixed = 2; // top right
        } else if (inner.bottom == newInner.bottom) {
            if (inner.right == newInner.right)
                fixed = 4; // bottom right
            else if (inner.left == newInner.left)
                fixed = 6; // bottom left
        }
        // no fixed corner, return without update
        if (fixed == -1)
            return;
        float widthSoFar = newInner.width();
        int moved = -1;
        for (int i = 0; i < newInnerCorners.length; i += 2) {
            float[] c = {
                    newInnerCorners[i], newInnerCorners[i + 1]
            };
            float[] c0 = Arrays.copyOf(c, 2);
            m0.mapPoints(c0);
            if (!CropMath.inclusiveContains(outer, c0[0], c0[1])) {
                moved = i;
                if (moved == fixed)
                    continue;
                float[] l2 = CropMath.closestSide(c, corners);
                float[] l1 = {
                        newInnerCorners[i], newInnerCorners[i + 1],
                        oldInnerCorners[i], oldInnerCorners[i + 1]
                };
                float[] p = GeometryMath.lineIntersect(l1, l2);
                if (p == null) {
                    // lines are parallel or not well defined, so set to old
                    // corner
                    p = new float[2];
                    p[0] = oldInnerCorners[i];
                    p[1] = oldInnerCorners[i + 1];
                }
                // relies on corners being in same order as method
                // getCornersFromRect
                float fixed_x = oldInnerCorners[fixed];
                float fixed_y = oldInnerCorners[fixed + 1];
                float newWidth = Math.abs(fixed_x - p[0]);
                float newHeight = Math.abs(fixed_y - p[1]);
                newWidth = Math.max(newWidth, aspRatio * newHeight);
                if (newWidth < widthSoFar)
                    widthSoFar = newWidth;
            }
        }

        float heightSoFar = widthSoFar / aspRatio;
        RectF ret = new RectF(inner);
        if (fixed == 0) {
            ret.right = ret.left + widthSoFar;
            ret.bottom = ret.top + heightSoFar;
        } else if (fixed == 2) {
            ret.left = ret.right - widthSoFar;
            ret.bottom = ret.top + heightSoFar;
        } else if (fixed == 4) {
            ret.left = ret.right - widthSoFar;
            ret.top = ret.bottom - heightSoFar;
        } else if (fixed == 6) {
            ret.right = ret.left + widthSoFar;
            ret.top = ret.bottom - heightSoFar;
        }
        float[] retCorners = CropMath.getCornersFromRect(ret);
        m0.mapPoints(retCorners);
        innerRotated = retCorners;
        // reconstrain to update inner
        reconstrain();
    }

    // internal methods

    private boolean isConstrained() {
        for (int i = 0; i < 8; i += 2) {
            if (!CropMath.inclusiveContains(outer, innerRotated[i], innerRotated[i + 1]))
                return false;
        }
        return true;
    }

    private void reconstrain() {
        // innerRotated has been changed to have incorrect values
        CropMath.getEdgePoints(outer, innerRotated);
        Matrix m = getRotMatrix();
        float[] unrotated = Arrays.copyOf(innerRotated, 8);
        m.mapPoints(unrotated);
        inner = CropMath.trapToRect(unrotated);
    }

    private void rotateInner() {
        Matrix m = getInverseRotMatrix();
        m.mapPoints(innerRotated);
    }

    private Matrix getRotMatrix() {
        Matrix m = new Matrix();
        m.setRotate(rot, outer.centerX(), outer.centerY());
        return m;
    }

    private Matrix getInverseRotMatrix() {
        Matrix m = new Matrix();
        m.setRotate(-rot, outer.centerX(), outer.centerY());
        return m;
    }
}
