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

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;

import com.android.gallery3d.R;

public class ImageCrop extends ImageGeometry {
    private static final boolean LOGV = false;
    private static final int MOVE_LEFT = 1;
    private static final int MOVE_TOP = 2;
    private static final int MOVE_RIGHT = 4;
    private static final int MOVE_BOTTOM = 8;
    private static final int MOVE_BLOCK = 16;

    //Corners
    private static final int TOP_LEFT = MOVE_TOP | MOVE_LEFT;
    private static final int TOP_RIGHT = MOVE_TOP | MOVE_RIGHT;
    private static final int BOTTOM_RIGHT = MOVE_BOTTOM | MOVE_RIGHT;
    private static final int BOTTOM_LEFT = MOVE_BOTTOM | MOVE_LEFT;

    private static final float MIN_CROP_WIDTH_HEIGHT = 0.1f;
    private static int mTouchTolerance = 45;

    private boolean mFirstDraw = true;
    private float mAspectWidth = 1;
    private float mAspectHeight = 1;
    private boolean mFixAspectRatio = false;

    private float mLastRot = 0;
    private final Paint borderPaint;

    private int movingEdges;
    private final Drawable cropIndicator;
    private final int indicatorSize;
    private final int mBorderColor = Color.argb(128, 255, 255, 255);

    private static final String LOGTAG = "ImageCrop";

    private static final Paint gPaint = new Paint();

    public ImageCrop(Context context) {
        super(context);
        Resources resources = context.getResources();
        cropIndicator = resources.getDrawable(R.drawable.camera_crop);
        indicatorSize = (int) resources.getDimension(R.dimen.crop_indicator_size);
        borderPaint = new Paint();
        borderPaint.setStyle(Paint.Style.STROKE);
        borderPaint.setColor(mBorderColor);
        borderPaint.setStrokeWidth(2f);
    }

    public ImageCrop(Context context, AttributeSet attrs) {
        super(context, attrs);
        Resources resources = context.getResources();
        cropIndicator = resources.getDrawable(R.drawable.camera_crop);
        indicatorSize = (int) resources.getDimension(R.dimen.crop_indicator_size);
        borderPaint = new Paint();
        borderPaint.setStyle(Paint.Style.STROKE);
        borderPaint.setColor(mBorderColor);
        borderPaint.setStrokeWidth(2f);
    }

    @Override
    public String getName() {
        return getContext().getString(R.string.crop);
    }

    private void swapAspect(){
        float temp = mAspectWidth;
        mAspectWidth = mAspectHeight;
        mAspectHeight = temp;
    }

    public static void setTouchTolerance(int tolerance){
        mTouchTolerance = tolerance;
    }

    private boolean switchCropBounds(int moving_corner, RectF dst) {
        RectF crop = getCropBoundsDisplayed();
        float dx1 = 0;
        float dy1 = 0;
        float dx2 = 0;
        float dy2 = 0;
        if ((moving_corner & MOVE_RIGHT) != 0) {
            dx1 = mCurrentX - crop.right;
        } else if ((moving_corner & MOVE_LEFT) != 0) {
            dx1 = mCurrentX - crop.left;
        }
        if ((moving_corner & MOVE_BOTTOM) != 0) {
            dy1 = mCurrentY - crop.bottom;
        } else if ((moving_corner & MOVE_TOP) != 0) {
            dy1 = mCurrentY - crop.top;
        }
        RectF newCrop = null;
        //Fix opposite corner in place and move sides
        if (moving_corner == BOTTOM_RIGHT) {
            newCrop = new RectF(crop.left, crop.top, crop.left + crop.height(), crop.top
                    + crop.width());
        } else if (moving_corner == BOTTOM_LEFT) {
            newCrop = new RectF(crop.right - crop.height(), crop.top, crop.right, crop.top
                    + crop.width());
        } else if (moving_corner == TOP_LEFT) {
            newCrop = new RectF(crop.right - crop.height(), crop.bottom - crop.width(),
                    crop.right, crop.bottom);
        } else if (moving_corner == TOP_RIGHT) {
            newCrop = new RectF(crop.left, crop.bottom - crop.width(), crop.left
                    + crop.height(), crop.bottom);
        }
        if ((moving_corner & MOVE_RIGHT) != 0) {
            dx2 = mCurrentX - newCrop.right;
        } else if ((moving_corner & MOVE_LEFT) != 0) {
            dx2 = mCurrentX - newCrop.left;
        }
        if ((moving_corner & MOVE_BOTTOM) != 0) {
            dy2 = mCurrentY - newCrop.bottom;
        } else if ((moving_corner & MOVE_TOP) != 0) {
            dy2 = mCurrentY - newCrop.top;
        }
        if (Math.sqrt(dx1*dx1 + dy1*dy1) > Math.sqrt(dx2*dx2 + dy2*dy2)){
             Matrix m = getCropBoundDisplayMatrix();
             Matrix m0 = new Matrix();
             if (!m.invert(m0)){
                 if (LOGV)
                     Log.v(LOGTAG, "FAILED TO INVERT CROP MATRIX");
                 return false;
             }
             if (!m0.mapRect(newCrop)){
                 if (LOGV)
                     Log.v(LOGTAG, "FAILED TO MAP RECTANGLE TO RECTANGLE");
                 return false;
             }
             swapAspect();
             dst.set(newCrop);
             return true;
        }
        return false;
    }

    public void apply(float w, float h){
        mFixAspectRatio = true;
        mAspectWidth = w;
        mAspectHeight = h;
        setLocalCropBounds(getUntranslatedStraightenCropBounds(getLocalPhotoBounds(),
                getLocalStraighten()));
        cropSetup();
        saveAndSetPreset();
        invalidate();
    }

    public void applyOriginal() {
        mFixAspectRatio = true;
        RectF photobounds = getLocalPhotoBounds();
        float w = photobounds.width();
        float h = photobounds.height();
        float scale = Math.min(w, h);
        mAspectWidth = w / scale;
        mAspectHeight = h / scale;
        setLocalCropBounds(getUntranslatedStraightenCropBounds(photobounds,
                getLocalStraighten()));
        cropSetup();
        saveAndSetPreset();
        invalidate();
    }

    public void applyClear() {
        mFixAspectRatio = false;
        setLocalCropBounds(getUntranslatedStraightenCropBounds(getLocalPhotoBounds(),
                getLocalStraighten()));
        cropSetup();
        saveAndSetPreset();
        invalidate();
    }

    private float getScaledMinWidthHeight() {
        RectF disp = new RectF(0, 0, getWidth(), getHeight());
        float scaled = Math.min(disp.width(), disp.height()) * MIN_CROP_WIDTH_HEIGHT
                / computeScale(getWidth(), getHeight());
        return scaled;
    }

    protected Matrix getCropRotationMatrix(float rotation, RectF localImage) {
        Matrix m = getLocalGeoFlipMatrix(localImage.width(), localImage.height());
        m.postRotate(rotation, localImage.centerX(), localImage.centerY());
        if (!m.rectStaysRect()) {
            return null;
        }
        return m;
    }

    protected Matrix getCropBoundDisplayMatrix(){
        Matrix m = getCropRotationMatrix(getLocalRotation(), getLocalPhotoBounds());
        if (m == null) {
            if (LOGV)
                Log.v(LOGTAG, "FAILED TO MAP CROP BOUNDS TO RECTANGLE");
            m = new Matrix();
        }
        float zoom = computeScale(getWidth(), getHeight());
        m.postTranslate(mXOffset, mYOffset);
        m.postScale(zoom, zoom, mCenterX, mCenterY);
        return m;
    }

    protected RectF getCropBoundsDisplayed() {
        RectF bounds = getLocalCropBounds();
        RectF crop = new RectF(bounds);
        Matrix m = getCropRotationMatrix(getLocalRotation(), getLocalPhotoBounds());

        if (m == null) {
            if (LOGV)
                Log.v(LOGTAG, "FAILED TO MAP CROP BOUNDS TO RECTANGLE");
            m = new Matrix();
        } else {
            m.mapRect(crop);
        }
        m = new Matrix();
        float zoom = computeScale(getWidth(), getHeight());
        m.setScale(zoom, zoom, mCenterX, mCenterY);
        m.preTranslate(mXOffset, mYOffset);
        m.mapRect(crop);
        return crop;
    }

    private RectF getRotatedCropBounds() {
        RectF bounds = getLocalCropBounds();
        RectF crop = new RectF(bounds);
        Matrix m = getCropRotationMatrix(getLocalRotation(), getLocalPhotoBounds());

        if (m == null) {
            if (LOGV)
                Log.v(LOGTAG, "FAILED TO MAP CROP BOUNDS TO RECTANGLE");
            return null;
        } else {
            m.mapRect(crop);
        }
        return crop;
    }

    private RectF getUnrotatedCropBounds(RectF cropBounds) {
        Matrix m = getCropRotationMatrix(getLocalRotation(), getLocalPhotoBounds());

        if (m == null) {
            if (LOGV)
                Log.v(LOGTAG, "FAILED TO GET ROTATION MATRIX");
            return null;
        }
        Matrix m0 = new Matrix();
        if (!m.invert(m0)) {
            if (LOGV)
                Log.v(LOGTAG, "FAILED TO INVERT ROTATION MATRIX");
            return null;
        }
        RectF crop = new RectF(cropBounds);
        if (!m0.mapRect(crop)) {
            if (LOGV)
                Log.v(LOGTAG, "FAILED TO UNROTATE CROPPING BOUNDS");
            return null;
        }
        return crop;
    }

    private RectF getRotatedStraightenBounds() {
        RectF straightenBounds = getUntranslatedStraightenCropBounds(getLocalPhotoBounds(),
                getLocalStraighten());
        Matrix m = getCropRotationMatrix(getLocalRotation(), getLocalPhotoBounds());

        if (m == null) {
            if (LOGV)
                Log.v(LOGTAG, "FAILED TO MAP STRAIGHTEN BOUNDS TO RECTANGLE");
            return null;
        } else {
            m.mapRect(straightenBounds);
        }
        return straightenBounds;
    }

    /**
     * Sets cropped bounds; modifies the bounds if it's smaller than the allowed
     * dimensions.
     */
    public void setCropBounds(RectF bounds) {
        // Avoid cropping smaller than minimum width or height.
        RectF cbounds = new RectF(bounds);
        float minWidthHeight = getScaledMinWidthHeight();
        float aw = mAspectWidth;
        float ah = mAspectHeight;
        if (mFixAspectRatio) {
            minWidthHeight /= aw * ah;
            int r = (int) (getLocalRotation() / 90);
            if (r % 2 != 0) {
                float temp = aw;
                aw = ah;
                ah = temp;
            }
        }

        float newWidth = cbounds.width();
        float newHeight = cbounds.height();
        if (mFixAspectRatio) {
            if (newWidth < (minWidthHeight * aw) || newHeight < (minWidthHeight * ah)) {
                newWidth = minWidthHeight * aw;
                newHeight = minWidthHeight * ah;
            }
        } else {
            if (newWidth < minWidthHeight) {
                newWidth = minWidthHeight;
            }
            if (newHeight < minWidthHeight) {
                newHeight = minWidthHeight;
            }
        }
        RectF pbounds = getLocalPhotoBounds();
        if (pbounds.width() < minWidthHeight) {
            newWidth = pbounds.width();
        }
        if (pbounds.height() < minWidthHeight) {
            newHeight = pbounds.height();
        }

        cbounds.set(cbounds.left, cbounds.top, cbounds.left + newWidth, cbounds.top + newHeight);
        RectF straightenBounds = getUntranslatedStraightenCropBounds(getLocalPhotoBounds(),
                getLocalStraighten());
        cbounds.intersect(straightenBounds);

        if (mFixAspectRatio) {
            fixAspectRatio(cbounds, aw, ah);
        }
        setLocalCropBounds(cbounds);
        invalidate();
    }

    private void detectMovingEdges(float x, float y) {
        RectF cropped = getCropBoundsDisplayed();
        movingEdges = 0;

        // Check left or right.
        float left = Math.abs(x - cropped.left);
        float right = Math.abs(x - cropped.right);
        if ((left <= mTouchTolerance) && (left < right)) {
            movingEdges |= MOVE_LEFT;
        }
        else if (right <= mTouchTolerance) {
            movingEdges |= MOVE_RIGHT;
        }

        // Check top or bottom.
        float top = Math.abs(y - cropped.top);
        float bottom = Math.abs(y - cropped.bottom);
        if ((top <= mTouchTolerance) & (top < bottom)) {
            movingEdges |= MOVE_TOP;
        }
        else if (bottom <= mTouchTolerance) {
            movingEdges |= MOVE_BOTTOM;
        }
        // Check inside block.
        if (cropped.contains(x, y) && (movingEdges == 0)) {
            movingEdges = MOVE_BLOCK;
        }
        if (mFixAspectRatio && (movingEdges != MOVE_BLOCK)) {
            movingEdges = fixEdgeToCorner(movingEdges);
        }
        invalidate();
    }

    private int fixEdgeToCorner(int moving_edges){
        if (moving_edges == MOVE_LEFT) {
            moving_edges |= MOVE_TOP;
        }
        if (moving_edges == MOVE_TOP) {
            moving_edges |= MOVE_LEFT;
        }
        if (moving_edges == MOVE_RIGHT) {
            moving_edges |= MOVE_BOTTOM;
        }
        if (moving_edges == MOVE_BOTTOM) {
            moving_edges |= MOVE_RIGHT;
        }
        return moving_edges;
    }

    private RectF fixedCornerResize(RectF r, int moving_corner, float dx, float dy){
        RectF newCrop = null;
        //Fix opposite corner in place and move sides
        if (moving_corner == BOTTOM_RIGHT) {
            newCrop = new RectF(r.left, r.top, r.left + r.width() + dx, r.top + r.height()
                    + dy);
        } else if (moving_corner == BOTTOM_LEFT) {
            newCrop = new RectF(r.right - r.width() + dx, r.top, r.right, r.top + r.height()
                    + dy);
        } else if (moving_corner == TOP_LEFT) {
            newCrop = new RectF(r.right - r.width() + dx, r.bottom - r.height() + dy,
                    r.right, r.bottom);
        } else if (moving_corner == TOP_RIGHT) {
            newCrop = new RectF(r.left, r.bottom - r.height() + dy, r.left
                    + r.width() + dx, r.bottom);
        }
        return newCrop;
    }

    private void moveEdges(float dX, float dY) {
        RectF cropped = getRotatedCropBounds();
        float minWidthHeight = getScaledMinWidthHeight();
        float scale = computeScale(getWidth(), getHeight());
        float deltaX = dX / scale;
        float deltaY = dY / scale;
        int select = movingEdges;
        if (mFixAspectRatio && (select != MOVE_BLOCK)) {

            // TODO: add in orientation change for fixed aspect
            /*if (select == TOP_LEFT || select == TOP_RIGHT ||
                    select == BOTTOM_LEFT || select == BOTTOM_RIGHT){
                RectF blank = new RectF();
                if(switchCropBounds(select, blank)){
                    setCropBounds(blank);
                    return;
                }
            }*/
            if (select == MOVE_LEFT) {
                select |= MOVE_TOP;
            }
            if (select == MOVE_TOP) {
                select |= MOVE_LEFT;
            }
            if (select == MOVE_RIGHT) {
                select |= MOVE_BOTTOM;
            }
            if (select == MOVE_BOTTOM) {
                select |= MOVE_RIGHT;
            }
        }

        if (select == MOVE_BLOCK) {
            RectF straight = getRotatedStraightenBounds();
            // Move the whole cropped bounds within the photo display bounds.
            deltaX = (deltaX > 0) ? Math.min(straight.right - cropped.right, deltaX)
                    : Math.max(straight.left - cropped.left, deltaX);
            deltaY = (deltaY > 0) ? Math.min(straight.bottom - cropped.bottom, deltaY)
                    : Math.max(straight.top - cropped.top, deltaY);
            cropped.offset(deltaX, deltaY);
        } else {
            float dx = 0;
            float dy = 0;

            if ((select & MOVE_LEFT) != 0) {
                dx = Math.min(cropped.left + deltaX, cropped.right - minWidthHeight) - cropped.left;
            }
            if ((select & MOVE_TOP) != 0) {
                dy = Math.min(cropped.top + deltaY, cropped.bottom - minWidthHeight) - cropped.top;
            }
            if ((select & MOVE_RIGHT) != 0) {
                dx = Math.max(cropped.right + deltaX, cropped.left + minWidthHeight)
                        - cropped.right;
            }
            if ((select & MOVE_BOTTOM) != 0) {
                dy = Math.max(cropped.bottom + deltaY, cropped.top + minWidthHeight)
                        - cropped.bottom;
            }

            if (mFixAspectRatio) {
                RectF crop = getCropBoundsDisplayed();
                float [] l1 = {crop.left, crop.bottom};
                float [] l2 = {crop.right, crop.top};
                if(movingEdges == TOP_LEFT || movingEdges == BOTTOM_RIGHT){
                    l1[1] = crop.top;
                    l2[1] = crop.bottom;
                }
                float[] b = { l1[0] - l2[0], l1[1] - l2[1] };
                float[] disp = {dx, dy};
                float[] bUnit = GeometryMath.normalize(b);
                float sp = GeometryMath.scalarProjection(disp, bUnit);
                dx = sp * bUnit[0];
                dy = sp * bUnit[1];
                RectF newCrop = fixedCornerResize(crop, select, dx * scale, dy * scale);
                Matrix m = getCropBoundDisplayMatrix();
                Matrix m0 = new Matrix();
                if (!m.invert(m0)){
                    if (LOGV)
                        Log.v(LOGTAG, "FAILED TO INVERT CROP MATRIX");
                    return;
                }
                if (!m0.mapRect(newCrop)){
                    if (LOGV)
                        Log.v(LOGTAG, "FAILED TO MAP RECTANGLE TO RECTANGLE");
                    return;
                }
                setCropBounds(newCrop);
                return;
            } else {
                if ((select & MOVE_LEFT) != 0) {
                    cropped.left += dx;
                }
                if ((select & MOVE_TOP) != 0) {
                    cropped.top += dy;
                }
                if ((select & MOVE_RIGHT) != 0) {
                    cropped.right += dx;
                }
                if ((select & MOVE_BOTTOM) != 0) {
                    cropped.bottom += dy;
                }
            }
        }
        movingEdges = select;
        Matrix m = getCropRotationMatrix(getLocalRotation(), getLocalPhotoBounds());
        Matrix m0 = new Matrix();
        if (!m.invert(m0)) {
            if (LOGV)
                Log.v(LOGTAG, "FAILED TO INVERT ROTATION MATRIX");
        }
        if (!m0.mapRect(cropped)) {
            if (LOGV)
                Log.v(LOGTAG, "FAILED TO UNROTATE CROPPING BOUNDS");
        }
        setCropBounds(cropped);
    }

    private void drawIndicator(Canvas canvas, Drawable indicator, float centerX, float centerY) {
        int left = (int) centerX - indicatorSize / 2;
        int top = (int) centerY - indicatorSize / 2;
        indicator.setBounds(left, top, left + indicatorSize, top + indicatorSize);
        indicator.draw(canvas);
    }

    @Override
    protected void setActionDown(float x, float y) {
        super.setActionDown(x, y);
        detectMovingEdges(x, y);
    }

    @Override
    protected void setActionUp() {
        super.setActionUp();
        movingEdges = 0;
    }

    @Override
    protected void setActionMove(float x, float y) {
        if (movingEdges != 0){
            moveEdges(x - mCurrentX, y - mCurrentY);
        }
        super.setActionMove(x, y);
    }

    private void cropSetup() {
        if (mFixAspectRatio) {
            RectF cb = getRotatedCropBounds();
            fixAspectRatio(cb, mAspectWidth, mAspectHeight);
            RectF cb0 = getUnrotatedCropBounds(cb);
            setCropBounds(cb0);
        } else {
            setCropBounds(getLocalCropBounds());
        }
    }

    @Override
    public void imageLoaded() {
        super.imageLoaded();
        syncLocalToMasterGeometry();
        applyOriginal();
        invalidate();
    }

    @Override
    protected void gainedVisibility() {
        float rot = getLocalRotation();
        // if has changed orientation via rotate
        if( ((int) ((rot - mLastRot) / 90)) % 2 != 0 ){
            swapAspect();
        }
        cropSetup();
        mFirstDraw = true;
    }

    @Override
    public void resetParameter() {
        super.resetParameter();
        cropSetup();
    }

    @Override
    protected void lostVisibility() {
        mLastRot = getLocalRotation();
    }

    private void drawRuleOfThird(Canvas canvas, RectF bounds, Paint p) {
        float stepX = bounds.width() / 3.0f;
        float stepY = bounds.height() / 3.0f;
        float x = bounds.left + stepX;
        float y = bounds.top + stepY;
        for (int i = 0; i < 2; i++) {
            canvas.drawLine(x, bounds.top, x, bounds.bottom, p);
            x += stepX;
        }
        for (int j = 0; j < 2; j++) {
            canvas.drawLine(bounds.left, y, bounds.right, y, p);
            y += stepY;
        }
    }

    @Override
    protected void drawShape(Canvas canvas, Bitmap image) {
        // TODO: move style to xml
        gPaint.setAntiAlias(true);
        gPaint.setFilterBitmap(true);
        gPaint.setDither(true);
        gPaint.setARGB(255, 255, 255, 255);

        if (mFirstDraw) {
            cropSetup();
            mFirstDraw = false;
        }
        float rotation = getLocalRotation();

        RectF crop = drawTransformed(canvas, image, gPaint);
        gPaint.setColor(mBorderColor);
        gPaint.setStrokeWidth(3);
        gPaint.setStyle(Paint.Style.STROKE);
        drawRuleOfThird(canvas, crop, gPaint);

        gPaint.setColor(mBorderColor);
        gPaint.setStrokeWidth(3);
        gPaint.setStyle(Paint.Style.STROKE);
        drawStraighten(canvas, gPaint);

        int decoded_moving = decoder(movingEdges, rotation);
        canvas.save();
        canvas.rotate(rotation, mCenterX, mCenterY);
        RectF scaledCrop = unrotatedCropBounds();
        boolean notMoving = decoded_moving == 0;
        if (((decoded_moving & MOVE_TOP) != 0) || notMoving) {
            drawIndicator(canvas, cropIndicator, scaledCrop.centerX(), scaledCrop.top);
        }
        if (((decoded_moving & MOVE_BOTTOM) != 0) || notMoving) {
            drawIndicator(canvas, cropIndicator, scaledCrop.centerX(), scaledCrop.bottom);
        }
        if (((decoded_moving & MOVE_LEFT) != 0) || notMoving) {
            drawIndicator(canvas, cropIndicator, scaledCrop.left, scaledCrop.centerY());
        }
        if (((decoded_moving & MOVE_RIGHT) != 0) || notMoving) {
            drawIndicator(canvas, cropIndicator, scaledCrop.right, scaledCrop.centerY());
        }
        canvas.restore();
    }

    private int bitCycleLeft(int x, int times, int d) {
        int mask = (1 << d) - 1;
        int mout = x & mask;
        times %= d;
        int hi = mout >> (d - times);
        int low = (mout << times) & mask;
        int ret = x & ~mask;
        ret |= low;
        ret |= hi;
        return ret;
    }

    protected int decoder(int movingEdges, float rotation) {
        int rot = constrainedRotation(rotation);
        switch (rot) {
            case 90:
                return bitCycleLeft(movingEdges, 3, 4);
            case 180:
                return bitCycleLeft(movingEdges, 2, 4);
            case 270:
                return bitCycleLeft(movingEdges, 1, 4);
            default:
                return movingEdges;
        }
    }
}
