/*
 * Copyright (C) 2013 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.cts.verifier.sensors;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.hardware.SensorManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Surface;
import android.view.View;

/**
 * A view class that draws the user prompt
 *
 * The following piece of code should show how to use this view.
 *
 *  public void testUI()  {
 *     final int MAX_TILT_ANGLE = 70; // +/- 70
 *
 *     final int TILT_ANGLE_STEP = 5; // 5 degree(s) per step
 *     final int YAW_ANGLE_STEP = 10; // 10 degree(s) per step
 *
 *     RangeCoveredRegister xCovered, yCovered, zCovered;
 *     xCovered = new RangeCoveredRegister(-MAX_TILT_ANGLE, +MAX_TILT_ANGLE, TILT_ANGLE_STEP);
 *
 *     yCovered = new RangeCoveredRegister(-MAX_TILT_ANGLE, +MAX_TILT_ANGLE, TILT_ANGLE_STEP);
 *     zCovered = new RangeCoveredRegister(YAW_ANGLE_STEP);
 *
 *     xCovered.update(40);
 *     xCovered.update(-40);
 *     xCovered.update(12);
 *
 *     yCovered.update(50);
 *     yCovered.update(-51);
 *
 *     zCovered.update(150);
 *     zCovered.update(42);
 *
 *     setDataProvider(xCovered, yCovered, zCovered);
 *     enableAxis(RVCVRecordActivity.AXIS_ALL); //debug mode, show all three axis
 * }
 */
public class MotionIndicatorView extends View {
    private final String TAG = "MotionIndicatorView";
    private final boolean LOCAL_LOGV = false;

    private Paint mCursorPaint;
    private Paint mLimitPaint;
    private Paint mCoveredPaint;
    private Paint mRangePaint;
    private Paint mEraserPaint;

    // UI settings
    private final int XBAR_WIDTH = 50;
    private final int XBAR_MARGIN = 50;
    private final int XBAR_CURSOR_ADD = 20;

    private final int YBAR_WIDTH = 50;
    private final int YBAR_MARGIN = 50;
    private final int YBAR_CURSOR_ADD = 20;

    private final int ZRING_WIDTH = 50;
    private final int ZRING_CURSOR_ADD = 30;


    private int mXSize, mYSize;
    private RectF mZBoundOut, mZBoundOut2, mZBoundIn, mZBoundIn2;

    private RangeCoveredRegister mXCovered, mYCovered, mZCovered;

    private boolean mXEnabled, mYEnabled, mZEnabled;

    private boolean mIsDeviceRotated = false;

    /**
     * Constructor
     * @param context
     */
    public MotionIndicatorView(Context context) {
        super(context);
        init();
    }

    /**
     * Constructor
     * @param context Application context
     * @param attrs
     */
    public MotionIndicatorView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    /**
     * Initialize the Paint objects
     */
    private void init() {

        mCursorPaint = new Paint();
        mCursorPaint.setColor(Color.BLUE);

        mLimitPaint = new Paint();
        mLimitPaint.setColor(Color.YELLOW);

        mCoveredPaint = new Paint();
        mCoveredPaint.setColor(Color.CYAN);

        mRangePaint = new Paint();
        mRangePaint.setColor(Color.DKGRAY);

        mEraserPaint = new Paint();
        mEraserPaint.setColor(Color.TRANSPARENT);
        // ensure the erasing effect
        mEraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
    }

    /**
     * Connect the view to certain data provider objects
     * @param x Data provider for x direction tilt angle
     * @param y Data provider for y direction tilt angle
     * @param z Data provider for z rotation
     */
    public void setDataProvider(RangeCoveredRegister x,
                                RangeCoveredRegister y,
                                RangeCoveredRegister z)    {
        mXCovered = x;
        mYCovered = y;
        mZCovered = z;
    }

    /**
     * Set the device's current rotation
     * @param rotation Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_180, or
     *                 Surface.ROTATION_270
     */
    public void setDeviceRotation(int rotation) {
        mIsDeviceRotated = (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270);
    }

    /**
     * Set the active axis for display
     *
     * @param axis AXIS_X, AXIS_Y, AXIS_Z for x, y, z axis indicators, or AXIS_ALL for all three.
     */
    public void enableAxis(int axis)  {
        mXEnabled = mYEnabled = mZEnabled = false;

        switch(axis)
        {
            case SensorManager.AXIS_X:
                mXEnabled = true;
                break;
            case SensorManager.AXIS_Y:
                mYEnabled = true;
                break;
            case SensorManager.AXIS_Z:
                mZEnabled = true;
                break;
            case RVCVRecordActivity.AXIS_ALL:
                mXEnabled = mYEnabled = mZEnabled = true;
        }
    }

    /**
     * Doing some pre-calculation that only changes when view dimensions are changed.
     * @param w
     * @param h
     * @param oldw
     * @param oldh
     */
    @Override
    protected void onSizeChanged (int w, int h, int oldw, int oldh) {
        mXSize = w;
        mYSize = h;

        float halfSideLength = 0.4f * Math.min(w, h);
        float leftSide = w/2 - halfSideLength;
        float topSide = h/2 - halfSideLength;
        float rightSide = w/2 + halfSideLength;
        float bottomSide = h/2 + halfSideLength;

        mZBoundOut = new RectF(leftSide, topSide, rightSide, bottomSide);
        mZBoundOut2 = new RectF(
                leftSide-ZRING_CURSOR_ADD, topSide-ZRING_CURSOR_ADD,
                rightSide+ZRING_CURSOR_ADD, bottomSide+ZRING_CURSOR_ADD);
        mZBoundIn = new RectF(
                leftSide+ZRING_WIDTH, topSide+ZRING_WIDTH,
                rightSide-ZRING_WIDTH, bottomSide-ZRING_WIDTH);
        mZBoundIn2 = new RectF(
                leftSide+ZRING_WIDTH+ZRING_CURSOR_ADD, topSide+ZRING_WIDTH+ZRING_CURSOR_ADD,
                rightSide-ZRING_WIDTH-ZRING_CURSOR_ADD, bottomSide-ZRING_WIDTH-ZRING_CURSOR_ADD);

        if (LOCAL_LOGV) Log.v(TAG, "New view size = ("+w+", "+h+")");
    }

    /**
     * Draw UI depends on the selected axis and registered value
     *
     * @param canvas the canvas to draw on
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int i,t;

        Paint p = new Paint();
        p.setColor(Color.YELLOW);
        canvas.drawRect(10,10, 50, 50, p);

        // In order to determine which progress bar to draw, the device's rotation must be accounted
        // for since the accelerometer rotates with the display.
        boolean drawX = (mXEnabled && !mIsDeviceRotated) || (mYEnabled && mIsDeviceRotated);
        boolean drawY = (mYEnabled && !mIsDeviceRotated) || (mXEnabled && mIsDeviceRotated);

        if (drawX && mXCovered != null) {
            RangeCoveredRegister covered = mIsDeviceRotated ? mYCovered : mXCovered;
            int xNStep = covered.getNSteps() + 4; // two on each side as a buffer
            int xStepSize = mXSize * 3/4 / xNStep;
            int xLeft = mXSize * 1/8 + (mXSize * 3/4 % xNStep)/2;

            // base bar
            canvas.drawRect(xLeft, XBAR_MARGIN,
                    xLeft+xStepSize*xNStep-1, XBAR_WIDTH+XBAR_MARGIN, mRangePaint);

            // covered range
            for (i=0; i<covered.getNSteps(); ++i) {
                if (covered.isCovered(i)) {
                    canvas.drawRect(
                            xLeft+xStepSize*(i+2), XBAR_MARGIN,
                            xLeft+xStepSize*(i+3)-1, XBAR_WIDTH + XBAR_MARGIN,
                            mCoveredPaint);
                }
            }

            // limit
            canvas.drawRect(xLeft+xStepSize*2-4, XBAR_MARGIN,
                    xLeft+xStepSize*2+3, XBAR_WIDTH+XBAR_MARGIN, mLimitPaint);
            canvas.drawRect(xLeft+xStepSize*(xNStep-2)-4, XBAR_MARGIN,
                    xLeft+xStepSize*(xNStep-2)+3, XBAR_WIDTH+XBAR_MARGIN, mLimitPaint);

            // cursor
            t = (int)(xLeft+xStepSize*(covered.getLastValue()+2));
            canvas.drawRect(t-4, XBAR_MARGIN-XBAR_CURSOR_ADD, t+3,
                    XBAR_WIDTH+XBAR_MARGIN+XBAR_CURSOR_ADD, mCursorPaint);
        }

        if (drawY && mYCovered != null) {
            RangeCoveredRegister covered = mIsDeviceRotated ? mXCovered : mYCovered;
            int yNStep = covered.getNSteps() + 4; // two on each side as a buffer
            int yStepSize = mYSize * 3/4 / yNStep;
            int yLeft = mYSize * 1/8 + (mYSize * 3/4 % yNStep)/2;

            // base bar
            canvas.drawRect(YBAR_MARGIN, yLeft,
                    YBAR_WIDTH+YBAR_MARGIN, yLeft+yStepSize*yNStep-1, mRangePaint);

            // covered range
            for (i=0; i<covered.getNSteps(); ++i) {
                if (covered.isCovered(i)) {
                    canvas.drawRect(
                            YBAR_MARGIN, yLeft+yStepSize*(i+2),
                            YBAR_WIDTH + YBAR_MARGIN, yLeft+yStepSize*(i+3)-1,
                            mCoveredPaint);
                }
            }

            // limit
            canvas.drawRect(YBAR_MARGIN, yLeft + yStepSize * 2 - 4,
                    YBAR_WIDTH + YBAR_MARGIN, yLeft + yStepSize * 2 + 3, mLimitPaint);
            canvas.drawRect(YBAR_MARGIN, yLeft + yStepSize * (yNStep - 2) - 4,
                    YBAR_WIDTH + YBAR_MARGIN, yLeft + yStepSize * (yNStep - 2) + 3, mLimitPaint);

            // cursor
            t = (int)(yLeft+yStepSize*(covered.getLastValue()+2));
            canvas.drawRect( YBAR_MARGIN-YBAR_CURSOR_ADD, t-4,
                    YBAR_WIDTH+YBAR_MARGIN+YBAR_CURSOR_ADD, t+3, mCursorPaint);
        }

        if (mZEnabled && mZCovered != null) {
            float stepSize  = 360.0f/mZCovered.getNSteps();

            // base bar
            canvas.drawArc(mZBoundOut,0, 360, true, mRangePaint);

            // covered range
            for (i=0; i<mZCovered.getNSteps(); ++i) {
                if (mZCovered.isCovered(i)) {
                    canvas.drawArc(mZBoundOut,i*stepSize-0.2f, stepSize+0.4f,
                            true, mCoveredPaint);
                }
            }
            // clear center
            canvas.drawArc(mZBoundIn, 0, 360, true, mEraserPaint);
            // cursor
            canvas.drawArc(mZBoundOut2, mZCovered.getLastValue()*stepSize- 1, 2,
                    true, mCursorPaint);
            canvas.drawArc(mZBoundIn2, mZCovered.getLastValue()*stepSize-1.5f, 3,
                    true, mEraserPaint);
        }
    }
}

/**
 *  A range register class for the RVCVRecord Activity
 */
class RangeCoveredRegister {
    enum MODE {
        LINEAR,
        ROTATE2D
    }

    private boolean[] mCovered;
    private MODE mMode;
    private int mStep;
    private int mLow, mHigh;
    private int mLastData;

    // high is not inclusive
    RangeCoveredRegister(int low, int high, int step) {
        mMode = MODE.LINEAR;
        mStep = step;
        mLow = low;
        mHigh = high;
        init();
    }

    RangeCoveredRegister(int step) {
        mMode = MODE.ROTATE2D;
        mStep = step;
        mLow = 0;
        mHigh = 360;
        init();
    }

    private void init() {
        if (mMode == MODE.LINEAR) {
            mCovered = new boolean[(mHigh-mLow)/mStep];
        }else {
            mCovered = new boolean[360/mStep];
        }
    }

    /**
     * Test if the range specified by (low, high) is covered.
     *
     * If it is LINEAR mode, the range will be quantized to nearest step boundary. If it is the
     * ROTATE2D mode, it is the same as isFullyCovered().
     *
     * @param low The low end of the range.
     * @param high The high end of the range.
     * @return if the specified range is covered, return true; otherwise false.
     */
    public boolean isRangeCovered(int low, int high) {
        if (mMode == MODE.LINEAR) {
            int iLow = Math.max((low - mLow) / mStep, 0);
            int iHigh = Math.min((high - mLow) / mStep, mCovered.length - 1);

            for (int i = iLow; i <= iHigh; ++i) {
                if (!mCovered[i]) {
                    return false;
                }
            }
            return true;

        } else {
            return isFullyCovered();
        }
    }

    /**
     * Test if the range defined is fully covered.
     *
     * @return if the range is fully covered, return true; otherwise false.
     */
    public boolean isFullyCovered() {
        for (boolean i : mCovered) {
            if (!i) return false;
        }
        return true;
    }

    /**
     * Test if a specific step is covered.
     *
     * @param i the step number
     * @return if the step specified is covered, return true; otherwise false.
     */
    public boolean isCovered(int i) {
        return mCovered[i];
    }

    /**
     *
     *
     * @param data
     * @return if this update changes the status of
     */
    public boolean update(int data) {
        mLastData = data;

        if (mMode == MODE.ROTATE2D) {
            data %= 360;
        }

        int iStep = (data - mLow)/mStep;

        if (iStep>=0 && iStep<getNSteps()) {
            // only record valid data
            mLastData = data;

            if (mCovered[iStep]) {
                return false;
            } else {
                mCovered[iStep] = true;
                return true;
            }
        }
        return false;
    }

    /**
     * Get the number of steps in this register
     *
     * @return The number of steps in this register
     */
    public int getNSteps() {
        //if (mCovered == null) {
        //return 0;
        //}
        return mCovered.length;
    }

    /**
     * Get the last value updated
     *
     * @return The last value updated
     */
    public float getLastValue() {
        // ensure float division
        return ((float)(mLastData - mLow))/mStep;
    }
}
