using System;
using System.Linq;
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Windows.Devices.Sensors;
using Windows.UI.Core;
using Windows.Storage;
using Newtonsoft.Json;


// Pour en savoir plus sur le modèle d'élément Page vierge, consultez la page http://go.microsoft.com/fwlink/?LinkId=391641

namespace ProfilConducteur
{

    /// <summary>
    /// Une page vide peut être utilisée seule ou constituer une page de destination au sein d'un frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        double[] accel = new double[100000];
        double[][] results;
        int[] clustered;
        int curCond;
        int curNormeAccel = 0;
        private Accelerometer _accelerometer;
        private uint _desiredReportInterval;

        // eviter le spam de la touche false
        private bool runningTest = false;

        public MainPage()
        {
            this.InitializeComponent();
            try
            {
                
                curCond = (int)ApplicationData.Current.LocalSettings.Values["cc"];
                results = JsonConvert.DeserializeObject<double[][]>((String)ApplicationData.Current.LocalSettings.Values["res"]);
                Array.Resize(ref results, curCond + 1);
            }
            catch (Exception)
            {
                results = new double[1][];
                curCond = 0;
            } 

            _accelerometer = Accelerometer.GetDefault();
            if (_accelerometer != null)
            {
                // Select a report interval that is both suitable for the purposes of the app and supported by the sensor.
                // This value will be used later to activate the sensor.
                uint minReportInterval = _accelerometer.MinimumReportInterval;
                _desiredReportInterval = minReportInterval > 16 ? minReportInterval : 16;
            }
        }

        /// <summary>
        /// Invoked immediately before the Page is unloaded and is no longer the current source of a parent Frame.
        /// </summary>
        /// <param name="e">
        /// Event data that can be examined by overriding code. The event data is representative
        /// of the navigation that will unload the current Page unless canceled. The
        /// navigation can potentially be canceled by setting Cancel.
        /// </param>
        protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
        {
            if (arreteTest.IsEnabled)
            {
                Window.Current.VisibilityChanged -= new WindowVisibilityChangedEventHandler(VisibilityChanged);
                _accelerometer.ReadingChanged -= new TypedEventHandler<Accelerometer, AccelerometerReadingChangedEventArgs>(ReadingChanged);

                // Restore the default report interval to release resources while the sensor is not in use
                _accelerometer.ReportInterval = 0;
            }

            base.OnNavigatingFrom(e);
        }

        /// <summary>
        /// This is the event handler for VisibilityChanged events. You would register for these notifications
        /// if handling sensor data when the app is not visible could cause unintended actions in the app.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e">
        /// Event data that can be examined for the current visibility state.
        /// </param>
        private void VisibilityChanged(object sender, VisibilityChangedEventArgs e)
        {
            if (arreteTest.IsEnabled)
            {
                if (e.Visible)
                {
                    // Re-enable sensor input (no need to restore the desired reportInterval... it is restored for us upon app resume)
                    _accelerometer.ReadingChanged += new TypedEventHandler<Accelerometer, AccelerometerReadingChangedEventArgs>(ReadingChanged);
                }
                else
                {
                    // Disable sensor input (no need to restore the default reportInterval... resources will be released upon app suspension)
                    _accelerometer.ReadingChanged -= new TypedEventHandler<Accelerometer, AccelerometerReadingChangedEventArgs>(ReadingChanged);
                }
            }
        }

        /// <summary>
        /// This is the event handler for ReadingChanged events.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        async private void ReadingChanged(object sender, AccelerometerReadingChangedEventArgs e)
        {
            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                AccelerometerReading reading = e.Reading;
                accel[curNormeAccel] = Math.Sqrt(reading.AccelerationX* reading.AccelerationX + reading.AccelerationY * reading.AccelerationY+ reading.AccelerationZ* reading.AccelerationZ);
                //System.Diagnostics.Debug.WriteLine(reading.AccelerationX);
                curNormeAccel++;
            });
        }

        /// <summary>
        /// This is the click handler for the 'Enable' button.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void start(object sender, RoutedEventArgs e)
        {
            runningTest = true;
            this.runningLabel.Text = "test en cours";

            if (_accelerometer != null)
            {
                // Establish the report interval
                _accelerometer.ReportInterval = _desiredReportInterval;

                Window.Current.VisibilityChanged += new WindowVisibilityChangedEventHandler(VisibilityChanged);
                _accelerometer.ReadingChanged += new TypedEventHandler<Accelerometer, AccelerometerReadingChangedEventArgs>(ReadingChanged);               

            }
            demarreTest.IsEnabled = false;
            arreteTest.IsEnabled = true;
            progressRing.IsActive = true;
        }

        /// <summary>
        /// This is the click handler for the 'Disable' button.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void stop(object sender, RoutedEventArgs e)
        {
            this.runningLabel.Text = "pas de test en cours";

            if (runningTest)
            {
                runningTest = false;
                Window.Current.VisibilityChanged -= new WindowVisibilityChangedEventHandler(VisibilityChanged);
                _accelerometer.ReadingChanged -= new TypedEventHandler<Accelerometer, AccelerometerReadingChangedEventArgs>(ReadingChanged);

                // Restore the default report interval to release resources while the sensor is not in use
                _accelerometer.ReportInterval = 0;
                Array.Sort(accel);

                double[] quart = math.Quartiles(accel);
                results[curCond] = new double[] { quart[0], quart[1], quart[2], accel.Max() };
                //System.Diagnostics.Debug.WriteLine("Valeurs  : " + quart[0]+" "+ quart[1]+" "+ quart[2]+" "+ accel.Max());

                if (curCond <= 4)
                {
                    //Il faut au moins 4 résultats pour l'initialisation
                    System.Diagnostics.Debug.WriteLine(curCond);
                   Results.Text = "Pas assez de résultats encore";
                }
                else
                {
                    clustered = KMeans.KMeans.Cluster(results, 4);
                    if (clustered[results.Length - 1] == 0)
                    {
                        Results.Text = "Conducteur prudent + ecoconduite";
                    }
                    else if (clustered[results.Length - 1] == 1)
                    {
                        Results.Text = "Conducteur prudent";
                    }
                    else if (clustered[results.Length - 1] == 2)
                    {
                        Results.Text = "Conducteur moyen";
                    }
                    else if (clustered[results.Length - 1] == 3)
                    {
                        Results.Text = "Conducteur dangereux";
                    }
                }
                curCond++;
                curNormeAccel = 0;
                String strObject = JsonConvert.SerializeObject(results);
                ApplicationData.Current.LocalSettings.Values["res"] = strObject;
                ApplicationData.Current.LocalSettings.Values["cc"] = curCond;
                Array.Resize(ref results, curCond + 1);
            }
            updateNbMesures();
            demarreTest.IsEnabled = true;
            arreteTest.IsEnabled = false;
            progressRing.IsActive = false;
        }

        private void updateNbMesures()
        {
            this.nbMesures.Text = "Nombre de mesures prises:" + curCond;
        }

        // Bouton " Display Clusters"
        private void button_Click(object sender, RoutedEventArgs e)
        {

            if (clustered != null)
            {
                //KMeans.KMeans.ShowClustered(results, int[] clustering, int numClusters, 3);

                //System.Diagnostics.Debug.WriteLine("-----\n"+results[0].Length);
                //System.Diagnostics.Debug.WriteLine(results.Length);


                // itère sur les clusters
                for (int i = 0; i < 4; i++)
                {
                    System.Diagnostics.Debug.WriteLine("---------cluster : " + i + "------------------");
                    // itère sur les données
                    for (int j = 0; j < clustered.Length; j++)
                    {
                        if (i == clustered[j])
                        {
                            System.Diagnostics.Debug.WriteLine("---------data : ");
                            for (int k = 0; k < results[j].Length; k++)
                            {
                                System.Diagnostics.Debug.WriteLine(results[j][k]);
                            }

                        }
                    }
                }
            }
        }
    }
}
