/*
 * Copyright (C) 2014 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 android.hardware.cts.helpers.sensorTestOperations;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.hardware.cts.helpers.SensorCtsHelper;
import android.hardware.cts.helpers.SensorManagerTestVerifier;
import android.hardware.cts.helpers.SensorTestInformation;
import android.hardware.cts.helpers.SensorTestOperation;
import android.hardware.cts.helpers.SensorVerificationHelper;
import android.hardware.cts.helpers.SensorVerificationHelper.VerificationResult;
import android.hardware.cts.helpers.TestSensorEvent;
import android.util.Log;

import junit.framework.Assert;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * A {@link SensorTestOperation} used to verify that sensor events and sensor values are correct.
 * <p>
 * Provides methods to set test expectations as well as providing a set of default expectations
 * depending on sensor type.  When {{@link #execute()} is called, the sensor will collect the
 * events and then run all the tests.
 * </p>
 */
public class VerifySensorOperation extends SensorTestOperation {
    private static final String TAG = "VerifySensorOperation";

    private static final boolean DEBUG = false;

    private SensorManagerTestVerifier mSensor;
    private Context mContext = null;
    private int mSensorType = 0;
    private int mRateUs = 0;
    private int mMaxBatchReportLatencyUs = 0;
    private int mEventCount = 0;

    private boolean mVerifyEventOrdering = false;

    private boolean mVerifyFrequency = false;
    private double mFrequencyExpected = 0.0;
    private double mFrequencyThreshold = 0.0;

    private boolean mVerifyJitter = false;
    private int mJitterExpected = 0;
    private int mJitterThreshold = 0;

    private boolean mVerifyMean = false;
    private float[] mMeanExpected = null;
    private float[] mMeanThreshold = null;

    private boolean mVerifyMagnitude = false;
    private float mMagnitudeExpected = 0.0f;
    private float mMagnitudeThreshold = 0.0f;

    private boolean mVerifySignum = false;
    private int[] mSignumExpected = null;
    private float[] mSignumThreshold = null;

    private boolean mVerifyStandardDeviation = false;
    private float[] mStandardDeviationThreshold = null;

    /**
     * Create a {@link VerifySensorOperation}.
     *
     * @param context the {@link Context}.
     * @param sensorType the sensor type
     * @param rateUs the rate that
     * @param maxBatchReportLatencyUs the max batch report latency
     * @param eventCount the number of events to gather
     */
    public VerifySensorOperation(Context context, int sensorType, int rateUs,
            int maxBatchReportLatencyUs, int eventCount) {
        mContext = context;
        mSensorType = sensorType;
        mRateUs = rateUs;
        mMaxBatchReportLatencyUs = maxBatchReportLatencyUs;
        mEventCount = eventCount;
        mSensor = new SensorManagerTestVerifier(mContext, mSensorType, mRateUs,
                mMaxBatchReportLatencyUs);
    }

    /**
     * Set all of the default test expectations.
     */
    public void setDefaultVerifications() {
        setDefaultVerifyEventOrdering();
        setDefaultVerifyFrequency();
        setDefaultVerifyJitter();
        setDefaultVerifyMean();
        setDefaultVerifyMagnitude();
        setDefaultVerifySignum();
        setDefaultVerifyStandardDeviation();
    }

    /**
     * Enable the event ordering verification.
     */
    public void verifyEventOrdering() {
        mVerifyEventOrdering = true;
    }

    /**
     * Set the default event ordering verification.
     */
    @SuppressWarnings("deprecation")
    public void setDefaultVerifyEventOrdering() {
        switch (mSensorType) {
            case Sensor.TYPE_ACCELEROMETER:
            case Sensor.TYPE_MAGNETIC_FIELD:
            case Sensor.TYPE_ORIENTATION:
            case Sensor.TYPE_GYROSCOPE:
            case Sensor.TYPE_PRESSURE:
            case Sensor.TYPE_GRAVITY:
            case Sensor.TYPE_LINEAR_ACCELERATION:
            case Sensor.TYPE_ROTATION_VECTOR:
            case Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED:
            case Sensor.TYPE_GAME_ROTATION_VECTOR:
            case Sensor.TYPE_GYROSCOPE_UNCALIBRATED:
            case Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR:
                verifyEventOrdering();
                break;
        }
    }

    /**
     * Enable the frequency verification.
     *
     * @param expected the expected frequency in ns.
     * @param threshold the threshold in ns.
     */
    public void verifyFrequency(double expected, double threshold) {
        mVerifyFrequency = true;
        mFrequencyExpected = expected;
        mFrequencyThreshold = threshold;
    }

    /**
     * Set the default frequency verification depending on the sensor.
     * <p>
     * The expected frequency is based on {@link Sensor#getMinDelay()} and the threshold is
     * calculated based on a percentage of the expected frequency.  The verification will not be run
     * if the rate is set to {@link SensorManager#SENSOR_DELAY_GAME},
     * {@link SensorManager#SENSOR_DELAY_UI}, or {@link SensorManager#SENSOR_DELAY_NORMAL} because
     * these rates are not specified in the CDD.
     */
    @SuppressWarnings("deprecation")
    public void setDefaultVerifyFrequency() {
        if (!isRateValid()) {
            return;
        }

        // sensorType: threshold (% of expected frequency)
        Map<Integer, Integer> defaults = new HashMap<Integer, Integer>(12);
        // Sensors that we don't want to test at this time but still want to record the values.
        defaults.put(Sensor.TYPE_ACCELEROMETER, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_MAGNETIC_FIELD, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_GYROSCOPE, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_ORIENTATION, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_PRESSURE, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_GRAVITY, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_LINEAR_ACCELERATION, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_ROTATION_VECTOR, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_GAME_ROTATION_VECTOR, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, Integer.MAX_VALUE);

        if (defaults.containsKey(mSensorType)) {
            // Expected frequency in Hz
            double expected = SensorCtsHelper.getFrequency(
                    SensorCtsHelper.getDelay(mSensor.getUnderlyingSensor(), mRateUs),
                    TimeUnit.MICROSECONDS);
            // Expected frequency * threshold percentage
            double threshold = expected * defaults.get(mSensorType) / 100;
            verifyFrequency(expected, threshold);
        }
    }

    /**
     * Enable the jitter verification.
     * <p>
     * This test looks at the 95th percentile of the jitter and makes sure it is less than the
     * threshold percentage of the expected period.
     * </p>
     *
     * @param expected the expected period in ns.
     * @param threshold the theshold as a percentage of the expected period.
     */
    public void verifyJitter(int expected, int threshold) {
        mVerifyJitter = true;
        mJitterExpected = expected;
        mJitterThreshold = threshold;
    }

    /**
     * Set the default jitter verification based on the sensor type.
     * <p>
     * The verification will not be run if the rate is set to
     * {@link SensorManager#SENSOR_DELAY_GAME}, {@link SensorManager#SENSOR_DELAY_UI}, or
     * {@link SensorManager#SENSOR_DELAY_NORMAL} because these rates are not specified in the CDD.
     * </p>
     */
    @SuppressWarnings("deprecation")
    public void setDefaultVerifyJitter() {
        if (!isRateValid()) {
            return;
        }

        // sensorType: threshold (% of expected period)
        Map<Integer, Integer> defaults = new HashMap<Integer, Integer>(12);
        // Sensors that we don't want to test at this time but still want to record the values.
        defaults.put(Sensor.TYPE_ACCELEROMETER, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_MAGNETIC_FIELD, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_GYROSCOPE, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_ORIENTATION, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_PRESSURE, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_GRAVITY, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_LINEAR_ACCELERATION, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_ROTATION_VECTOR, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_GAME_ROTATION_VECTOR, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, Integer.MAX_VALUE);
        defaults.put(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, Integer.MAX_VALUE);

        if (defaults.containsKey(mSensorType)) {
            int expected = (int) TimeUnit.NANOSECONDS.convert(
                    SensorCtsHelper.getDelay(mSensor.getUnderlyingSensor(), mRateUs),
                    TimeUnit.MICROSECONDS);
            verifyJitter(expected, defaults.get(mSensorType));
        }
    }

    /**
     * Enable the mean verification.
     *
     * @param expected the expected means
     * @param threshold the threshold
     */
    public void verifyMean(float[] expected, float[] threshold) {
        mVerifyMean = true;
        mMeanExpected = expected;
        mMeanThreshold = threshold;
    }

    /**
     * Set the default mean verification based on sensor type.
     * <p>
     * This sets the mean expectations for a device at rest in a standard environment. For sensors
     * whose values vary depending on the orientation or environment, the expectations will not be
     * set.
     * </p><p>
     * The following expectations are set for these sensors:
     * </p><ul>
     * <li>Gyroscope: all values should be 0.</li>
     * <li>Pressure: values[0] should be close to the standard pressure.</li>
     * <li>Linear acceleration: all values should be 0.</li>
     * <li>Game rotation vector: all values should be 0 except values[3] which should be 1.</li>
     * <li>Uncalibrated gyroscope: all values should be 0.</li>
     * </ul>
     */
    @SuppressWarnings("deprecation")
    public void setDefaultVerifyMean() {
        // sensorType: {expected, threshold}
        Map<Integer, Object[]> defaults = new HashMap<Integer, Object[]>(5);
        // Sensors that we don't want to test at this time but still want to record the values.
        // Gyroscope should be 0 for a static device
        defaults.put(Sensor.TYPE_GYROSCOPE, new Object[]{
                new float[]{0.0f, 0.0f, 0.0f},
                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE}});
        // Pressure will not be exact in a controlled environment but should be relatively close to
        // sea level. Second values should always be 0.
        defaults.put(Sensor.TYPE_PRESSURE, new Object[]{
                new float[]{SensorManager.PRESSURE_STANDARD_ATMOSPHERE, 0.0f, 0.0f},
                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE}});
        // Linear acceleration should be 0 in all directions for a static device
        defaults.put(Sensor.TYPE_LINEAR_ACCELERATION, new Object[]{
                new float[]{0.0f, 0.0f, 0.0f},
                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE}});
        // Game rotation vector should be (0, 0, 0, 1, 0) for a static device
        defaults.put(Sensor.TYPE_GAME_ROTATION_VECTOR, new Object[]{
                new float[]{0.0f, 0.0f, 0.0f, 1.0f, 0.0f},
                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
                        Float.MAX_VALUE}});
        // Uncalibrated gyroscope should be 0 for a static device but allow a bigger threshold
        defaults.put(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, new Object[]{
                new float[]{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
                        Float.MAX_VALUE, Float.MAX_VALUE}});

        if (defaults.containsKey(mSensorType)) {
            float[] expected = (float[]) defaults.get(mSensorType)[0];
            float[] threshold = (float[]) defaults.get(mSensorType)[1];
            verifyMean(expected, threshold);
        }
    }

    /**
     * Enable the magnitude verification.
     *
     * @param expected the expected magnitude of the vector
     * @param threshold the threshold
     */
    public void verifyMagnitude(float expected, float threshold) {
        mVerifyMagnitude = true;
        mMagnitudeExpected = expected;
        mMagnitudeThreshold = threshold;
    }

    /**
     * Set the default magnitude verification base on the sensor type.
     * <p>
     * This sets the magnitude expectations for a device at rest in a standard environment. For
     * sensors whose values vary depending on the orientation or environment, the expectations will
     * not be set.
     * </p>
     */
    @SuppressWarnings("deprecation")
    public void setDefaultVerifyMagnitude() {
        // sensorType: {expected, threshold}
        Map<Integer, Float[]> defaults = new HashMap<Integer, Float[]>(3);
        defaults.put(Sensor.TYPE_ACCELEROMETER, new Float[]{SensorManager.STANDARD_GRAVITY, 1.5f});
        defaults.put(Sensor.TYPE_GYROSCOPE, new Float[]{0.0f, 1.5f});
        // Sensors that we don't want to test at this time but still want to record the values.
        defaults.put(Sensor.TYPE_GRAVITY,
                new Float[]{SensorManager.STANDARD_GRAVITY, Float.MAX_VALUE});

        if (defaults.containsKey(mSensorType)) {
            Float expected = defaults.get(mSensorType)[0];
            Float threshold = defaults.get(mSensorType)[1];
            verifyMagnitude(expected, threshold);
        }
    }

    /**
     * Enable the signum verification.
     *
     * @param expected the expected signs, an array of either -1s, 0s, or 1s.
     * @param threshold the threshold
     */
    public void verifySignum(int[] expected, float[] threshold) {
        mVerifySignum = true;
        mSignumExpected = expected;
        mSignumThreshold = threshold;
    }

    /**
     * Set the default signum verification base on the sensor type.
     * <p>
     * This is a no-op since currently all sensors which can specify a default sign can also specify
     * a default mean which is a more precise test.
     * </p>
     */
    public void setDefaultVerifySignum() {
        // No-op: All sensors that have an expected sign when static are already tested in
        // setDefaultVerifyMean().
    }

    /**
     * Enable the standard deviation verification.
     *
     * @param threshold the threshold.
     */
    public void verifyStandardDeviation(float[] threshold) {
        mVerifyStandardDeviation = true;
        mStandardDeviationThreshold = threshold;
    }

    /**
     * Set the default standard deviation verification based on the sensor type.
     */
    @SuppressWarnings("deprecation")
    public void setDefaultVerifyStandardDeviation() {
        // sensorType: threshold
        Map<Integer, float[]> defaults = new HashMap<Integer, float[]>(12);
        defaults.put(Sensor.TYPE_ACCELEROMETER, new float[]{1.0f, 1.0f, 1.0f});
        defaults.put(Sensor.TYPE_GYROSCOPE, new float[]{0.5f, 0.5f, 0.5f});
        // Sensors that we don't want to test at this time but still want to record the values.
        defaults.put(Sensor.TYPE_MAGNETIC_FIELD,
                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE});
        defaults.put(Sensor.TYPE_ORIENTATION,
                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE});
        defaults.put(Sensor.TYPE_PRESSURE,
                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE});
        defaults.put(Sensor.TYPE_GRAVITY,
                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE});
        defaults.put(Sensor.TYPE_LINEAR_ACCELERATION,
                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE});
        defaults.put(Sensor.TYPE_ROTATION_VECTOR,
                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
                Float.MAX_VALUE});
        defaults.put(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED,
                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
                Float.MAX_VALUE, Float.MAX_VALUE});
        defaults.put(Sensor.TYPE_GAME_ROTATION_VECTOR,
                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
                Float.MAX_VALUE});
        defaults.put(Sensor.TYPE_GYROSCOPE_UNCALIBRATED,
                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
                Float.MAX_VALUE, Float.MAX_VALUE});
        defaults.put(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR,
                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
                Float.MAX_VALUE});

        if (defaults.containsKey(mSensorType)) {
            float[] threshold = defaults.get(mSensorType);
            verifyStandardDeviation(threshold);
        }
    }

    /**
     * Collect the specified number of events from the sensor and run all enabled verifications.
     */
    @Override
    public void doWork() {
        TestSensorEvent[] events = mSensor.collectEvents(mEventCount);

        boolean failed = false;
        StringBuilder sb = new StringBuilder();
        VerificationResult result = null;
        Map<String, Object> stats = new HashMap<String, Object>();

        if (mVerifyEventOrdering) {
            result = SensorVerificationHelper.verifyEventOrdering(events);
            // evaluateResults first so it is always called.
            failed = evaluateResults(result, sb, stats) || failed;
        }

        if (mVerifyFrequency) {
            result = SensorVerificationHelper.verifyFrequency(events, mFrequencyExpected,
                    mFrequencyThreshold);
            failed = evaluateResults(result, sb, stats) || failed;
        }

        if (mVerifyJitter) {
            result = SensorVerificationHelper.verifyJitter(events, mJitterExpected,
                    mJitterThreshold);
            failed = evaluateResults(result, sb, stats) || failed;
        }

        if (mVerifyMean) {
            result = SensorVerificationHelper.verifyMean(events, mMeanExpected, mMeanThreshold);
            failed = evaluateResults(result, sb, stats) || failed;
        }

        if (mVerifyMagnitude) {
            result = SensorVerificationHelper.verifyMagnitude(events, mMagnitudeExpected,
                    mMagnitudeThreshold);
            failed = evaluateResults(result, sb, stats) || failed;
        }

        if (mVerifySignum) {
            result = SensorVerificationHelper.verifySignum(events, mSignumExpected,
                    mSignumThreshold);
            failed = evaluateResults(result, sb, stats) || failed;
        }

        if (mVerifyStandardDeviation) {
            result = SensorVerificationHelper.verifyStandardDeviation(events,
                    mStandardDeviationThreshold);
            failed = evaluateResults(result, sb, stats) || failed;
        }

        logStats(events, stats);

        if (failed) {
            Assert.fail(String.format("%s, handle %d: %s",
                    SensorTestInformation.getSensorName(mSensorType),
                    mSensor.getUnderlyingSensor().getHandle(), sb.toString()));
        }
    }

    /**
     * Return true if the operation rate is not one of {@link SensorManager#SENSOR_DELAY_GAME},
     * {@link SensorManager#SENSOR_DELAY_UI}, or {@link SensorManager#SENSOR_DELAY_NORMAL}.
     */
    private boolean isRateValid() {
        return (mRateUs != SensorManager.SENSOR_DELAY_GAME
                && mRateUs != SensorManager.SENSOR_DELAY_UI
                && mRateUs != SensorManager.SENSOR_DELAY_NORMAL);
    }

    /**
     * Evaluate the results of a test, aggregate the stats, and build the error message.
     */
    private boolean evaluateResults(VerificationResult result, StringBuilder sb,
            Map<String, Object> stats) {
        for (String key : result.getKeys()) {
            stats.put(key, result.getValue(key));
        }

        if (result.isFailed()) {
            if (sb.length() > 0) {
                sb.append(", ");
            }
            sb.append(result.getFailureMessage());
            return true;
        }
        return false;
    }

    /**
     * Log the stats to the logcat.
     */
    private void logStats(TestSensorEvent[] events, Map<String, Object> stats) {
        if (events.length <= 0) {
            return;
        }

        if (DEBUG) {
            List<Double> jitterValues = null;
            if (events.length > 1) {
                jitterValues = SensorCtsHelper.getJitterValues(events);
            }

            logTestSensorEvent(0, events[0], null, null);
            for (int i = 1; i < events.length; i++) {
                Double jitter = jitterValues == null ? null : jitterValues.get(i - 1);
                logTestSensorEvent(i, events[i], events[i - 1], jitter);
            }
        }

        List<String> keys = new ArrayList<String>(stats.keySet());
        Collections.sort(keys);
        Log.v(TAG, String.format("Stats for %s, handle %d:",
                SensorTestInformation.getSensorName(mSensorType),
                mSensor.getUnderlyingSensor().getHandle()));
        for (String key : keys) {
            Log.v(TAG, String.format("%s: %s", key, stats.get(key).toString()));
        }
    }

    /**
     * Log a single sensor event to the logcat.
     */
    private void logTestSensorEvent(int index, TestSensorEvent event, TestSensorEvent prevEvent,
            Double jitter) {
        String deltaStr = prevEvent == null ? null : String.format("%d",
                event.timestamp - prevEvent.timestamp);
        String jitterStr = jitter == null ? null : String.format("%.2f", jitter);

        StringBuilder valuesSb = new StringBuilder();
        if (event.values.length == 1) {
            valuesSb.append(String.format("%.2f", event.values[0]));
        } else {
            valuesSb.append("[").append(String.format("%.2f", event.values[0]));
            for (int i = 1; i < event.values.length; i++) {
                valuesSb.append(String.format(", %.2f", event.values[i]));
            }
            valuesSb.append("]");
        }

        Log.v(TAG, String.format(
                "Sensor %d: Event %d: device_timestamp=%d, delta_timestamp=%s, jitter=%s, "
                + "values=%s", mSensor.getUnderlyingSensor().getType(), index, event.timestamp,
                deltaStr, jitterStr, valuesSb.toString()));
    }
}
