package com.koeping.lukas.sensordatacollector;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;

/**
 * Created by lukas on 18.01.16.
 */
public class SensorDataCollector implements SensorEventListener
{
    private SensorManager sensorManager;
    private final int SENSOR_DELAY = SensorManager.SENSOR_DELAY_FASTEST;
    private SensorDataWriter dataWriter;
    private long startTime;



    public SensorDataCollector(SensorDataWriter sdw, SensorManager sensorManager, long startTime) {
        this.sensorManager = sensorManager;
        initSensors();
        this.startTime = startTime;
        this.dataWriter = sdw;
    }

    private void initSensors() {
        Sensors[] allSensors = Sensors.values();

        for(int i = 0; i < Sensors.values().length; i++) {
            allSensors[i].setSensor(sensorManager.getDefaultSensor(allSensors[i].getSensorType()));
            sensorManager.registerListener(this, allSensors[i].getSensor(), SENSOR_DELAY);
        }
    }


    private float[] getSensorData(Sensors sensor, SensorEvent event) {
        int nValues = sensor.getNValues();
        int pos = sensor.getPos();
        float[] data = new float[nValues];
        System.arraycopy(event.values, 0, data, 0, nValues);

        return data;
    }

    private float[] getRotationMatrix(float[] gravity, float[] magnetic) {
        float[] rotation = new float[16];
        float[] inclination = new float[16];
        sensorManager.getRotationMatrix(rotation, inclination, gravity, magnetic);

        return rotation;
    }

    private float[] getOrientations(float[] rotation_Matrix) {
        float[] values = new float[3];
        values = sensorManager.getOrientation(rotation_Matrix, values);

        return values;
    }

    private void receiveAndWrite(Sensors sensor, SensorEvent event) {
        float[] data = getSensorData(sensor, event);
        sensor.setData(data);
        long timestamp = System.currentTimeMillis() - startTime;
        dataWriter.writeDataToFile(sensor, timestamp, data);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {

        if(dataWriter != null)
            recordData(event);
    }


    private void recordData(SensorEvent event) {

        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
            receiveAndWrite(Sensors.ACCELEROMETER, event);
        }

        if (event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION) {
            receiveAndWrite(Sensors.LINEAR_ACCELEROMETER, event);
        }

        if (event.sensor.getType() == Sensor.TYPE_GRAVITY) {
            receiveAndWrite(Sensors.GRAVITY, event);
            long timestamp = System.currentTimeMillis() - startTime;

            if (Sensors.MAGNETOMETER.getData() != null) {
                float[] data = getRotationMatrix(Sensors.GRAVITY.getData(), Sensors.MAGNETOMETER.getData());
                Sensors.ROTATION_MATRIX.setData(data);
                dataWriter.writeDataToFile(Sensors.ROTATION_MATRIX, timestamp, data);

                data = getOrientations(Sensors.ROTATION_MATRIX.getData());
                Sensors.ORIENTATION.setData(data);
                dataWriter.writeDataToFile(Sensors.ORIENTATION, timestamp, data);
            }

        }

        if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
            receiveAndWrite(Sensors.GYROSCOPE, event);
        }

        if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
            receiveAndWrite(Sensors.MAGNETOMETER, event);
        }

        if (event.sensor.getType() == Sensor.TYPE_PRESSURE) {
            receiveAndWrite(Sensors.BAROMETER, event);
        }

    }


    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        //Nothing to be done here
    }












}
