﻿/*  
	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.
*/

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using DeviceCompass = Microsoft.Devices.Sensors.Compass;
using System.Windows.Threading;
using System.Runtime.Serialization;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Threading;
using Microsoft.Devices.Sensors;

namespace WP7CordovaClassLib.Cordova.Commands
{

    public class Compass : BaseCommand
    {
        #region Static members

        /// <summary>
        /// Status of listener
        /// </summary>
        private static int currentStatus;

        /// <summary>
        /// Id for get getCompass method
        /// </summary>
        private static string getCompassId = "getCompassId";

        /// <summary>
        /// Compass
        /// </summary>
        private static DeviceCompass compass = new DeviceCompass();

        /// <summary>
        /// Listeners for callbacks
        /// </summary>
        private static Dictionary<string, Compass> watchers = new Dictionary<string, Compass>();

        #endregion

        #region Status codes

        public const int Stopped = 0;
        public const int Starting = 1;
        public const int Running = 2;
        public const int ErrorFailedToStart = 4;
        public const int Not_Supported = 20;

        /*
         *   // Capture error codes
            CompassError.COMPASS_INTERNAL_ERR = 0;
            CompassError.COMPASS_NOT_SUPPORTED = 20;
         * */

        #endregion

        #region CompassOptions class
        /// <summary>
        /// Represents Accelerometer options.
        /// </summary>
        [DataContract]
        public class CompassOptions
        {
            /// <summary>
            /// How often to retrieve the Acceleration in milliseconds
            /// </summary>
            [DataMember(IsRequired = false, Name = "frequency")]
            public int Frequency { get; set; }

            /// <summary>
            /// The change in degrees required to initiate a watchHeadingFilter success callback.
            /// </summary>
            [DataMember(IsRequired = false, Name = "filter")]
            public int Filter { get; set; }

            /// <summary>
            /// Watcher id
            /// </summary>
            [DataMember(IsRequired = false, Name = "id")]
            public string Id { get; set; }

        }
        #endregion


        /// <summary>
        /// Time the value was last changed
        /// </summary>
        //private DateTime lastValueChangedTime;

        /// <summary>
        /// Accelerometer options
        /// </summary>
        private CompassOptions compassOptions;

        //bool isDataValid;

        //bool calibrating = false;

        public Compass()
        {

        }

        /// <summary>
        /// Formats current coordinates into JSON format
        /// </summary>
        /// <returns>Coordinates in JSON format</returns>
        private string GetHeadingFormatted(CompassReading reading)
        {
            string result = String.Format("\"magneticHeading\":{0},\"headingAccuracy\":{1},\"trueHeading\":{2},\"timestamp\":{3}",
                            reading.MagneticHeading.ToString("0.0", CultureInfo.InvariantCulture),
                            reading.HeadingAccuracy.ToString("0.0", CultureInfo.InvariantCulture),
                            reading.TrueHeading.ToString("0.0", CultureInfo.InvariantCulture),
                            reading.Timestamp.UtcTicks.ToString());
            result = "{" + result + "}";
            return result;
        }

        public void getHeading(string options)
        {
            if (!DeviceCompass.IsSupported)
            {
                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "{code:" + Not_Supported + "}"));
            }
            else
            {
                //if (compass == null)
                //{
                //    // Instantiate the compass.
                //    compass = new DeviceCompass();
                //    compass.TimeBetweenUpdates = TimeSpan.FromMilliseconds(40);
                //    compass.CurrentValueChanged += new EventHandler<Microsoft.Devices.Sensors.SensorReadingEventArgs<Microsoft.Devices.Sensors.CompassReading>>(compass_CurrentValueChanged);
                //    compass.Calibrate += new EventHandler<Microsoft.Devices.Sensors.CalibrationEventArgs>(compass_Calibrate);
                //}


                //compass.Start();

            }

            try
            {
                if (currentStatus != Running)
                {

                    lock (compass)
                    {
                        compass.CurrentValueChanged += compass_SingleHeadingValueChanged;
                        compass.Start();
                        this.SetStatus(Starting);
                    }

                    long timeout = 2000;
                    while ((currentStatus == Starting) && (timeout > 0))
                    {
                        timeout = timeout - 100;
                        Thread.Sleep(100);
                    }

                    if (currentStatus != Running)
                    {
                        DispatchCommandResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, ErrorFailedToStart));
                        return;
                    }
                }
                lock (compass)
                {

                    compass.CurrentValueChanged -= compass_SingleHeadingValueChanged;
                    if (watchers.Count < 1)
                    {
                        compass.Stop();
                    }
                }
            }
            catch (UnauthorizedAccessException)
            {
                DispatchCommandResult(new PluginResult(PluginResult.Status.ILLEGAL_ACCESS_EXCEPTION, ErrorFailedToStart));
            }
            catch (Exception)
            {
                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ErrorFailedToStart));
            }
        }

        void compass_SingleHeadingValueChanged(object sender, Microsoft.Devices.Sensors.SensorReadingEventArgs<CompassReading> e)
        {
            this.SetStatus(Running);
            if (compass.IsDataValid)
            {
                // trueHeading :: The heading in degrees from 0 - 359.99 at a single moment in time.
                //  magneticHeading:: The heading relative to the geographic North Pole in degrees 0 - 359.99 at a single moment in time. 
                //  A negative value indicates that the true heading could not be determined.
                // headingAccuracy :: The deviation in degrees between the reported heading and the true heading.
                //rawMagnetometerReading = e.SensorReading.MagnetometerReading;

                //Debug.WriteLine("Compass Result :: " + GetHeadingFormatted(e.SensorReading));

                PluginResult result = new PluginResult(PluginResult.Status.OK, GetHeadingFormatted(e.SensorReading));

                DispatchCommandResult(result);
            }
        }

        /// <summary>
        /// Starts listening for compass sensor
        /// </summary>
        /// <returns>status of listener</returns>
        private int start()
        {
            if ((currentStatus == Running) || (currentStatus == Starting))
            {
                return currentStatus;
            }
            try
            {
                lock (compass)
                {
                    watchers.Add(getCompassId, this);
                    compass.CurrentValueChanged += watchers[getCompassId].compass_CurrentValueChanged;
                    compass.Start();
                    this.SetStatus(Starting);
                }
            }
            catch (Exception)
            {
                this.SetStatus(ErrorFailedToStart);
            }
            return currentStatus;
        }

        public void startWatch(string options)
        {
            if (!DeviceCompass.IsSupported)
            {
                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, Not_Supported));
            }

            try
            {
                compassOptions = JSON.JsonHelper.Deserialize<CompassOptions>(options);
            }
            catch (Exception ex)
            {
                this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION, ex.Message));
                return;
            }

            if (string.IsNullOrEmpty(compassOptions.Id))
            {
                this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
                return;
            }

            try
            {
                lock (compass)
                {
                    watchers.Add(compassOptions.Id, this);
                    compass.CurrentValueChanged += watchers[compassOptions.Id].compass_CurrentValueChanged;
                    compass.Start();
                    this.SetStatus(Starting);
                }
            }
            catch (Exception)
            {
                this.DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ErrorFailedToStart));
                return;
            }
        }

        public void stopWatch(string options)
        {
            try
            {
                compassOptions = JSON.JsonHelper.Deserialize<CompassOptions>(options);
            }
            catch (Exception ex)
            {
                this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION, ex.Message));
                return;
            }

            if (string.IsNullOrEmpty(compassOptions.Id))
            {
                this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
                return;
            }

            if (currentStatus != Stopped)
            {
                lock (compass)
                {
                    Compass watcher = watchers[compassOptions.Id];
                    compass.CurrentValueChanged -= watcher.compass_CurrentValueChanged;
                    watchers.Remove(compassOptions.Id);
                    watcher.Dispose();
                }
            }
            this.SetStatus(Stopped);

            this.DispatchCommandResult();
        }

        void compass_Calibrate(object sender, Microsoft.Devices.Sensors.CalibrationEventArgs e)
        {
            //throw new NotImplementedException();
            // TODO: pass calibration error to JS
        }

        void compass_CurrentValueChanged(object sender, Microsoft.Devices.Sensors.SensorReadingEventArgs<CompassReading> e)
        {
            this.SetStatus(Running);
            if (compass.IsDataValid)
            {
                // trueHeading :: The heading in degrees from 0 - 359.99 at a single moment in time.
                //  magneticHeading:: The heading relative to the geographic North Pole in degrees 0 - 359.99 at a single moment in time. 
                //  A negative value indicates that the true heading could not be determined.
                // headingAccuracy :: The deviation in degrees between the reported heading and the true heading.
                //rawMagnetometerReading = e.SensorReading.MagnetometerReading;

                //Debug.WriteLine("Compass Result :: " + GetHeadingFormatted(e.SensorReading));

                PluginResult result = new PluginResult(PluginResult.Status.OK, GetHeadingFormatted(e.SensorReading));
                result.KeepCallback = true;

                DispatchCommandResult(result);
            }
        }

        /// <summary>
        /// Sets current status
        /// </summary>
        /// <param name="status">current status</param>
        private void SetStatus(int status)
        {
            currentStatus = status;
        }

    }
}
