/*
 * Copyright (C) 2010 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.ui;

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.RectF;
import android.media.FaceDetector;
import android.os.Handler;
import android.os.Message;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.view.animation.DecelerateInterpolator;
import android.widget.Toast;

import com.android.gallery3d.R;
import com.android.gallery3d.anim.Animation;
import com.android.gallery3d.app.AbstractGalleryActivity;
import com.android.gallery3d.common.Utils;

import java.util.ArrayList;

import javax.microedition.khronos.opengles.GL11;

/**
 * The activity can crop specific region of interest from an image.
 */
public class CropView extends GLView {
    @SuppressWarnings("unused")
    private static final String TAG = "CropView";

    private static final int FACE_PIXEL_COUNT = 120000; // around 400x300

    private static final int COLOR_OUTLINE = 0xFF008AFF;
    private static final int COLOR_FACE_OUTLINE = 0xFF000000;

    private static final float OUTLINE_WIDTH = 3f;

    private static final int SIZE_UNKNOWN = -1;
    private static final int TOUCH_TOLERANCE = 30;

    private static final float MIN_SELECTION_LENGTH = 16f;
    public static final float UNSPECIFIED = -1f;

    private static final int MAX_FACE_COUNT = 3;
    private static final float FACE_EYE_RATIO = 2f;

    private static final int ANIMATION_DURATION = 1250;

    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;

    private static final float MAX_SELECTION_RATIO = 0.8f;
    private static final float MIN_SELECTION_RATIO = 0.4f;
    private static final float SELECTION_RATIO = 0.60f;
    private static final int ANIMATION_TRIGGER = 64;

    private static final int MSG_UPDATE_FACES = 1;

    private float mAspectRatio = UNSPECIFIED;
    private float mSpotlightRatioX = 0;
    private float mSpotlightRatioY = 0;

    private Handler mMainHandler;

    private FaceHighlightView mFaceDetectionView;
    private HighlightRectangle mHighlightRectangle;
    private TileImageView mImageView;
    private AnimationController mAnimation = new AnimationController();

    private int mImageWidth = SIZE_UNKNOWN;
    private int mImageHeight = SIZE_UNKNOWN;

    private AbstractGalleryActivity mActivity;

    private GLPaint mPaint = new GLPaint();
    private GLPaint mFacePaint = new GLPaint();

    private int mImageRotation;

    public CropView(AbstractGalleryActivity activity) {
        mActivity = activity;
        mImageView = new TileImageView(activity);
        mFaceDetectionView = new FaceHighlightView();
        mHighlightRectangle = new HighlightRectangle();

        addComponent(mImageView);
        addComponent(mFaceDetectionView);
        addComponent(mHighlightRectangle);

        mHighlightRectangle.setVisibility(GLView.INVISIBLE);

        mPaint.setColor(COLOR_OUTLINE);
        mPaint.setLineWidth(OUTLINE_WIDTH);

        mFacePaint.setColor(COLOR_FACE_OUTLINE);
        mFacePaint.setLineWidth(OUTLINE_WIDTH);

        mMainHandler = new SynchronizedHandler(activity.getGLRoot()) {
            @Override
            public void handleMessage(Message message) {
                Utils.assertTrue(message.what == MSG_UPDATE_FACES);
                ((DetectFaceTask) message.obj).updateFaces();
            }
        };
    }

    public void setAspectRatio(float ratio) {
        mAspectRatio = ratio;
    }

    public void setSpotlightRatio(float ratioX, float ratioY) {
        mSpotlightRatioX = ratioX;
        mSpotlightRatioY = ratioY;
    }

    @Override
    public void onLayout(boolean changed, int l, int t, int r, int b) {
        int width = r - l;
        int height = b - t;

        mFaceDetectionView.layout(0, 0, width, height);
        mHighlightRectangle.layout(0, 0, width, height);
        mImageView.layout(0, 0, width, height);
        if (mImageHeight != SIZE_UNKNOWN) {
            mAnimation.initialize();
            if (mHighlightRectangle.getVisibility() == GLView.VISIBLE) {
                mAnimation.parkNow(
                        mHighlightRectangle.mHighlightRect);
            }
        }
    }

    private boolean setImageViewPosition(int centerX, int centerY, float scale) {
        int inverseX = mImageWidth - centerX;
        int inverseY = mImageHeight - centerY;
        TileImageView t = mImageView;
        int rotation = mImageRotation;
        switch (rotation) {
            case 0: return t.setPosition(centerX, centerY, scale, 0);
            case 90: return t.setPosition(centerY, inverseX, scale, 90);
            case 180: return t.setPosition(inverseX, inverseY, scale, 180);
            case 270: return t.setPosition(inverseY, centerX, scale, 270);
            default: throw new IllegalArgumentException(String.valueOf(rotation));
        }
    }

    @Override
    public void render(GLCanvas canvas) {
        AnimationController a = mAnimation;
        if (a.calculate(AnimationTime.get())) invalidate();
        setImageViewPosition(a.getCenterX(), a.getCenterY(), a.getScale());
        super.render(canvas);
    }

    @Override
    public void renderBackground(GLCanvas canvas) {
        canvas.clearBuffer();
    }

    public RectF getCropRectangle() {
        if (mHighlightRectangle.getVisibility() == GLView.INVISIBLE) return null;
        RectF rect = mHighlightRectangle.mHighlightRect;
        RectF result = new RectF(rect.left * mImageWidth, rect.top * mImageHeight,
                rect.right * mImageWidth, rect.bottom * mImageHeight);
        return result;
    }

    public int getImageWidth() {
        return mImageWidth;
    }

    public int getImageHeight() {
        return mImageHeight;
    }

    private class FaceHighlightView extends GLView {
        private static final int INDEX_NONE = -1;
        private ArrayList<RectF> mFaces = new ArrayList<RectF>();
        private RectF mRect = new RectF();
        private int mPressedFaceIndex = INDEX_NONE;

        public void addFace(RectF faceRect) {
            mFaces.add(faceRect);
            invalidate();
        }

        private void renderFace(GLCanvas canvas, RectF face, boolean pressed) {
            GL11 gl = canvas.getGLInstance();
            if (pressed) {
                gl.glEnable(GL11.GL_STENCIL_TEST);
                gl.glClear(GL11.GL_STENCIL_BUFFER_BIT);
                gl.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE);
                gl.glStencilFunc(GL11.GL_ALWAYS, 1, 1);
            }

            RectF r = mAnimation.mapRect(face, mRect);
            canvas.fillRect(r.left, r.top, r.width(), r.height(), Color.TRANSPARENT);
            canvas.drawRect(r.left, r.top, r.width(), r.height(), mFacePaint);

            if (pressed) {
                gl.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
            }
        }

        @Override
        protected void renderBackground(GLCanvas canvas) {
            ArrayList<RectF> faces = mFaces;
            for (int i = 0, n = faces.size(); i < n; ++i) {
                renderFace(canvas, faces.get(i), i == mPressedFaceIndex);
            }

            GL11 gl = canvas.getGLInstance();
            if (mPressedFaceIndex != INDEX_NONE) {
                gl.glStencilFunc(GL11.GL_NOTEQUAL, 1, 1);
                canvas.fillRect(0, 0, getWidth(), getHeight(), 0x66000000);
                gl.glDisable(GL11.GL_STENCIL_TEST);
            }
        }

        private void setPressedFace(int index) {
            if (mPressedFaceIndex == index) return;
            mPressedFaceIndex = index;
            invalidate();
        }

        private int getFaceIndexByPosition(float x, float y) {
            ArrayList<RectF> faces = mFaces;
            for (int i = 0, n = faces.size(); i < n; ++i) {
                RectF r = mAnimation.mapRect(faces.get(i), mRect);
                if (r.contains(x, y)) return i;
            }
            return INDEX_NONE;
        }

        @Override
        protected boolean onTouch(MotionEvent event) {
            float x = event.getX();
            float y = event.getY();
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                case MotionEvent.ACTION_MOVE: {
                    setPressedFace(getFaceIndexByPosition(x, y));
                    break;
                }
                case MotionEvent.ACTION_CANCEL:
                case MotionEvent.ACTION_UP: {
                    int index = mPressedFaceIndex;
                    setPressedFace(INDEX_NONE);
                    if (index != INDEX_NONE) {
                        mHighlightRectangle.setRectangle(mFaces.get(index));
                        mHighlightRectangle.setVisibility(GLView.VISIBLE);
                        setVisibility(GLView.INVISIBLE);
                    }
                }
            }
            return true;
        }
    }

    private class AnimationController extends Animation {
        private int mCurrentX;
        private int mCurrentY;
        private float mCurrentScale;
        private int mStartX;
        private int mStartY;
        private float mStartScale;
        private int mTargetX;
        private int mTargetY;
        private float mTargetScale;

        public AnimationController() {
            setDuration(ANIMATION_DURATION);
            setInterpolator(new DecelerateInterpolator(4));
        }

        public void initialize() {
            mCurrentX = mImageWidth / 2;
            mCurrentY = mImageHeight / 2;
            mCurrentScale = Math.min(2, Math.min(
                    (float) getWidth() / mImageWidth,
                    (float) getHeight() / mImageHeight));
        }

        public void startParkingAnimation(RectF highlight) {
            RectF r = mAnimation.mapRect(highlight, new RectF());
            int width = getWidth();
            int height = getHeight();

            float wr = r.width() / width;
            float hr = r.height() / height;
            final int d = ANIMATION_TRIGGER;
            if (wr >= MIN_SELECTION_RATIO && wr < MAX_SELECTION_RATIO
                    && hr >= MIN_SELECTION_RATIO && hr < MAX_SELECTION_RATIO
                    && r.left >= d && r.right < width - d
                    && r.top >= d && r.bottom < height - d) return;

            mStartX = mCurrentX;
            mStartY = mCurrentY;
            mStartScale = mCurrentScale;
            calculateTarget(highlight);
            start();
        }

        public void parkNow(RectF highlight) {
            calculateTarget(highlight);
            forceStop();
            mStartX = mCurrentX = mTargetX;
            mStartY = mCurrentY = mTargetY;
            mStartScale = mCurrentScale = mTargetScale;
        }

        public void inverseMapPoint(PointF point) {
            float s = mCurrentScale;
            point.x = Utils.clamp(((point.x - getWidth() * 0.5f) / s
                    + mCurrentX) / mImageWidth, 0, 1);
            point.y = Utils.clamp(((point.y - getHeight() * 0.5f) / s
                    + mCurrentY) / mImageHeight, 0, 1);
        }

        public RectF mapRect(RectF input, RectF output) {
            float offsetX = getWidth() * 0.5f;
            float offsetY = getHeight() * 0.5f;
            int x = mCurrentX;
            int y = mCurrentY;
            float s = mCurrentScale;
            output.set(
                    offsetX + (input.left * mImageWidth - x) * s,
                    offsetY + (input.top * mImageHeight - y) * s,
                    offsetX + (input.right * mImageWidth - x) * s,
                    offsetY + (input.bottom * mImageHeight - y) * s);
            return output;
        }

        @Override
        protected void onCalculate(float progress) {
            mCurrentX = Math.round(mStartX + (mTargetX - mStartX) * progress);
            mCurrentY = Math.round(mStartY + (mTargetY - mStartY) * progress);
            mCurrentScale = mStartScale + (mTargetScale - mStartScale) * progress;

            if (mCurrentX == mTargetX && mCurrentY == mTargetY
                    && mCurrentScale == mTargetScale) forceStop();
        }

        public int getCenterX() {
            return mCurrentX;
        }

        public int getCenterY() {
            return mCurrentY;
        }

        public float getScale() {
            return mCurrentScale;
        }

        private void calculateTarget(RectF highlight) {
            float width = getWidth();
            float height = getHeight();

            if (mImageWidth != SIZE_UNKNOWN) {
                float minScale = Math.min(width / mImageWidth, height / mImageHeight);
                float scale = Utils.clamp(SELECTION_RATIO * Math.min(
                        width / (highlight.width() * mImageWidth),
                        height / (highlight.height() * mImageHeight)), minScale, 2f);
                int centerX = Math.round(
                        mImageWidth * (highlight.left + highlight.right) * 0.5f);
                int centerY = Math.round(
                        mImageHeight * (highlight.top + highlight.bottom) * 0.5f);

                if (Math.round(mImageWidth * scale) > width) {
                    int limitX = Math.round(width * 0.5f / scale);
                    centerX = Math.round(
                            (highlight.left + highlight.right) * mImageWidth / 2);
                    centerX = Utils.clamp(centerX, limitX, mImageWidth - limitX);
                } else {
                    centerX = mImageWidth / 2;
                }
                if (Math.round(mImageHeight * scale) > height) {
                    int limitY = Math.round(height * 0.5f / scale);
                    centerY = Math.round(
                            (highlight.top + highlight.bottom) * mImageHeight / 2);
                    centerY = Utils.clamp(centerY, limitY, mImageHeight - limitY);
                } else {
                    centerY = mImageHeight / 2;
                }
                mTargetX = centerX;
                mTargetY = centerY;
                mTargetScale = scale;
            }
        }

    }

    private class HighlightRectangle extends GLView {
        private RectF mHighlightRect = new RectF(0.25f, 0.25f, 0.75f, 0.75f);
        private RectF mTempRect = new RectF();
        private PointF mTempPoint = new PointF();

        private ResourceTexture mArrow;

        private int mMovingEdges = 0;
        private float mReferenceX;
        private float mReferenceY;

        public HighlightRectangle() {
            mArrow = new ResourceTexture(mActivity.getAndroidContext(),
                    R.drawable.camera_crop_holo);
        }

        public void setInitRectangle() {
            float targetRatio = mAspectRatio == UNSPECIFIED
                    ? 1f
                    : mAspectRatio * mImageHeight / mImageWidth;
            float w = SELECTION_RATIO / 2f;
            float h = SELECTION_RATIO / 2f;
            if (targetRatio > 1) {
                h = w / targetRatio;
            } else {
                w = h * targetRatio;
            }
            mHighlightRect.set(0.5f - w, 0.5f - h, 0.5f + w, 0.5f + h);
        }

        public void setRectangle(RectF faceRect) {
            mHighlightRect.set(faceRect);
            mAnimation.startParkingAnimation(faceRect);
            invalidate();
        }

        private void moveEdges(MotionEvent event) {
            float scale = mAnimation.getScale();
            float dx = (event.getX() - mReferenceX) / scale / mImageWidth;
            float dy = (event.getY() - mReferenceY) / scale / mImageHeight;
            mReferenceX = event.getX();
            mReferenceY = event.getY();
            RectF r = mHighlightRect;

            if ((mMovingEdges & MOVE_BLOCK) != 0) {
                dx = Utils.clamp(dx, -r.left,  1 - r.right);
                dy = Utils.clamp(dy, -r.top , 1 - r.bottom);
                r.top += dy;
                r.bottom += dy;
                r.left += dx;
                r.right += dx;
            } else {
                PointF point = mTempPoint;
                point.set(mReferenceX, mReferenceY);
                mAnimation.inverseMapPoint(point);
                float left = r.left + MIN_SELECTION_LENGTH / mImageWidth;
                float right = r.right - MIN_SELECTION_LENGTH / mImageWidth;
                float top = r.top + MIN_SELECTION_LENGTH / mImageHeight;
                float bottom = r.bottom - MIN_SELECTION_LENGTH / mImageHeight;
                if ((mMovingEdges & MOVE_RIGHT) != 0) {
                    r.right = Utils.clamp(point.x, left, 1f);
                }
                if ((mMovingEdges & MOVE_LEFT) != 0) {
                    r.left = Utils.clamp(point.x, 0, right);
                }
                if ((mMovingEdges & MOVE_TOP) != 0) {
                    r.top = Utils.clamp(point.y, 0, bottom);
                }
                if ((mMovingEdges & MOVE_BOTTOM) != 0) {
                    r.bottom = Utils.clamp(point.y, top, 1f);
                }
                if (mAspectRatio != UNSPECIFIED) {
                    float targetRatio = mAspectRatio * mImageHeight / mImageWidth;
                    if (r.width() / r.height() > targetRatio) {
                        float height = r.width() / targetRatio;
                        if ((mMovingEdges & MOVE_BOTTOM) != 0) {
                            r.bottom = Utils.clamp(r.top + height, top, 1f);
                        } else {
                            r.top = Utils.clamp(r.bottom - height, 0, bottom);
                        }
                    } else {
                        float width = r.height() * targetRatio;
                        if ((mMovingEdges & MOVE_LEFT) != 0) {
                            r.left = Utils.clamp(r.right - width, 0, right);
                        } else {
                            r.right = Utils.clamp(r.left + width, left, 1f);
                        }
                    }
                    if (r.width() / r.height() > targetRatio) {
                        float width = r.height() * targetRatio;
                        if ((mMovingEdges & MOVE_LEFT) != 0) {
                            r.left = Utils.clamp(r.right - width, 0, right);
                        } else {
                            r.right = Utils.clamp(r.left + width, left, 1f);
                        }
                    } else {
                        float height = r.width() / targetRatio;
                        if ((mMovingEdges & MOVE_BOTTOM) != 0) {
                            r.bottom = Utils.clamp(r.top + height, top, 1f);
                        } else {
                            r.top = Utils.clamp(r.bottom - height, 0, bottom);
                        }
                    }
                }
            }
            invalidate();
        }

        private void setMovingEdges(MotionEvent event) {
            RectF r = mAnimation.mapRect(mHighlightRect, mTempRect);
            float x = event.getX();
            float y = event.getY();

            if (x > r.left + TOUCH_TOLERANCE && x < r.right - TOUCH_TOLERANCE
                    && y > r.top + TOUCH_TOLERANCE && y < r.bottom - TOUCH_TOLERANCE) {
                mMovingEdges = MOVE_BLOCK;
                return;
            }

            boolean inVerticalRange = (r.top - TOUCH_TOLERANCE) <= y
                    && y <= (r.bottom + TOUCH_TOLERANCE);
            boolean inHorizontalRange = (r.left - TOUCH_TOLERANCE) <= x
                    && x <= (r.right + TOUCH_TOLERANCE);

            if (inVerticalRange) {
                boolean left = Math.abs(x - r.left) <= TOUCH_TOLERANCE;
                boolean right = Math.abs(x - r.right) <= TOUCH_TOLERANCE;
                if (left && right) {
                    left = Math.abs(x - r.left) < Math.abs(x - r.right);
                    right = !left;
                }
                if (left) mMovingEdges |= MOVE_LEFT;
                if (right) mMovingEdges |= MOVE_RIGHT;
                if (mAspectRatio != UNSPECIFIED && inHorizontalRange) {
                    mMovingEdges |= (y >
                            (r.top + r.bottom) / 2) ? MOVE_BOTTOM : MOVE_TOP;
                }
            }
            if (inHorizontalRange) {
                boolean top = Math.abs(y - r.top) <= TOUCH_TOLERANCE;
                boolean bottom = Math.abs(y - r.bottom) <= TOUCH_TOLERANCE;
                if (top && bottom) {
                    top = Math.abs(y - r.top) < Math.abs(y - r.bottom);
                    bottom = !top;
                }
                if (top) mMovingEdges |= MOVE_TOP;
                if (bottom) mMovingEdges |= MOVE_BOTTOM;
                if (mAspectRatio != UNSPECIFIED && inVerticalRange) {
                    mMovingEdges |= (x >
                            (r.left + r.right) / 2) ? MOVE_RIGHT : MOVE_LEFT;
                }
            }
        }

        @Override
        protected boolean onTouch(MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    mReferenceX = event.getX();
                    mReferenceY = event.getY();
                    setMovingEdges(event);
                    invalidate();
                    return true;
                }
                case MotionEvent.ACTION_MOVE:
                    moveEdges(event);
                    break;
                case MotionEvent.ACTION_CANCEL:
                case MotionEvent.ACTION_UP: {
                    mMovingEdges = 0;
                    mAnimation.startParkingAnimation(mHighlightRect);
                    invalidate();
                    return true;
                }
            }
            return true;
        }

        @Override
        protected void renderBackground(GLCanvas canvas) {
            RectF r = mAnimation.mapRect(mHighlightRect, mTempRect);
            drawHighlightRectangle(canvas, r);

            float centerY = (r.top + r.bottom) / 2;
            float centerX = (r.left + r.right) / 2;
            boolean notMoving = mMovingEdges == 0;
            if ((mMovingEdges & MOVE_RIGHT) != 0 || notMoving) {
                mArrow.draw(canvas,
                        Math.round(r.right - mArrow.getWidth() / 2),
                        Math.round(centerY - mArrow.getHeight() / 2));
            }
            if ((mMovingEdges & MOVE_LEFT) != 0 || notMoving) {
                mArrow.draw(canvas,
                        Math.round(r.left - mArrow.getWidth() / 2),
                        Math.round(centerY - mArrow.getHeight() / 2));
            }
            if ((mMovingEdges & MOVE_TOP) != 0 || notMoving) {
                mArrow.draw(canvas,
                        Math.round(centerX - mArrow.getWidth() / 2),
                        Math.round(r.top - mArrow.getHeight() / 2));
            }
            if ((mMovingEdges & MOVE_BOTTOM) != 0 || notMoving) {
                mArrow.draw(canvas,
                        Math.round(centerX - mArrow.getWidth() / 2),
                        Math.round(r.bottom - mArrow.getHeight() / 2));
            }
        }

        private void drawHighlightRectangle(GLCanvas canvas, RectF r) {
            GL11 gl = canvas.getGLInstance();
            gl.glLineWidth(3.0f);
            gl.glEnable(GL11.GL_LINE_SMOOTH);

            gl.glEnable(GL11.GL_STENCIL_TEST);
            gl.glClear(GL11.GL_STENCIL_BUFFER_BIT);
            gl.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE);
            gl.glStencilFunc(GL11.GL_ALWAYS, 1, 1);

            if (mSpotlightRatioX == 0 || mSpotlightRatioY == 0) {
                canvas.fillRect(r.left, r.top, r.width(), r.height(), Color.TRANSPARENT);
                canvas.drawRect(r.left, r.top, r.width(), r.height(), mPaint);
            } else {
                float sx = r.width() * mSpotlightRatioX;
                float sy = r.height() * mSpotlightRatioY;
                float cx = r.centerX();
                float cy = r.centerY();

                canvas.fillRect(cx - sx / 2, cy - sy / 2, sx, sy, Color.TRANSPARENT);
                canvas.drawRect(cx - sx / 2, cy - sy / 2, sx, sy, mPaint);
                canvas.drawRect(r.left, r.top, r.width(), r.height(), mPaint);

                gl.glStencilFunc(GL11.GL_NOTEQUAL, 1, 1);
                gl.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE);

                canvas.drawRect(cx - sy / 2, cy - sx / 2, sy, sx, mPaint);
                canvas.fillRect(cx - sy / 2, cy - sx / 2, sy, sx, Color.TRANSPARENT);
                canvas.fillRect(r.left, r.top, r.width(), r.height(), 0x80000000);
            }

            gl.glStencilFunc(GL11.GL_NOTEQUAL, 1, 1);
            gl.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);

            canvas.fillRect(0, 0, getWidth(), getHeight(), 0xA0000000);

            gl.glDisable(GL11.GL_STENCIL_TEST);
        }
    }

    private class DetectFaceTask extends Thread {
        private final FaceDetector.Face[] mFaces = new FaceDetector.Face[MAX_FACE_COUNT];
        private final Bitmap mFaceBitmap;
        private int mFaceCount;

        public DetectFaceTask(Bitmap bitmap) {
            mFaceBitmap = bitmap;
            setName("face-detect");
        }

        @Override
        public void run() {
            Bitmap bitmap = mFaceBitmap;
            FaceDetector detector = new FaceDetector(
                    bitmap.getWidth(), bitmap.getHeight(), MAX_FACE_COUNT);
            mFaceCount = detector.findFaces(bitmap, mFaces);
            mMainHandler.sendMessage(
                    mMainHandler.obtainMessage(MSG_UPDATE_FACES, this));
        }

        private RectF getFaceRect(FaceDetector.Face face) {
            PointF point = new PointF();
            face.getMidPoint(point);

            int width = mFaceBitmap.getWidth();
            int height = mFaceBitmap.getHeight();
            float rx = face.eyesDistance() * FACE_EYE_RATIO;
            float ry = rx;
            float aspect = mAspectRatio;
            if (aspect != UNSPECIFIED) {
                if (aspect > 1) {
                    rx = ry * aspect;
                } else {
                    ry = rx / aspect;
                }
            }

            RectF r = new RectF(
                    point.x - rx, point.y - ry, point.x + rx, point.y + ry);
            r.intersect(0, 0, width, height);

            if (aspect != UNSPECIFIED) {
                if (r.width() / r.height() > aspect) {
                    float w = r.height() * aspect;
                    r.left = (r.left + r.right - w) * 0.5f;
                    r.right = r.left + w;
                } else {
                    float h = r.width() / aspect;
                    r.top =  (r.top + r.bottom - h) * 0.5f;
                    r.bottom = r.top + h;
                }
            }

            r.left /= width;
            r.right /= width;
            r.top /= height;
            r.bottom /= height;
            return r;
        }

        public void updateFaces() {
            if (mFaceCount > 1) {
                for (int i = 0, n = mFaceCount; i < n; ++i) {
                    mFaceDetectionView.addFace(getFaceRect(mFaces[i]));
                }
                mFaceDetectionView.setVisibility(GLView.VISIBLE);
                Toast.makeText(mActivity.getAndroidContext(),
                        R.string.multiface_crop_help, Toast.LENGTH_SHORT).show();
            } else if (mFaceCount == 1) {
                mFaceDetectionView.setVisibility(GLView.INVISIBLE);
                mHighlightRectangle.setRectangle(getFaceRect(mFaces[0]));
                mHighlightRectangle.setVisibility(GLView.VISIBLE);
            } else /*mFaceCount == 0*/ {
                mHighlightRectangle.setInitRectangle();
                mHighlightRectangle.setVisibility(GLView.VISIBLE);
            }
        }
    }

    public void setDataModel(TileImageView.Model dataModel, int rotation) {
        if (((rotation / 90) & 0x01) != 0) {
            mImageWidth = dataModel.getImageHeight();
            mImageHeight = dataModel.getImageWidth();
        } else {
            mImageWidth = dataModel.getImageWidth();
            mImageHeight = dataModel.getImageHeight();
        }

        mImageRotation = rotation;

        mImageView.setModel(dataModel);
        mAnimation.initialize();
    }

    public void detectFaces(Bitmap bitmap) {
        int rotation = mImageRotation;
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        float scale = FloatMath.sqrt((float) FACE_PIXEL_COUNT / (width * height));

        // faceBitmap is a correctly rotated bitmap, as viewed by a user.
        Bitmap faceBitmap;
        if (((rotation / 90) & 1) == 0) {
            int w = (Math.round(width * scale) & ~1); // must be even
            int h = Math.round(height * scale);
            faceBitmap = Bitmap.createBitmap(w, h, Config.RGB_565);
            Canvas canvas = new Canvas(faceBitmap);
            canvas.rotate(rotation, w / 2, h / 2);
            canvas.scale((float) w / width, (float) h / height);
            canvas.drawBitmap(bitmap, 0, 0, new Paint(Paint.FILTER_BITMAP_FLAG));
        } else {
            int w = (Math.round(height * scale) & ~1); // must be even
            int h = Math.round(width * scale);
            faceBitmap = Bitmap.createBitmap(w, h, Config.RGB_565);
            Canvas canvas = new Canvas(faceBitmap);
            canvas.translate(w / 2, h / 2);
            canvas.rotate(rotation);
            canvas.translate(-h / 2, -w / 2);
            canvas.scale((float) w / height, (float) h / width);
            canvas.drawBitmap(bitmap, 0, 0, new Paint(Paint.FILTER_BITMAP_FLAG));
        }
        new DetectFaceTask(faceBitmap).start();
    }

    public void initializeHighlightRectangle() {
        mHighlightRectangle.setInitRectangle();
        mHighlightRectangle.setVisibility(GLView.VISIBLE);
    }

    public void resume() {
        mImageView.prepareTextures();
    }

    public void pause() {
        mImageView.freeTextures();
    }
}

