/*
 * Copyright (C) 2015 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 org.drrickorang.loopback;

import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;


/**
 * This class is used to automatically estimate latency and its confidence.
 */

public class Correlation implements Parcelable {
    private static final String TAG = "Correlation";

    private int       mBlockSize = 4096;
    private int       mSamplingRate;
    private double [] mDataDownsampled = new double [mBlockSize];
    private double [] mDataAutocorrelated = new double[mBlockSize];

    public double mEstimatedLatencySamples = 0;
    public double mEstimatedLatencyMs = 0;
    public double mEstimatedLatencyConfidence = 0.0;
    public double mAverage = 0.0;
    public double mRms = 0.0;

    private double mAmplitudeThreshold = 0.001;  // 0.001 = -60 dB noise

    private boolean mDataIsValid = false; // Used to mark computed latency information is available

    public Correlation() {
        // Default constructor for when no data will be restored
    }

    public void init(int blockSize, int samplingRate) {
        mBlockSize = blockSize;
        mSamplingRate = samplingRate;
    }


    public void computeCorrelation(double [] data, int samplingRate) {
        log("Started Auto Correlation for data with " + data.length + " points");
        mSamplingRate = samplingRate;

        downsampleData(data, mDataDownsampled, mAmplitudeThreshold);

        //correlation vector
        autocorrelation(mDataDownsampled, mDataAutocorrelated);


        int N = data.length; //all samples available
        double groupSize =  (double) N / mBlockSize;  //samples per downsample point.

        double maxValue = 0;
        int maxIndex = -1;

        double minLatencyMs = 8; //min latency expected. This algorithm should be improved.
        int minIndex = (int) (0.5 + minLatencyMs * mSamplingRate / (groupSize * 1000));

        double average = 0;
        double rms = 0;

        //find max
        for (int i = minIndex; i < mDataAutocorrelated.length; i++) {
            average += mDataAutocorrelated[i];
            rms += mDataAutocorrelated[i] * mDataAutocorrelated[i];
           if (mDataAutocorrelated[i] > maxValue) {
               maxValue = mDataAutocorrelated[i];
               maxIndex = i;
           }
        }

        rms = Math.sqrt(rms / mDataAutocorrelated.length);
        average = average / mDataAutocorrelated.length;
        log(String.format(" Maxvalue %f, max Index : %d/%d (%d)  minIndex = %d", maxValue, maxIndex,
                          mDataAutocorrelated.length, data.length, minIndex));
        log(String.format("  average : %.3f  rms: %.3f", average, rms));

        mAverage = average;
        mRms = rms;

        mEstimatedLatencyConfidence = 0.0;
        if (average > 0) {
            double factor = 3.0;

            double raw = (rms - average) / (factor * average);
            log(String.format("Raw: %.3f", raw));
            mEstimatedLatencyConfidence = Math.max(Math.min(raw, 1.0), 0.0);
        }
        log(String.format(" ****Confidence: %.2f", mEstimatedLatencyConfidence));

        mEstimatedLatencySamples = maxIndex * groupSize;
        mEstimatedLatencyMs = mEstimatedLatencySamples * 1000 / mSamplingRate;
        log(String.format(" latencySamples: %.2f  %.2f ms", mEstimatedLatencySamples,
                          mEstimatedLatencyMs));

        mDataIsValid = mEstimatedLatencyMs > 0.0001;
    }

    // Called by LoopbackActivity before displaying latency test results
    public boolean isValid() {
        return mDataIsValid;
    }

    // Called at beginning of new test
    public void invalidate() {
        mDataIsValid = false;
    }

    private boolean downsampleData(double [] data, double [] dataDownsampled, double threshold) {

        boolean status;
        for (int i = 0; i < mBlockSize; i++) {
            dataDownsampled[i] = 0;
        }

        int N = data.length; //all samples available
        double groupSize =  (double) N / mBlockSize;

        int ignored = 0;

        int currentIndex = 0;
        double nextGroup = groupSize;
        for (int i = 0; i < N && currentIndex < mBlockSize; i++) {

            if (i > nextGroup) { //advanced to next group.
                currentIndex++;
                nextGroup += groupSize;
            }

            if (currentIndex >= mBlockSize) {
                break;
            }

            double value =  Math.abs(data[i]);
            if (value >= threshold) {
                dataDownsampled[currentIndex] += value;
            } else {
                ignored++;
            }
        }

        log(String.format(" Threshold: %.3f, ignored:%d/%d (%%.2f)",
                threshold, ignored, N, (double) ignored/(double)N));

        status = true;
        return status;
    }


    private boolean autocorrelation(double [] data, double [] dataOut) {
        boolean status = false;

        double sumsquared = 0;
        int N = data.length;
        for (int i = 0; i < N; i++) {
            double value = data[i];
            sumsquared += value * value;
        }

        if (sumsquared > 0) {
            //correlate (not circular correlation)
            for (int i = 0; i < N; i++) {
                dataOut[i] = 0;
                for (int j = 0; j < N - i; j++) {

                    dataOut[i] += data[j] * data[i + j];
                }
                dataOut[i] = dataOut[i] / sumsquared;
            }
            status = true;
        }

        return status;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    // Store the results before this object is destroyed
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        Bundle bundle = new Bundle();
        bundle.putBoolean("mDataIsValid", mDataIsValid);
        if(mDataIsValid) {
            bundle.putDouble("mEstimatedLatencySamples", mEstimatedLatencySamples);
            bundle.putDouble("mEstimatedLatencyMs", mEstimatedLatencyMs);
            bundle.putDouble("mEstimatedLatencyConfidence", mEstimatedLatencyConfidence);
            bundle.putDouble("mAverage", mAverage);
            bundle.putDouble("mRms", mRms);
        }
        dest.writeBundle(bundle);
    }

    // Restore the results which were previously calculated
    private Correlation(Parcel in) {
        Bundle bundle = in.readBundle(getClass().getClassLoader());
        mDataIsValid = bundle.getBoolean("mDataIsValid");
        if(mDataIsValid) {
            mEstimatedLatencySamples    = bundle.getDouble("mEstimatedLatencySamples");
            mEstimatedLatencyMs         = bundle.getDouble("mEstimatedLatencyMs");
            mEstimatedLatencyConfidence = bundle.getDouble("mEstimatedLatencyConfidence");
            mAverage                    = bundle.getDouble("mAverage");
            mRms                        = bundle.getDouble("mRms");
        }
    }

    public static final Parcelable.Creator<Correlation> CREATOR
            = new Parcelable.Creator<Correlation>() {
        public Correlation createFromParcel(Parcel in) {
            return new Correlation(in);
        }

        public Correlation[] newArray(int size) {
            return new Correlation[size];
        }
    };

    private static void log(String msg) {
        Log.v(TAG, msg);
    }
}
