/*
 * Copyright 2012 Mark Injerd
 *
 * 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 com.pilot51.voicenotify;

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

public class Shake implements SensorEventListener {
	private final Context context;
	private final SensorManager manager;
	private final Sensor sensor;
	private OnShakeListener listener;
	private int threshold;
	private float accel, accelCurrent, accelLast;
	
	Shake(Context c) {
		context = c;
		manager = (SensorManager)c.getSystemService(Context.SENSOR_SERVICE);
		sensor = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
	}
	
	void enable() {
		if (listener == null) return;
		try {
			threshold = Integer.parseInt(Common.getPrefs(context).getString(context.getString(R.string.key_shake_threshold), null));
		} catch (NumberFormatException e) {
			// Don't enable if threshold setting is blank
			return;
		}
		manager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL);
		accelCurrent = SensorManager.GRAVITY_EARTH;
		accelLast = SensorManager.GRAVITY_EARTH;
	}
	
	void disable() {
		manager.unregisterListener(this);
	}
	
	void setOnShakeListener(OnShakeListener listener) {
		this.listener = listener;
	}
	
	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {}
	
	@Override
	public void onSensorChanged(SensorEvent event) {
		float x = event.values[0];
		float y = event.values[1];
		float z = event.values[2];
		accelCurrent = (float)Math.sqrt(x * x + y * y + z * z);
		accel = accel * 0.9f + accelCurrent - accelLast;
		if (Math.abs(accel) > threshold / 10) {
			listener.onShake();
		}
		accelLast = accelCurrent;
	}
	
	interface OnShakeListener {
		void onShake();
	}
}

@@ -1018,16 +1018,36 @@
 hreshold
+, overThresholdCount
 ;%0A%09priva
@@ -1058,15 +1058,8 @@
 loat
- accel,
  acc
@@ -1622,153 +1622,127 @@
 );%0A%09
-%09accelCurrent = SensorManager.GRAVITY_EARTH;%0A%09%09accelLast = SensorManager.GRAVITY_EARTH;%0A%09%7D%0A%09%0A%09void disable() %7B%0A%09%09manager.unregisterListener(this)
+%7D%0A%09%0A%09void disable() %7B%0A%09%09manager.unregisterListener(this);%0A%09%09accelCurrent = 0;%0A%09%09accelLast = 0;%0A%09%09overThresholdCount = 0
 ;%0A%09%7D
@@ -2118,30 +2118,21 @@
 ;%0A%09%09
+float 
 accel =
- accel * 0.9f +
  acc
@@ -2160,16 +2160,34 @@
 ;%0A%09%09if (
+accelLast != 0 && 
 Math.abs
@@ -2221,26 +2221,129 @@
 %0A%09%09%09
-listener.onShake()
+overThresholdCount++;%0A%09%09%09if (overThresholdCount %3E= 2) %7B%0A%09%09%09%09listener.onShake();%0A%09%09%09%7D%0A%09%09%7D else %7B%0A%09%09%09overThresholdCount = 0
 ;%0A%09%09

Fix issue #24: Shake-To-Silence silencing future notifications.