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

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Message;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.LinearInterpolator;
import android.view.animation.Transformation;

import com.android.camera.drawable.TextDrawable;
import com.android.gallery3d.R;

import java.util.ArrayList;
import java.util.List;

public class PieRenderer extends OverlayRenderer
        implements FocusIndicator {

    private static final String TAG = "CAM Pie";

    // Sometimes continuous autofocus starts and stops several times quickly.
    // These states are used to make sure the animation is run for at least some
    // time.
    private volatile int mState;
    private ScaleAnimation mAnimation = new ScaleAnimation();
    private static final int STATE_IDLE = 0;
    private static final int STATE_FOCUSING = 1;
    private static final int STATE_FINISHING = 2;
    private static final int STATE_PIE = 8;

    private static final float MATH_PI_2 = (float)(Math.PI / 2);

    private Runnable mDisappear = new Disappear();
    private Animation.AnimationListener mEndAction = new EndAction();
    private static final int SCALING_UP_TIME = 600;
    private static final int SCALING_DOWN_TIME = 100;
    private static final int DISAPPEAR_TIMEOUT = 200;
    private static final int DIAL_HORIZONTAL = 157;
    // fade out timings
    private static final int PIE_FADE_OUT_DURATION = 600;

    private static final long PIE_FADE_IN_DURATION = 200;
    private static final long PIE_XFADE_DURATION = 200;
    private static final long PIE_SELECT_FADE_DURATION = 300;
    private static final long PIE_OPEN_SUB_DELAY = 400;
    private static final long PIE_SLICE_DURATION = 80;

    private static final int MSG_OPEN = 0;
    private static final int MSG_CLOSE = 1;
    private static final int MSG_OPENSUBMENU = 2;

    protected static float CENTER = (float) Math.PI / 2;
    protected static float RAD24 = (float)(24 * Math.PI / 180);
    protected static final float SWEEP_SLICE = 0.14f;
    protected static final float SWEEP_ARC = 0.23f;

    // geometry
    private int mRadius;
    private int mRadiusInc;

    // the detection if touch is inside a slice is offset
    // inbounds by this amount to allow the selection to show before the
    // finger covers it
    private int mTouchOffset;

    private List<PieItem> mOpen;

    private Paint mSelectedPaint;
    private Paint mSubPaint;
    private Paint mMenuArcPaint;

    // touch handling
    private PieItem mCurrentItem;

    private Paint mFocusPaint;
    private int mSuccessColor;
    private int mFailColor;
    private int mCircleSize;
    private int mFocusX;
    private int mFocusY;
    private int mCenterX;
    private int mCenterY;
    private int mArcCenterY;
    private int mSliceCenterY;
    private int mPieCenterX;
    private int mPieCenterY;
    private int mSliceRadius;
    private int mArcRadius;
    private int mArcOffset;

    private int mDialAngle;
    private RectF mCircle;
    private RectF mDial;
    private Point mPoint1;
    private Point mPoint2;
    private int mStartAnimationAngle;
    private boolean mFocused;
    private int mInnerOffset;
    private int mOuterStroke;
    private int mInnerStroke;
    private boolean mTapMode;
    private boolean mBlockFocus;
    private int mTouchSlopSquared;
    private Point mDown;
    private boolean mOpening;
    private LinearAnimation mXFade;
    private LinearAnimation mFadeIn;
    private FadeOutAnimation mFadeOut;
    private LinearAnimation mSlice;
    private volatile boolean mFocusCancelled;
    private PointF mPolar = new PointF();
    private TextDrawable mLabel;
    private int mDeadZone;
    private int mAngleZone;
    private float mCenterAngle;



    private Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch(msg.what) {
            case MSG_OPEN:
                if (mListener != null) {
                    mListener.onPieOpened(mPieCenterX, mPieCenterY);
                }
                break;
            case MSG_CLOSE:
                if (mListener != null) {
                    mListener.onPieClosed();
                }
                break;
            case MSG_OPENSUBMENU:
                onEnterOpen();
                break;
            }

        }
    };

    private PieListener mListener;

    static public interface PieListener {
        public void onPieOpened(int centerX, int centerY);
        public void onPieClosed();
    }

    public void setPieListener(PieListener pl) {
        mListener = pl;
    }

    public PieRenderer(Context context) {
        init(context);
    }

    private void init(Context ctx) {
        setVisible(false);
        mOpen = new ArrayList<PieItem>();
        mOpen.add(new PieItem(null, 0));
        Resources res = ctx.getResources();
        mRadius = (int) res.getDimensionPixelSize(R.dimen.pie_radius_start);
        mRadiusInc = (int) res.getDimensionPixelSize(R.dimen.pie_radius_increment);
        mCircleSize = mRadius - res.getDimensionPixelSize(R.dimen.focus_radius_offset);
        mTouchOffset = (int) res.getDimensionPixelSize(R.dimen.pie_touch_offset);
        mSelectedPaint = new Paint();
        mSelectedPaint.setColor(Color.argb(255, 51, 181, 229));
        mSelectedPaint.setAntiAlias(true);
        mSubPaint = new Paint();
        mSubPaint.setAntiAlias(true);
        mSubPaint.setColor(Color.argb(200, 250, 230, 128));
        mFocusPaint = new Paint();
        mFocusPaint.setAntiAlias(true);
        mFocusPaint.setColor(Color.WHITE);
        mFocusPaint.setStyle(Paint.Style.STROKE);
        mSuccessColor = Color.GREEN;
        mFailColor = Color.RED;
        mCircle = new RectF();
        mDial = new RectF();
        mPoint1 = new Point();
        mPoint2 = new Point();
        mInnerOffset = res.getDimensionPixelSize(R.dimen.focus_inner_offset);
        mOuterStroke = res.getDimensionPixelSize(R.dimen.focus_outer_stroke);
        mInnerStroke = res.getDimensionPixelSize(R.dimen.focus_inner_stroke);
        mState = STATE_IDLE;
        mBlockFocus = false;
        mTouchSlopSquared = ViewConfiguration.get(ctx).getScaledTouchSlop();
        mTouchSlopSquared = mTouchSlopSquared * mTouchSlopSquared;
        mDown = new Point();
        mMenuArcPaint = new Paint();
        mMenuArcPaint.setAntiAlias(true);
        mMenuArcPaint.setColor(Color.argb(140, 255, 255, 255));
        mMenuArcPaint.setStrokeWidth(10);
        mMenuArcPaint.setStyle(Paint.Style.STROKE);
        mSliceRadius = res.getDimensionPixelSize(R.dimen.pie_item_radius);
        mArcRadius = res.getDimensionPixelSize(R.dimen.pie_arc_radius);
        mArcOffset = res.getDimensionPixelSize(R.dimen.pie_arc_offset);
        mLabel = new TextDrawable(res);
        mLabel.setDropShadow(true);
        mDeadZone = res.getDimensionPixelSize(R.dimen.pie_deadzone_width);
        mAngleZone = res.getDimensionPixelSize(R.dimen.pie_anglezone_width);
    }

    private PieItem getRoot() {
        return mOpen.get(0);
    }

    public boolean showsItems() {
        return mTapMode;
    }

    public void addItem(PieItem item) {
        // add the item to the pie itself
        getRoot().addItem(item);
    }

    public void clearItems() {
        getRoot().clearItems();
    }

    public void showInCenter() {
        if ((mState == STATE_PIE) && isVisible()) {
            mTapMode = false;
            show(false);
        } else {
            if (mState != STATE_IDLE) {
                cancelFocus();
            }
            mState = STATE_PIE;
            resetPieCenter();
            setCenter(mPieCenterX, mPieCenterY);
            mTapMode = true;
            show(true);
        }
    }

    public void hide() {
        show(false);
    }

    /**
     * guaranteed has center set
     * @param show
     */
    private void show(boolean show) {
        if (show) {
            if (mXFade != null) {
                mXFade.cancel();
            }
            mState = STATE_PIE;
            // ensure clean state
            mCurrentItem = null;
            PieItem root = getRoot();
            for (PieItem openItem : mOpen) {
                if (openItem.hasItems()) {
                    for (PieItem item : openItem.getItems()) {
                        item.setSelected(false);
                    }
                }
            }
            mLabel.setText("");
            mOpen.clear();
            mOpen.add(root);
            layoutPie();
            fadeIn();
        } else {
            mState = STATE_IDLE;
            mTapMode = false;
            if (mXFade != null) {
                mXFade.cancel();
            }
            if (mLabel != null) {
                mLabel.setText("");
            }
        }
        setVisible(show);
        mHandler.sendEmptyMessage(show ? MSG_OPEN : MSG_CLOSE);
    }

    private void fadeIn() {
        mFadeIn = new LinearAnimation(0, 1);
        mFadeIn.setDuration(PIE_FADE_IN_DURATION);
        mFadeIn.setAnimationListener(new AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                mFadeIn = null;
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });
        mFadeIn.startNow();
        mOverlay.startAnimation(mFadeIn);
    }

    public void setCenter(int x, int y) {
        mPieCenterX = x;
        mPieCenterY = y;
        mSliceCenterY = y + mSliceRadius - mArcOffset;
        mArcCenterY = y - mArcOffset + mArcRadius;
    }

    @Override
    public void layout(int l, int t, int r, int b) {
        super.layout(l, t, r, b);
        mCenterX = (r - l) / 2;
        mCenterY = (b - t) / 2;

        mFocusX = mCenterX;
        mFocusY = mCenterY;
        resetPieCenter();
        setCircle(mFocusX, mFocusY);
        if (isVisible() && mState == STATE_PIE) {
            setCenter(mPieCenterX, mPieCenterY);
            layoutPie();
        }
    }

    private void resetPieCenter() {
        mPieCenterX = mCenterX;
        mPieCenterY = (int) (getHeight() - 2.5f * mDeadZone);
    }

    private void layoutPie() {
        mCenterAngle = getCenterAngle();
        layoutItems(0, getRoot().getItems());
        layoutLabel(getLevel());
    }

    private void layoutLabel(int level) {
        int x = mPieCenterX - (int) (FloatMath.sin(mCenterAngle - CENTER)
                * (mArcRadius + (level + 2) * mRadiusInc));
        int y = mArcCenterY - mArcRadius - (level + 2) * mRadiusInc;
        int w = mLabel.getIntrinsicWidth();
        int h = mLabel.getIntrinsicHeight();
        mLabel.setBounds(x - w/2, y - h/2, x + w/2, y + h/2);
    }

    private void layoutItems(int level, List<PieItem> items) {
        int extend = 1;
        Path path = makeSlice(getDegrees(0) + extend, getDegrees(SWEEP_ARC) - extend,
                mArcRadius, mArcRadius + mRadiusInc + mRadiusInc / 4,
                mPieCenterX, mArcCenterY - level * mRadiusInc);
        final int count = items.size();
        int pos = 0;
        for (PieItem item : items) {
            // shared between items
            item.setPath(path);
            float angle = getArcCenter(item, pos, count);
            int w = item.getIntrinsicWidth();
            int h = item.getIntrinsicHeight();
            // move views to outer border
            int r = mArcRadius + mRadiusInc * 2 / 3;
            int x = (int) (r * Math.cos(angle));
            int y = mArcCenterY - (level * mRadiusInc) - (int) (r * Math.sin(angle)) - h / 2;
            x = mPieCenterX + x - w / 2;
            item.setBounds(x, y, x + w, y + h);
            item.setLevel(level);
            if (item.hasItems()) {
                layoutItems(level + 1, item.getItems());
            }
            pos++;
        }
    }

    private Path makeSlice(float start, float end, int inner, int outer, int cx, int cy) {
        RectF bb =
                new RectF(cx - outer, cy - outer, cx + outer,
                        cy + outer);
        RectF bbi =
                new RectF(cx - inner, cy - inner, cx + inner,
                        cy + inner);
        Path path = new Path();
        path.arcTo(bb, start, end - start, true);
        path.arcTo(bbi, end, start - end);
        path.close();
        return path;
    }

    private float getArcCenter(PieItem item, int pos, int count) {
        return getCenter(pos, count, SWEEP_ARC);
    }

    private float getSliceCenter(PieItem item, int pos, int count) {
        float center = (getCenterAngle() - CENTER) * 0.5f + CENTER;
        return center + (count - 1) * SWEEP_SLICE / 2f
                - pos * SWEEP_SLICE;
    }

    private float getCenter(int pos, int count, float sweep) {
        return mCenterAngle + (count - 1) * sweep / 2f - pos * sweep;
    }

    private float getCenterAngle() {
        float center = CENTER;
        if (mPieCenterX < mDeadZone + mAngleZone) {
            center = CENTER - (mAngleZone - mPieCenterX + mDeadZone) * RAD24
                    / (float) mAngleZone;
        } else if (mPieCenterX > getWidth() - mDeadZone - mAngleZone) {
            center = CENTER + (mPieCenterX - (getWidth() - mDeadZone - mAngleZone)) * RAD24
                    / (float) mAngleZone;
        }
        return center;
    }

    /**
     * converts a
     * @param angle from 0..PI to Android degrees (clockwise starting at 3 o'clock)
     * @return skia angle
     */
    private float getDegrees(double angle) {
        return (float) (360 - 180 * angle / Math.PI);
    }

    private void startFadeOut(final PieItem item) {
        if (mFadeIn != null) {
            mFadeIn.cancel();
        }
        if (mXFade != null) {
            mXFade.cancel();
        }
        mFadeOut = new FadeOutAnimation();
        mFadeOut.setDuration(PIE_FADE_OUT_DURATION);
        mFadeOut.setAnimationListener(new AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                item.performClick();
                mFadeOut = null;
                deselect();
                show(false);
                mOverlay.setAlpha(1);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });
        mFadeOut.startNow();
        mOverlay.startAnimation(mFadeOut);
    }

    // root does not count
    private boolean hasOpenItem() {
        return mOpen.size() > 1;
    }

    // pop an item of the open item stack
    private PieItem closeOpenItem() {
        PieItem item = getOpenItem();
        mOpen.remove(mOpen.size() -1);
        return item;
    }

    private PieItem getOpenItem() {
        return mOpen.get(mOpen.size() - 1);
    }

    // return the children either the root or parent of the current open item
    private PieItem getParent() {
        return mOpen.get(Math.max(0, mOpen.size() - 2));
    }

    private int getLevel() {
        return mOpen.size() - 1;
    }

    @Override
    public void onDraw(Canvas canvas) {
        float alpha = 1;
        if (mXFade != null) {
            alpha = mXFade.getValue();
        } else if (mFadeIn != null) {
            alpha = mFadeIn.getValue();
        } else if (mFadeOut != null) {
            alpha = mFadeOut.getValue();
        }
        int state = canvas.save();
        if (mFadeIn != null) {
            float sf = 0.9f + alpha * 0.1f;
            canvas.scale(sf, sf, mPieCenterX, mPieCenterY);
        }
        if (mState != STATE_PIE) {
            drawFocus(canvas);
        }
        if (mState == STATE_FINISHING) {
            canvas.restoreToCount(state);
            return;
        }
        if (mState != STATE_PIE) return;
        if (!hasOpenItem() || (mXFade != null)) {
            // draw base menu
            drawArc(canvas, getLevel(), getParent());
            List<PieItem> items = getParent().getItems();
            final int count = items.size();
            int pos = 0;
            for (PieItem item : getParent().getItems()) {
                drawItem(Math.max(0, mOpen.size() - 2), pos, count, canvas, item, alpha);
                pos++;
            }
            mLabel.draw(canvas);
        }
        if (hasOpenItem()) {
            int level = getLevel();
            drawArc(canvas, level, getOpenItem());
            List<PieItem> items = getOpenItem().getItems();
            final int count = items.size();
            int pos = 0;
            for (PieItem inner : items) {
                if (mFadeOut != null) {
                    drawItem(level, pos, count, canvas, inner, alpha);
                } else {
                    drawItem(level, pos, count, canvas, inner, (mXFade != null) ? (1 - 0.5f * alpha) : 1);
                }
                pos++;
            }
            mLabel.draw(canvas);
        }
        canvas.restoreToCount(state);
    }

    private void drawArc(Canvas canvas, int level, PieItem item) {
        // arc
        if (mState == STATE_PIE) {
            final int count = item.getItems().size();
            float start = mCenterAngle + (count * SWEEP_ARC / 2f);
            float end =  mCenterAngle - (count * SWEEP_ARC / 2f);
            int cy = mArcCenterY - level * mRadiusInc;
            canvas.drawArc(new RectF(mPieCenterX - mArcRadius, cy - mArcRadius,
                    mPieCenterX + mArcRadius, cy + mArcRadius),
                    getDegrees(end), getDegrees(start) - getDegrees(end), false, mMenuArcPaint);
        }
    }

    private void drawItem(int level, int pos, int count, Canvas canvas, PieItem item, float alpha) {
        if (mState == STATE_PIE) {
            if (item.getPath() != null) {
                int y = mArcCenterY - level * mRadiusInc;
                if (item.isSelected()) {
                    Paint p = mSelectedPaint;
                    int state = canvas.save();
                    float angle = 0;
                    if (mSlice != null) {
                        angle = mSlice.getValue();
                    } else {
                        angle = getArcCenter(item, pos, count) - SWEEP_ARC / 2f;
                    }
                    angle = getDegrees(angle);
                    canvas.rotate(angle, mPieCenterX, y);
                    if (mFadeOut != null) {
                        p.setAlpha((int)(255 * alpha));
                    }
                    canvas.drawPath(item.getPath(), p);
                    if (mFadeOut != null) {
                        p.setAlpha(255);
                    }
                    canvas.restoreToCount(state);
                }
                if (mFadeOut == null) {
                    alpha = alpha * (item.isEnabled() ? 1 : 0.3f);
                    // draw the item view
                    item.setAlpha(alpha);
                }
                item.draw(canvas);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent evt) {
        float x = evt.getX();
        float y = evt.getY();
        int action = evt.getActionMasked();
        getPolar(x, y, !mTapMode, mPolar);
        if (MotionEvent.ACTION_DOWN == action) {
            if ((x < mDeadZone) || (x > getWidth() - mDeadZone)) {
                return false;
            }
            mDown.x = (int) evt.getX();
            mDown.y = (int) evt.getY();
            mOpening = false;
            if (mTapMode) {
                PieItem item = findItem(mPolar);
                if ((item != null) && (mCurrentItem != item)) {
                    mState = STATE_PIE;
                    onEnter(item);
                }
            } else {
                setCenter((int) x, (int) y);
                show(true);
            }
            return true;
        } else if (MotionEvent.ACTION_UP == action) {
            if (isVisible()) {
                PieItem item = mCurrentItem;
                if (mTapMode) {
                    item = findItem(mPolar);
                    if (mOpening) {
                        mOpening = false;
                        return true;
                    }
                }
                if (item == null) {
                    mTapMode = false;
                    show(false);
                } else if (!mOpening && !item.hasItems()) {
                        startFadeOut(item);
                        mTapMode = false;
                } else {
                    mTapMode = true;
                }
                return true;
            }
        } else if (MotionEvent.ACTION_CANCEL == action) {
            if (isVisible() || mTapMode) {
                show(false);
            }
            deselect();
            mHandler.removeMessages(MSG_OPENSUBMENU);
            return false;
        } else if (MotionEvent.ACTION_MOVE == action) {
            if (pulledToCenter(mPolar)) {
                mHandler.removeMessages(MSG_OPENSUBMENU);
                if (hasOpenItem()) {
                    if (mCurrentItem != null) {
                        mCurrentItem.setSelected(false);
                    }
                    closeOpenItem();
                    mCurrentItem = null;
                } else {
                    deselect();
                }
                mLabel.setText("");
                return false;
            }
            PieItem item = findItem(mPolar);
            boolean moved = hasMoved(evt);
            if ((item != null) && (mCurrentItem != item) && (!mOpening || moved)) {
                mHandler.removeMessages(MSG_OPENSUBMENU);
                // only select if we didn't just open or have moved past slop
                if (moved) {
                    // switch back to swipe mode
                    mTapMode = false;
                }
                onEnterSelect(item);
                mHandler.sendEmptyMessageDelayed(MSG_OPENSUBMENU, PIE_OPEN_SUB_DELAY);
            }
        }
        return false;
    }

    private boolean pulledToCenter(PointF polarCoords) {
        return polarCoords.y < mArcRadius - mRadiusInc;
    }

    private boolean inside(PointF polar, PieItem item, int pos, int count) {
        float start = getSliceCenter(item, pos, count) - SWEEP_SLICE / 2f;
        boolean res =  (mArcRadius < polar.y)
                && (start < polar.x)
                && (start + SWEEP_SLICE > polar.x)
                && (!mTapMode || (mArcRadius + mRadiusInc > polar.y));
        return res;
    }

    private void getPolar(float x, float y, boolean useOffset, PointF res) {
        // get angle and radius from x/y
        res.x = (float) Math.PI / 2;
        x = x - mPieCenterX;
        float y1 = mSliceCenterY - getLevel() * mRadiusInc - y;
        float y2 = mArcCenterY - getLevel() * mRadiusInc - y;
        res.y = (float) Math.sqrt(x * x + y2 * y2);
        if (x != 0) {
            res.x = (float) Math.atan2(y1,  x);
            if (res.x < 0) {
                res.x = (float) (2 * Math.PI + res.x);
            }
        }
        res.y = res.y + (useOffset ? mTouchOffset : 0);
    }

    private boolean hasMoved(MotionEvent e) {
        return mTouchSlopSquared < (e.getX() - mDown.x) * (e.getX() - mDown.x)
                + (e.getY() - mDown.y) * (e.getY() - mDown.y);
    }

    private void onEnterSelect(PieItem item) {
        if (mCurrentItem != null) {
            mCurrentItem.setSelected(false);
        }
        if (item != null && item.isEnabled()) {
            moveSelection(mCurrentItem, item);
            item.setSelected(true);
            mCurrentItem = item;
            mLabel.setText(mCurrentItem.getLabel());
            layoutLabel(getLevel());
        } else {
            mCurrentItem = null;
        }
    }

    private void onEnterOpen() {
        if ((mCurrentItem != null) && (mCurrentItem != getOpenItem()) && mCurrentItem.hasItems()) {
            openCurrentItem();
        }
    }

    /**
     * enter a slice for a view
     * updates model only
     * @param item
     */
    private void onEnter(PieItem item) {
        if (mCurrentItem != null) {
            mCurrentItem.setSelected(false);
        }
        if (item != null && item.isEnabled()) {
            item.setSelected(true);
            mCurrentItem = item;
            mLabel.setText(mCurrentItem.getLabel());
            if ((mCurrentItem != getOpenItem()) && mCurrentItem.hasItems()) {
                openCurrentItem();
                layoutLabel(getLevel());
            }
        } else {
            mCurrentItem = null;
        }
    }

    private void deselect() {
        if (mCurrentItem != null) {
            mCurrentItem.setSelected(false);
        }
        if (hasOpenItem()) {
            PieItem item = closeOpenItem();
            onEnter(item);
        } else {
            mCurrentItem = null;
        }
    }

    private int getItemPos(PieItem target) {
        List<PieItem> items = getOpenItem().getItems();
        return items.indexOf(target);
    }

    private int getCurrentCount() {
        return getOpenItem().getItems().size();
    }

    private void moveSelection(PieItem from, PieItem to) {
        final int count = getCurrentCount();
        final int fromPos = getItemPos(from);
        final int toPos = getItemPos(to);
        if (fromPos != -1 && toPos != -1) {
            float startAngle = getArcCenter(from, getItemPos(from), count)
                    - SWEEP_ARC / 2f;
            float endAngle = getArcCenter(to, getItemPos(to), count)
                    - SWEEP_ARC / 2f;
            mSlice = new LinearAnimation(startAngle, endAngle);
            mSlice.setDuration(PIE_SLICE_DURATION);
            mSlice.setAnimationListener(new AnimationListener() {
                @Override
                public void onAnimationEnd(Animation arg0) {
                    mSlice = null;
                }

                @Override
                public void onAnimationRepeat(Animation arg0) {
                }

                @Override
                public void onAnimationStart(Animation arg0) {
                }
            });
            mOverlay.startAnimation(mSlice);
        }
    }

    private void openCurrentItem() {
        if ((mCurrentItem != null) && mCurrentItem.hasItems()) {
            mOpen.add(mCurrentItem);
            layoutLabel(getLevel());
            mOpening = true;
            if (mFadeIn != null) {
                mFadeIn.cancel();
            }
            mXFade = new LinearAnimation(1, 0);
            mXFade.setDuration(PIE_XFADE_DURATION);
            final PieItem ci = mCurrentItem;
            mXFade.setAnimationListener(new AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    mXFade = null;
                    ci.setSelected(false);
                    mOpening = false;
                }

                @Override
                public void onAnimationRepeat(Animation animation) {
                }
            });
            mXFade.startNow();
            mOverlay.startAnimation(mXFade);
        }
    }

    /**
     * @param polar x: angle, y: dist
     * @return the item at angle/dist or null
     */
    private PieItem findItem(PointF polar) {
        // find the matching item:
        List<PieItem> items = getOpenItem().getItems();
        final int count = items.size();
        int pos = 0;
        for (PieItem item : items) {
            if (inside(polar, item, pos, count)) {
                return item;
            }
            pos++;
        }
        return null;
    }


    @Override
    public boolean handlesTouch() {
        return true;
    }

    // focus specific code

    public void setBlockFocus(boolean blocked) {
        mBlockFocus = blocked;
        if (blocked) {
            clear();
        }
    }

    public void setFocus(int x, int y) {
        mFocusX = x;
        mFocusY = y;
        setCircle(mFocusX, mFocusY);
    }

    public void alignFocus(int x, int y) {
        mOverlay.removeCallbacks(mDisappear);
        mAnimation.cancel();
        mAnimation.reset();
        mFocusX = x;
        mFocusY = y;
        mDialAngle = DIAL_HORIZONTAL;
        setCircle(x, y);
        mFocused = false;
    }

    public int getSize() {
        return 2 * mCircleSize;
    }

    private int getRandomRange() {
        return (int)(-60 + 120 * Math.random());
    }

    private void setCircle(int cx, int cy) {
        mCircle.set(cx - mCircleSize, cy - mCircleSize,
                cx + mCircleSize, cy + mCircleSize);
        mDial.set(cx - mCircleSize + mInnerOffset, cy - mCircleSize + mInnerOffset,
                cx + mCircleSize - mInnerOffset, cy + mCircleSize - mInnerOffset);
    }

    public void drawFocus(Canvas canvas) {
        if (mBlockFocus) return;
        mFocusPaint.setStrokeWidth(mOuterStroke);
        canvas.drawCircle((float) mFocusX, (float) mFocusY, (float) mCircleSize, mFocusPaint);
        if (mState == STATE_PIE) return;
        int color = mFocusPaint.getColor();
        if (mState == STATE_FINISHING) {
            mFocusPaint.setColor(mFocused ? mSuccessColor : mFailColor);
        }
        mFocusPaint.setStrokeWidth(mInnerStroke);
        drawLine(canvas, mDialAngle, mFocusPaint);
        drawLine(canvas, mDialAngle + 45, mFocusPaint);
        drawLine(canvas, mDialAngle + 180, mFocusPaint);
        drawLine(canvas, mDialAngle + 225, mFocusPaint);
        canvas.save();
        // rotate the arc instead of its offset to better use framework's shape caching
        canvas.rotate(mDialAngle, mFocusX, mFocusY);
        canvas.drawArc(mDial, 0, 45, false, mFocusPaint);
        canvas.drawArc(mDial, 180, 45, false, mFocusPaint);
        canvas.restore();
        mFocusPaint.setColor(color);
    }

    private void drawLine(Canvas canvas, int angle, Paint p) {
        convertCart(angle, mCircleSize - mInnerOffset, mPoint1);
        convertCart(angle, mCircleSize - mInnerOffset + mInnerOffset / 3, mPoint2);
        canvas.drawLine(mPoint1.x + mFocusX, mPoint1.y + mFocusY,
                mPoint2.x + mFocusX, mPoint2.y + mFocusY, p);
    }

    private static void convertCart(int angle, int radius, Point out) {
        double a = 2 * Math.PI * (angle % 360) / 360;
        out.x = (int) (radius * Math.cos(a) + 0.5);
        out.y = (int) (radius * Math.sin(a) + 0.5);
    }

    @Override
    public void showStart() {
        if (mState == STATE_PIE) return;
        cancelFocus();
        mStartAnimationAngle = 67;
        int range = getRandomRange();
        startAnimation(SCALING_UP_TIME,
                false, mStartAnimationAngle, mStartAnimationAngle + range);
        mState = STATE_FOCUSING;
    }

    @Override
    public void showSuccess(boolean timeout) {
        if (mState == STATE_FOCUSING) {
            startAnimation(SCALING_DOWN_TIME,
                    timeout, mStartAnimationAngle);
            mState = STATE_FINISHING;
            mFocused = true;
        }
    }

    @Override
    public void showFail(boolean timeout) {
        if (mState == STATE_FOCUSING) {
            startAnimation(SCALING_DOWN_TIME,
                    timeout, mStartAnimationAngle);
            mState = STATE_FINISHING;
            mFocused = false;
        }
    }

    private void cancelFocus() {
        mFocusCancelled = true;
        mOverlay.removeCallbacks(mDisappear);
        if (mAnimation != null && !mAnimation.hasEnded()) {
            mAnimation.cancel();
        }
        mFocusCancelled = false;
        mFocused = false;
        mState = STATE_IDLE;
    }

    @Override
    public void clear() {
        if (mState == STATE_PIE) return;
        cancelFocus();
        mOverlay.post(mDisappear);
    }

    private void startAnimation(long duration, boolean timeout,
            float toScale) {
        startAnimation(duration, timeout, mDialAngle,
                toScale);
    }

    private void startAnimation(long duration, boolean timeout,
            float fromScale, float toScale) {
        setVisible(true);
        mAnimation.reset();
        mAnimation.setDuration(duration);
        mAnimation.setScale(fromScale, toScale);
        mAnimation.setAnimationListener(timeout ? mEndAction : null);
        mOverlay.startAnimation(mAnimation);
        update();
    }

    private class EndAction implements Animation.AnimationListener {
        @Override
        public void onAnimationEnd(Animation animation) {
            // Keep the focus indicator for some time.
            if (!mFocusCancelled) {
                mOverlay.postDelayed(mDisappear, DISAPPEAR_TIMEOUT);
            }
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
        }

        @Override
        public void onAnimationStart(Animation animation) {
        }
    }

    private class Disappear implements Runnable {
        @Override
        public void run() {
            if (mState == STATE_PIE) return;
            setVisible(false);
            mFocusX = mCenterX;
            mFocusY = mCenterY;
            mState = STATE_IDLE;
            setCircle(mFocusX, mFocusY);
            mFocused = false;
        }
    }

    private class FadeOutAnimation extends Animation {

        private float mAlpha;

        public float getValue() {
            return mAlpha;
        }

        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            if (interpolatedTime < 0.2) {
                mAlpha = 1;
            } else if (interpolatedTime < 0.3) {
                mAlpha = 0;
            } else {
                mAlpha = 1 - (interpolatedTime - 0.3f) / 0.7f;
            }
        }
    }

    private class ScaleAnimation extends Animation {
        private float mFrom = 1f;
        private float mTo = 1f;

        public ScaleAnimation() {
            setFillAfter(true);
        }

        public void setScale(float from, float to) {
            mFrom = from;
            mTo = to;
        }

        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            mDialAngle = (int)(mFrom + (mTo - mFrom) * interpolatedTime);
        }
    }

    private class LinearAnimation extends Animation {
        private float mFrom;
        private float mTo;
        private float mValue;

        public LinearAnimation(float from, float to) {
            setFillAfter(true);
            setInterpolator(new LinearInterpolator());
            mFrom = from;
            mTo = to;
        }

        public float getValue() {
            return mValue;
        }

        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            mValue = (mFrom + (mTo - mFrom) * interpolatedTime);
        }
    }

}
