package net.heartshield.sensors;

import android.util.Log;

import net.heartshield.data.WavData;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

/**
 * Time series signal handling (with ArrayList-like automatic array memory management).
 *
 * Builds a WAV file in memory.
 *
 * @author David Madl (git@abanbytes.eu)
 * @date 2016-03-31
 */
public class SensorDataPCM {
    /**
     * Note that backing arrays may be longer than the actual data contained.
     */
    private byte[] mBytes;

    /** actual number of bytes */
    private int mLength;

    private double mStartTime;

    private static final int START_BUF_SIZE = 1;

    SensorDataPCM() {
        clear();
    }

    public void setStartTime(double startTime) {
        mStartTime = startTime;
    }

    public double getStartTime() { return mStartTime; }

    /**
     * To save RAM, this method returns the underlying buffer - it does NOT deep-copy.
     */
    synchronized ByteBuffer getData() {
        /*
        // deep copy to return the actual amount of bytes
        byte[] arr = new byte[mLength];
        System.arraycopy(mBytes, 0, arr, 0, mLength);
        return arr;
        */

        return ByteBuffer.wrap(mBytes, 0, mLength);
    }

    /** @return number of bytes, including WAV header data */
    synchronized int length() { return mLength; }

    /** @return number of bytes of actual PCM data, without WAV header */
    synchronized int bodyLength() { return mLength - WavData.HEADER_SIZE; }

    private void extendIfNeeded(int writeIndex) {
        int oldLength = mBytes.length;
        if(writeIndex < oldLength)
            return;

        int newLength = oldLength;
        while(newLength <= writeIndex)
            newLength *= 2;

        byte[] newBytes = new byte[newLength];
        //Log.i("SensorDataPCM", "extendIfNeeded(writeIndex=" + writeIndex + ") of oldLength=" + oldLength + " to newLength=" + newLength + " so copying over " + mLength + " old mLength bytes.");
        System.arraycopy(mBytes, 0, newBytes, 0, mLength);
        mBytes = newBytes;
    }

    /*synchronized void addData(byte[] data) {
        extendIfNeeded(mLength + data.length);
        System.arraycopy(data, 0, mBytes, mLength, data.length);
        mLength += data.length;
    }*/

    synchronized void addData(ByteBuffer data, int nbytes) {
        extendIfNeeded(mLength + nbytes);
        data.rewind();
        data.get(mBytes, mLength, nbytes);
        mLength += nbytes;
    }

    synchronized void clear() {
        // implicitly reserve WavData header space in the front
        // note: ugly, and could be reversed and AudioSensor.getPCM() adapted instead.
        mLength = WavData.HEADER_SIZE;
        mBytes = new byte[WavData.HEADER_SIZE + START_BUF_SIZE];
        mStartTime = 0;
    }
}
