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

import android.content.Context;
import android.content.pm.PackageManager;

import android.util.Log;
import android.hardware.Sensor;
import android.hardware.cts.helpers.SensorCtsHelper;
import android.hardware.cts.helpers.SensorStats;
import android.hardware.cts.helpers.TestSensorEnvironment;
import android.hardware.cts.helpers.TestSensorEvent;
import android.util.SparseIntArray;

import com.android.cts.util.StatisticsUtils;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import junit.framework.Assert;

/**
 * A {@link ISensorVerification} which verifies that the sensor jitter is in an acceptable range.
 */
public class JitterVerification extends AbstractSensorVerification {
    public static final String PASSED_KEY = "jitter_passed";

    // sensorType: threshold (% of expected period)
    private static final SparseIntArray DEFAULTS = new SparseIntArray(12);
    // Max allowed jitter in +/- sense (in percentage).
    private static final int GRACE_FACTOR = 2;
    private static final int THRESHOLD_PERCENT_FOR_HIFI_SENSORS = 1 * GRACE_FACTOR;

    // Margin sample intervals that considered outliers, lower and higher margin is discarded
    // before verification
    private static final float OUTLIER_MARGIN = 0.025f; //2.5%

    static {
        // Use a method so that the @deprecation warning can be set for that method only
        setDefaults();
    }

    private final float     mOutlierMargin;
    private final long      mThresholdNs;
    private final long      mExpectedPeriodNs; // for error message only
    private final List<Long> mTimestamps = new LinkedList<Long>();

    /**
     * Construct a {@link JitterVerification}
     *
     * @param thresholdAsPercentage the acceptable margin of error as a percentage
     */
    public JitterVerification(float outlierMargin, long thresholdNs, long expectedPeriodNs) {
        mExpectedPeriodNs = expectedPeriodNs;
        mOutlierMargin = outlierMargin;
        mThresholdNs = thresholdNs;
    }

    /**
     * Get the default {@link JitterVerification} for a sensor.
     *
     * @param environment the test environment
     * @return the verification or null if the verification does not apply to the sensor.
     */
    public static JitterVerification getDefault(TestSensorEnvironment environment) {
        int sensorType = environment.getSensor().getType();

        int thresholdPercent = DEFAULTS.get(sensorType, -1);
        if (thresholdPercent == -1) {
            return null;
        }
        boolean hasHifiSensors = environment.getContext().getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_HIFI_SENSORS);
        if (hasHifiSensors) {
           thresholdPercent = THRESHOLD_PERCENT_FOR_HIFI_SENSORS;
        }

        long expectedPeriodNs = (long) environment.getExpectedSamplingPeriodUs() * 1000;
        long jitterThresholdNs = expectedPeriodNs * thresholdPercent * 2 / 100; // *2 is for +/-
        return new JitterVerification(OUTLIER_MARGIN, jitterThresholdNs, expectedPeriodNs);
    }

    /**
     * Verify that the 95th percentile of the jitter is in the acceptable range. Add
     * {@value #PASSED_KEY} and {@value SensorStats#JITTER_95_PERCENTILE_PERCENT_KEY} keys to
     * {@link SensorStats}.
     *
     * @throws AssertionError if the verification failed.
     */
    @Override
    public void verify(TestSensorEnvironment environment, SensorStats stats) {
        int timestampsCount = mTimestamps.size();
        if (timestampsCount < 2 || environment.isSensorSamplingRateOverloaded()) {
            // the verification is not reliable in environments under load
            stats.addValue(PASSED_KEY, true);
            return;
        }

        List<Long> deltas = getDeltaValues();
        float percentiles[] = new float[2];
        percentiles[0] = mOutlierMargin;
        percentiles[1] = 1 - percentiles[0];

        List<Long> percentileValues = SensorCtsHelper.getPercentileValue(deltas, percentiles);
        double normalizedRange =
                (double)(percentileValues.get(1) - percentileValues.get(0)) / mThresholdNs;

        double percentageJitter =
                (double)(percentileValues.get(1) - percentileValues.get(0)) /
                        mExpectedPeriodNs / 2 * 100; //one side variation comparing to sample time

        stats.addValue(SensorStats.JITTER_95_PERCENTILE_PERCENT_KEY, percentageJitter);

        boolean success = normalizedRange <= 1.0;
        stats.addValue(PASSED_KEY, success);

        if (!success) {
            String message = String.format(
                    "Jitter out of range: requested period = %dns, " +
                    "jitter min, max, range (95th percentile) = (%dns, %dns, %dns), " +
                    "jitter expected range <= %dns",
                    mExpectedPeriodNs,
                    percentileValues.get(0), percentileValues.get(1),
                    percentileValues.get(1) - percentileValues.get(0),
                    mThresholdNs);
            Assert.fail(message);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public JitterVerification clone() {
        return new JitterVerification(mOutlierMargin, mThresholdNs, mExpectedPeriodNs);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void addSensorEventInternal(TestSensorEvent event) {
        mTimestamps.add(event.timestamp);
    }

    /**
     * Get the list of delta values. Exposed for unit testing.
     */
    List<Long> getDeltaValues() {
        List<Long> deltas = new ArrayList<Long>(mTimestamps.size() - 1);
        for (int i = 1; i < mTimestamps.size(); i++) {
            deltas.add(mTimestamps.get(i) - mTimestamps.get(i - 1));
        }
        return deltas;
    }

    @SuppressWarnings("deprecation")
    private static void setDefaults() {
        DEFAULTS.put(Sensor.TYPE_ACCELEROMETER, Integer.MAX_VALUE);
        DEFAULTS.put(Sensor.TYPE_MAGNETIC_FIELD, Integer.MAX_VALUE);
        DEFAULTS.put(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, Integer.MAX_VALUE);
        DEFAULTS.put(Sensor.TYPE_GYROSCOPE, Integer.MAX_VALUE);
        DEFAULTS.put(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, 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_GAME_ROTATION_VECTOR, Integer.MAX_VALUE);
        DEFAULTS.put(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, Integer.MAX_VALUE);
    }
}
