CB-8876 Rewrote wp8 impementation to be more stable
diff --git a/src/wp/Accelerometer.cs b/src/wp/Accelerometer.cs
index cba911c..33c5434 100644
--- a/src/wp/Accelerometer.cs
+++ b/src/wp/Accelerometer.cs
@@ -1,4 +1,4 @@
-/*  
+/*
 	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
@@ -20,6 +20,7 @@
 using Microsoft.Devices.Sensors;
 using System.Globalization;
 using System.Diagnostics;
+using System.Windows.Threading;
 
 namespace WPCordovaClassLib.Cordova.Commands
 {
@@ -28,47 +29,6 @@
     /// </summary>
     public class Accelerometer : BaseCommand
     {
-        #region AccelerometerOptions class
-        /// <summary>
-        /// Represents Accelerometer options.
-        /// </summary>
-        [DataContract]
-        public class AccelerometerOptions
-        {
-            /// <summary>
-            /// How often to retrieve the Acceleration in milliseconds
-            /// </summary>
-            [DataMember(IsRequired = false, Name = "frequency")]
-            public int Frequency { get; set; }
-
-            /// <summary>
-            /// Watcher id
-            /// </summary>
-            [DataMember(IsRequired = false, Name = "id")]
-            public string Id { get; set; }
-
-            /// <summary>
-            /// Creates options object with default parameters
-            /// </summary>
-            public AccelerometerOptions()
-            {
-                this.SetDefaultValues(new StreamingContext());
-            }
-
-            /// <summary>
-            /// Initializes default values for class fields.
-            /// Implemented in separate method because default constructor is not invoked during deserialization.
-            /// </summary>
-            /// <param name="context"></param>
-            [OnDeserializing()]
-            public void SetDefaultValues(StreamingContext context)
-            {
-                this.Frequency = 10000;
-            }
-        }
-
-        #endregion
-
         #region Status codes and Constants
 
         public const int Stopped = 0;
@@ -90,23 +50,19 @@
         /// <summary>
         /// Accelerometer
         /// </summary>
-        private static Microsoft.Devices.Sensors.Accelerometer accelerometer = new Microsoft.Devices.Sensors.Accelerometer();
-
-        private static DateTime StartOfEpoch = new DateTime(1970, 1, 1, 0, 0, 0);
-
-        #endregion
+        private static readonly Windows.Devices.Sensors.Accelerometer accelerometer = Windows.Devices.Sensors.Accelerometer.GetDefault();
 
         /// <summary>
-        /// Sensor listener event
-        /// </summary>        
-        private void accelerometer_CurrentValueChanged(object sender, SensorReadingEventArgs<AccelerometerReading> e)
-        {
-            this.SetStatus(Running);
+        /// Timer which is used to update
+        /// </summary>
+        private static Timer updateTimer;
 
-            PluginResult result = new PluginResult(PluginResult.Status.OK, GetCurrentAccelerationFormatted());
-            result.KeepCallback = true;
-            DispatchCommandResult(result);
-        }
+        /// <summary>
+        /// Callback Id to report acceleration result in watch mode
+        /// </summary>
+        private static string watchCallbackId;
+ 
+        #endregion
 
         /// <summary>
         /// Starts listening for acceleration sensor
@@ -114,56 +70,64 @@
         /// <returns>status of listener</returns>
         public void start(string options)
         {
-            if ((currentStatus == Running) || (currentStatus == Starting))
+            watchCallbackId = GetCallbackIdFromOptions(options);
+
+            if (currentStatus == Running)
             {
                 return;
             }
+
             try
             {
-                lock (accelerometer)
-                {
-                    accelerometer.CurrentValueChanged += accelerometer_CurrentValueChanged;
-                    accelerometer.Start();
-                    this.SetStatus(Starting);
-                }
+                // we use 20ms as a minimum allowed update interval
+                int minReportInterval = Math.Max((int)accelerometer.MinimumReportInterval, 20);
 
-                long timeout = 2000;
-                while ((currentStatus == Starting) && (timeout > 0))
-                {
-                    timeout = timeout - 100;
-                    Thread.Sleep(100);
-                }
+                updateTimer = new Timer(ReportAccelerationValue, null, 0, minReportInterval);
+                this.SetStatus(Running);
 
-                if (currentStatus != Running)
-                {
-                    this.SetStatus(ErrorFailedToStart);
-                    DispatchCommandResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, ErrorFailedToStart));
-                    return;
-                }
+                PluginResult result = new PluginResult(PluginResult.Status.OK, GetCurrentAccelerationFormatted());
+                result.KeepCallback = true;
+                DispatchCommandResult(result, watchCallbackId);
             }
-            catch (Exception)
+            catch (Exception ex)
             {
                 this.SetStatus(ErrorFailedToStart);
-                DispatchCommandResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, ErrorFailedToStart));
-                return;
+                DispatchCommandResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, ErrorFailedToStart), watchCallbackId);
             }
-            PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
-            result.KeepCallback = true;
-            DispatchCommandResult(result);
         }
 
         public void stop(string options)
         {
+            string callbackId = GetCallbackIdFromOptions(options);
+
             if (currentStatus == Running)
             {
-                lock (accelerometer)
-                {
-                    accelerometer.CurrentValueChanged -= accelerometer_CurrentValueChanged;
-                    accelerometer.Stop();
-                    this.SetStatus(Stopped);
-                }
+                watchCallbackId = null;
+                updateTimer.Dispose();
+                this.SetStatus(Stopped);
             }
-            DispatchCommandResult(new PluginResult(PluginResult.Status.OK));
+
+            DispatchCommandResult(new PluginResult(PluginResult.Status.OK), callbackId);
+        }
+
+        public void getCurrentAcceleration(string options)
+        {
+            string callbackId = GetCallbackIdFromOptions(options);
+
+            DispatchCommandResult(new PluginResult(PluginResult.Status.OK, GetCurrentAccelerationFormatted()), callbackId);
+        }
+
+        private void ReportAccelerationValue(object stateInfo)
+        {
+            if (String.IsNullOrEmpty(watchCallbackId)) {
+                // soemthing goes wrong, callback has been called after stop..
+                return;
+            }
+            string currentAccelerationFormatted = GetCurrentAccelerationFormatted();
+            var result = currentAccelerationFormatted == null ? new PluginResult(PluginResult.Status.NO_RESULT)
+                                                              : new PluginResult(PluginResult.Status.OK, currentAccelerationFormatted);
+            result.KeepCallback = true;
+            DispatchCommandResult(result, watchCallbackId);
         }
 
         /// <summary>
@@ -172,15 +136,20 @@
         /// <returns>Coordinates in JSON format</returns>
         private string GetCurrentAccelerationFormatted()
         {
-            // convert to unix timestamp
-            // long timestamp = ((accelerometer.CurrentValue.Timestamp.DateTime - StartOfEpoch).Ticks) / 10000;
-            // Note: Removed timestamp, to let the JS side create it using (new Date().getTime()) -jm
-            // this resolves an issue with inconsistencies between JS dates and Native DateTime 
-            string resultCoordinates = String.Format("\"x\":{0},\"y\":{1},\"z\":{2}",
-                            (accelerometer.CurrentValue.Acceleration.X * gConstant).ToString("0.00000", CultureInfo.InvariantCulture),
-                            (accelerometer.CurrentValue.Acceleration.Y * gConstant).ToString("0.00000", CultureInfo.InvariantCulture),
-                            (accelerometer.CurrentValue.Acceleration.Z * gConstant).ToString("0.00000", CultureInfo.InvariantCulture));
-            return  "{" + resultCoordinates + "}";
+            try
+            {
+                var currentReading = accelerometer.GetCurrentReading();
+                var currentCoordinates = String.Format("\"x\":{0},\"y\":{1},\"z\":{2}",
+                                (currentReading.AccelerationX * gConstant).ToString("0.00000", CultureInfo.InvariantCulture),
+                                (currentReading.AccelerationY * gConstant).ToString("0.00000", CultureInfo.InvariantCulture),
+                                (currentReading.AccelerationZ * gConstant).ToString("0.00000", CultureInfo.InvariantCulture));
+
+                return "{" + currentCoordinates + "}";
+            }
+            catch
+            {
+                return null;
+            }
         }
 
         /// <summary>
@@ -191,6 +160,20 @@
         {
             currentStatus = status;
         }
+
+        private string GetCallbackIdFromOptions(string options)
+        {
+            try
+            {
+                string[] optionsString = JSON.JsonHelper.Deserialize<string[]>(options);
+
+                return optionsString[0];
+            }
+            catch (Exception)
+            {
+                DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), this.CurrentCommandCallbackId);
+                return null;
+            }
+        }
     }
 }
-
diff --git a/www/accelerometer.js b/www/accelerometer.js
index b6e9f97..900899c 100644
--- a/www/accelerometer.js
+++ b/www/accelerometer.js
@@ -42,13 +42,13 @@
 
 // Tells native to start.
 function start() {
-    exec(function(a) {
+    exec(function (a) {
         var tempListeners = listeners.slice(0);
         accel = new Acceleration(a.x, a.y, a.z, a.timestamp);
         for (var i = 0, l = tempListeners.length; i < l; i++) {
             tempListeners[i].win(accel);
         }
-    }, function(e) {
+    }, function (e) {
         var tempListeners = listeners.slice(0);
         for (var i = 0, l = tempListeners.length; i < l; i++) {
             tempListeners[i].fail(e);
@@ -60,12 +60,13 @@
 // Tells native to stop.
 function stop() {
     exec(null, null, "Accelerometer", "stop", []);
+    accel = null;
     running = false;
 }
 
 // Adds a callback pair to the listeners array
 function createCallbackPair(win, fail) {
-    return {win:win, fail:fail};
+    return { win: win, fail: fail };
 }
 
 // Removes a win/fail listener pair from the listeners array
@@ -87,15 +88,26 @@
      * @param {Function} errorCallback      The function to call when there is an error getting the acceleration data. (OPTIONAL)
      * @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. (OPTIONAL)
      */
-    getCurrentAcceleration: function(successCallback, errorCallback, options) {
+    getCurrentAcceleration: function (successCallback, errorCallback, options) {
         argscheck.checkArgs('fFO', 'accelerometer.getCurrentAcceleration', arguments);
 
+        if (cordova.platformId === "windowsphone") {
+            exec(function (a) {
+                accel = new Acceleration(a.x, a.y, a.z, a.timestamp);
+                successCallback(accel);
+            }, function (e) {
+                errorCallback(e);
+            }, "Accelerometer", "getCurrentAcceleration", []);
+
+            return;
+        }
+
         var p;
-        var win = function(a) {
+        var win = function (a) {
             removeListeners(p);
             successCallback(a);
         };
-        var fail = function(e) {
+        var fail = function (e) {
             removeListeners(p);
             errorCallback && errorCallback(e);
         };
@@ -116,7 +128,7 @@
      * @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. (OPTIONAL)
      * @return String                       The watch id that must be passed to #clearWatch to stop watching.
      */
-    watchAcceleration: function(successCallback, errorCallback, options) {
+    watchAcceleration: function (successCallback, errorCallback, options) {
         argscheck.checkArgs('fFO', 'accelerometer.watchAcceleration', arguments);
         // Default interval (10 sec)
         var frequency = (options && options.frequency && typeof options.frequency == 'number') ? options.frequency : 10000;
@@ -124,19 +136,19 @@
         // Keep reference to watch id, and report accel readings as often as defined in frequency
         var id = utils.createUUID();
 
-        var p = createCallbackPair(function(){}, function(e) {
+        var p = createCallbackPair(function () { }, function (e) {
             removeListeners(p);
             errorCallback && errorCallback(e);
         });
         listeners.push(p);
 
         timers[id] = {
-            timer:window.setInterval(function() {
+            timer: window.setInterval(function () {
                 if (accel) {
                     successCallback(accel);
                 }
             }, frequency),
-            listeners:p
+            listeners: p
         };
 
         if (running) {
@@ -157,7 +169,7 @@
      *
      * @param {String} id       The id of the watch returned from #watchAcceleration.
      */
-    clearWatch: function(id) {
+    clearWatch: function (id) {
         // Stop javascript timer & remove from timer list
         if (id && timers[id]) {
             window.clearInterval(timers[id].timer);