package org.exarhteam.iitc_mobile.compass;

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

public class AccMagCompass extends Compass {
    private static final double SENSOR_DELAY_USER = 100 * 1e6; // 100 milliseconds

    private final Context mContext;
    private long mLastUpdate = 0;
    private final SensorListener mListener = new SensorListener();
    private final float[] mOrientation = new float[3];
    private final float[] mRotationMatrix = new float[9];
    private final Sensor mSensorAcc, mSensorMag;
    private final SensorManager mSensorManager;
    private float[] mValuesAcc = null, mValuesMag = null;

    public AccMagCompass(final Context context) {
        mContext = context;

        mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);

        mSensorAcc = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mSensorMag = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
    }

    private void calculateOrientation() {

        // wait until both sensors have given us an event
        if (mValuesAcc == null || mValuesMag == null) return;

        if (!SensorManager.getRotationMatrix(mRotationMatrix, null, mValuesAcc, mValuesMag)) return;
        SensorManager.getOrientation(mRotationMatrix, mOrientation);

        publishOrientation(mOrientation[0], mOrientation[1], mOrientation[2]);
    }

    @Override
    protected void onStart() {
        mSensorManager.registerListener(mListener, mSensorAcc, SensorManager.SENSOR_DELAY_NORMAL);
        mSensorManager.registerListener(mListener, mSensorMag, SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    protected void onStop() {
        mSensorManager.unregisterListener(mListener);
    }

    private class SensorListener implements SensorEventListener {
        @Override
        public void onAccuracyChanged(final Sensor sensor, final int accuracy) {
        }

        @Override
        public void onSensorChanged(final SensorEvent event) {
            switch (event.sensor.getType()) {
                case Sensor.TYPE_ACCELEROMETER:
                    mValuesAcc = event.values;
                    break;
                case Sensor.TYPE_MAGNETIC_FIELD:
                    mValuesMag = event.values;

                    // save some battery, 10 updates per second should be enough
                    if ((event.timestamp - mLastUpdate) < SENSOR_DELAY_USER) break;
                    mLastUpdate = event.timestamp;

                    calculateOrientation();
            }
        }
    }
}
