﻿/*  
	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 WPCordovaClassLib.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)
        {   
            // NOTE: timestamp is generated on the JS side, to avoid issues with format conversions
            string result = String.Format("\"magneticHeading\":{0},\"headingAccuracy\":{1},\"trueHeading\":{2}",
                            reading.MagneticHeading.ToString("0.0", CultureInfo.InvariantCulture),
                            reading.HeadingAccuracy.ToString("0.0", CultureInfo.InvariantCulture),
                            reading.TrueHeading.ToString("0.0", CultureInfo.InvariantCulture));
            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();
                        this.SetStatus(Stopped);
                    }
                }
            }
            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;
        }

    }
}
