using System;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
using Newtonsoft.Json;
using System.Globalization;
using LiveCharts;
using LiveCharts.WinForms;
using LiveCharts.Wpf;

namespace Wetterstation
{
    public partial class Hintergrund : Form
    {
        public struct MassueredValue
        {
            public DateTime dtTimestamp;
            public double dValue;
        };

        MassueredValue temperatureValue;
        MassueredValue humidityValue;
        MassueredValue pressureValue;

        //Variable fuer den Debugmodues
        private bool debug = false;

        private MqttClient myClient;
        SettingsModel WeatherstationSettings = new SettingsModel();

        public Hintergrund()
        {
            InitializeComponent();
            WeatherstationSettings = SqliteDataAccess.LoadWeatherstationSettings();
            lbCity.Text = WeatherstationSettings.city;
            
            // Start a timer for date and time
            Timer t = new Timer();
            t.Interval = 1000;
            t.Tick += new EventHandler(this.t_DateTime);
            t.Start();

            mqttStart();
            updateChart();
        }

        private void updateChart()
        {
            cartesianChart1.Series = new SeriesCollection
            {
                new LineSeries
                {
                    Title = "Temperature",
                    Values = new ChartValues<double> {4, 4, 4, 4, 4},
                    PointGeometry = null
                },
                new LineSeries
                {
                    Title = "Humidity",
                    Values = new ChartValues<double> {6, 7, 3, 4, 6},
                    PointGeometry = null
                },
                new LineSeries
                {
                    Title = "Pressure",
                    Values = new ChartValues<double> {5, 2, 8, 3},
                    PointGeometry = null
                }
            };

            cartesianChart1.LegendLocation = LegendLocation.Right;

            //modifying the series collection will animate and update the chart
            //cartesianChart1.Series.Add(new LineSeries
            //{
            //    Values = new ChartValues<double> { 5, 3, 2, 4, 5 },
            //    LineSmoothness = 0, //straight lines, 1 really smooth lines
            //});

            //modifying any series values will also animate and update the chart
            cartesianChart1.Series[2].Values.Add(5d);
        }

        private void t_DateTime(object sender, EventArgs e)
        {
            lbUhr.Text = DateTime.Now.ToLongTimeString();
            lbDatum.Text = DateTime.Now.ToShortDateString();
        }

        private void LED_Click(object sender, EventArgs e)
        {
        
            System.Drawing.SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Red);
            System.Drawing.Graphics formGraphics;
            formGraphics = this.CreateGraphics();
            formGraphics.FillEllipse(myBrush, new Rectangle(818, 238, 12, 12));
            myBrush.Dispose();
            formGraphics.Dispose();
        }

        private void Label1_Click(object sender, EventArgs e)
        {
            System.Drawing.SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Red);
            System.Drawing.Graphics formGraphics;
            formGraphics = this.CreateGraphics();
            formGraphics.FillEllipse(myBrush, new Rectangle(872, 290, 12, 12));
            myBrush.Dispose();
            formGraphics.Dispose();
        }

        private void LED_S_Click(object sender, EventArgs e)
        {
            System.Drawing.SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Red);
            System.Drawing.Graphics formGraphics;
            formGraphics = this.CreateGraphics();
            formGraphics.FillEllipse(myBrush, new Rectangle(818,350, 12, 12));
            myBrush.Dispose();
            formGraphics.Dispose();
        }

        private void LED_W_Click(object sender, EventArgs e)
        {
            System.Drawing.SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Red);
            System.Drawing.Graphics formGraphics;
            formGraphics = this.CreateGraphics();
            formGraphics.FillEllipse(myBrush, new Rectangle(764, 290, 12, 12));
            myBrush.Dispose();
            formGraphics.Dispose();
        }

        //MQTT connect
        public void mqttStart()
        {
            String topic_publish = "/wetterstation/backend/" + WeatherstationSettings.frontendId + "/";
            String topic_subscribe = "/wetterstation/frontend/" + WeatherstationSettings.frontendId + "/#";

            System.Console.WriteLine("Mqtt wird gestartet ....");
            // Create Client instance
            this.myClient = new MqttClient("mqtt.itstall.de");

            // Register to message received
            myClient.MqttMsgPublishReceived += client_recievedMessage;

            string clientId = Guid.NewGuid().ToString();
            this.myClient.Connect("", "wetterstation", "wetterstation");

            // Subscribe to topic
            this.myClient.Subscribe(new String[] { topic_subscribe }, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });

            this.myClient.Publish(topic_publish, Encoding.UTF8.GetBytes("Request_frontend"));
        }

        public void msgPublish(String topic, String message)
        {
            Console.Write("Sending via MQTT: ");
            Console.Write("Topic: " + topic);
            Console.WriteLine("Message: " + message);
            this.myClient.Publish(topic, Encoding.UTF8.GetBytes(message));
        }

        private void client_recievedMessage(object sender, MqttMsgPublishEventArgs e)
        {
            // Handle message received
            var message = System.Text.Encoding.Default.GetString(e.Message);
            System.Console.WriteLine("Message received: " + message);
            Console.WriteLine("With Topic: " + e.Topic);

            if (e.Topic.Equals(WeatherstationSettings.mqtt_topic_frontend + WeatherstationSettings.frontendId + "/weather"))
            {
                this.updateFormWeather(message);
            }
            else if (e.Topic.Equals(WeatherstationSettings.mqtt_topic_frontend + WeatherstationSettings.frontendId + "/forecast"))
            {
                this.updateFormForecast(message);
            }
            else if (e.Topic.Equals(WeatherstationSettings.mqtt_topic_frontend + WeatherstationSettings.frontendId + "/sensors"))
            {
                this.updateFormSensors(message);
            }
            else if (e.Topic.Equals(WeatherstationSettings.mqtt_topic_frontend + WeatherstationSettings.frontendId + "/graph"))
            {
                Console.WriteLine("e.Topic Graph " + e.Topic);
                Console.WriteLine(WeatherstationSettings.mqtt_topic_frontend + WeatherstationSettings.frontendId + "/graph");
                this.updateFormChart(message);
            }
            
        }

        public void updateFormChart(String message)
        {
            dynamic weatherData = JsonConvert.DeserializeObject(message.ToString());
            Console.WriteLine("---- bin in update Graph -----");
            //Console.WriteLine(message);

            //Console.WriteLine("---- und das steht in weatherData -----");
            //Console.WriteLine(weatherData);

            Console.WriteLine("---- und das steht in results[0][series][0][columns] -----");
            Console.WriteLine("weatherData[\"results\"][0][\"series\"][0][\"columns\"][0] = > " + weatherData["results"][0]["series"][0]["columns"][0]);
            Console.WriteLine("weatherData[\"results\"][0][\"series\"][0][\"columns\"][1] = > " + weatherData["results"][0]["series"][0]["columns"][1]);
            Console.WriteLine("weatherData[\"results\"][0][\"series\"][0][\"columns\"][2] = > " + weatherData["results"][0]["series"][0]["columns"][2]);
            Console.WriteLine("weatherData[\"results\"][0][\"series\"][0][\"columns\"][3] = > " + weatherData["results"][0]["series"][0]["columns"][3]);
            Console.WriteLine("weatherData[\"results\"][0][\"series\"][0][\"columns\"][4] = > " + weatherData["results"][0]["series"][0]["columns"][4]);
            Console.WriteLine();


            Console.WriteLine("weatherData[\"results\"][0][\"series\"][0][\"values\"][1][0] => " + weatherData["results"][0]["series"][0]["values"][1][0]);
            Console.WriteLine("weatherData[\"results\"][0][\"series\"][0][\"values\"][65][0] => " + weatherData["results"][0]["series"][0]["values"][85][0]);
            Console.WriteLine("weatherData[\"results\"][0][\"series\"][0][\"values\"][65][1] => " + weatherData["results"][0]["series"][0]["values"][65][1]);
            Console.WriteLine("weatherData[\"results\"][0][\"series\"][0][\"values\"][65][2] => " + weatherData["results"][0]["series"][0]["values"][65][2]);
            Console.WriteLine("weatherData[\"results\"][0][\"series\"][0][\"values\"][65][3] => " + weatherData["results"][0]["series"][0]["values"][65][3]);
            Console.WriteLine("weatherData[\"results\"][0][\"series\"][0][\"values\"][65][4] => " + weatherData["results"][0]["series"][0]["values"][65][4]);
            


            Console.WriteLine(weatherData["results"][0]["series"][0]["values"][85][2]);

            //temperatureValue.dtTimestamp = weatherData["results"][0]["series"][0]["values"][1][0];
            //temperatureValue.dValue = weatherData["results"][0]["series"][0]["values"][85][2];


            
            //Console.WriteLine("Datum: " + temperatureValue.dtTimestamp + " hat Wert: " + temperatureValue.dValue);

            //Laufvariablen fuer For-Schleife
            int i = 0;
            int j = 0;



            //while((weatherData["results"][0]["series"][0]["columns"][0]))
            //{
            //    Console.WriteLine("4 erwaretet: " + i);
            //    i++;
            //}
            
                              
            



            //foreach()
            //Console.WriteLine(weatherData["results"]["columns"]["values"]);

            /*
            for(weatherData.)
            {

            }
            */
        }

        public void updateFormWeather(String message)
        {
            Console.WriteLine("Entered updateFormWeather");
            try
            {
                dynamic weatherData = JsonConvert.DeserializeObject(message.ToString());
                lbAussenTemp.Invoke(new Action(() => { lbAussenTemp.Text = weatherData.temp + " °C"; }));
                lbTempMin.Invoke(new Action(() => { lbTempMin.Text = weatherData.tempMin + " °C"; }));
                lbTempMax.Invoke(new Action(() => { lbTempMax.Text = weatherData.tempMax + " °C"; }));
                lbLuftfeuchtAussen.Invoke(new Action(() => { lbLuftfeuchtAussen.Text = weatherData.humidity + " %"; }));
                lbWindSpeed.Invoke(new Action(() => { lbWindSpeed.Text = weatherData.windSpeed + " ms"; }));
                lbWindricht.Invoke(new Action(() => { lbWindricht.Text = weatherData.windDeg + " °"; }));
                lbLuftdruck.Invoke(new Action(() => { lbLuftdruck.Text = weatherData.pressure + " mbar"; }));
                pictureBox1.Invoke(new Action(() => {
                    pictureBox1.Image = RotateImage((Bitmap)global::Wetterstation.Properties.Resources.ResourceManager.GetObject("WindRose_neu"), (int)weatherData.windDeg);
                }));

            }
            catch (Exception ignored) { }
        }
        private Bitmap RotateImage(Bitmap bmp, float angle)
        {
            float height = bmp.Height;
            float width = bmp.Width;
            int hypotenuse = System.Convert.ToInt32(System.Math.Floor(Math.Sqrt(height * height + width * width)));
            Bitmap rotatedImage = new Bitmap(hypotenuse, hypotenuse);
            using (Graphics g = Graphics.FromImage(rotatedImage))
            {
                g.TranslateTransform((float)rotatedImage.Width / 2, (float)rotatedImage.Height / 2); //set the rotation point as the center into the matrix
                g.RotateTransform(angle); //rotate
                g.TranslateTransform(-(float)rotatedImage.Width / 2, -(float)rotatedImage.Height / 2); //restore rotation point into the matrix
                g.DrawImage(bmp, (hypotenuse - width) / 2, (hypotenuse - height) / 2, width, height);
            }
            return rotatedImage;
        }


        public void updateFormForecast(String message)
        {
            Console.WriteLine("Entered updateFormForecast");
            try
            {
                dynamic weatherData = JsonConvert.DeserializeObject(message.ToString());
                if(weatherData[0].icon1 != null) lbForecastImage1.Invoke(new Action(() => { lbForecastImage1.Image = global::Wetterstation.Properties.Resources.ResourceManager.GetObject("_" + weatherData[0].icon1 + "_2x"); }));
                lbForecastTemp1.Invoke(new Action(() => { lbForecastTemp1.Text = weatherData[0].temp + " °C"; }));
                lbForecastDay1.Invoke(new Action(() => { lbForecastDay1.Text = getDayFromDateString(weatherData[0].from.ToString()); }));

                if (weatherData[1].icon1 != null) lbForecastImage2.Invoke(new Action(() => { lbForecastImage2.Image = global::Wetterstation.Properties.Resources.ResourceManager.GetObject("_" + weatherData[1].icon1 + "_2x"); }));
                lbForecastTemp2.Invoke(new Action(() => { lbForecastTemp2.Text = weatherData[1].temp + " °C"; }));
                lbForecastDay2.Invoke(new Action(() => { lbForecastDay2.Text = getDayFromDateString(weatherData[1].from.ToString()); }));

                if (weatherData[2].icon1 != null) lbForecastImage3.Invoke(new Action(() => { lbForecastImage3.Image = global::Wetterstation.Properties.Resources.ResourceManager.GetObject("_" + weatherData[2].icon1 + "_2x"); }));
                lbForecastTemp3.Invoke(new Action(() => { lbForecastTemp3.Text = weatherData[2].temp + " °C"; }));lbForecastDay1.Invoke(new Action(() => { lbForecastDay1.Text = getDayFromDateString(weatherData[0].from.ToString()); }));
                lbForecastDay3.Invoke(new Action(() => { lbForecastDay3.Text = getDayFromDateString(weatherData[2].from.ToString()); }));

                if (weatherData[3].icon1 != null) lbForecastImage4.Invoke(new Action(() => { lbForecastImage4.Image = global::Wetterstation.Properties.Resources.ResourceManager.GetObject("_" + weatherData[3].icon1 + "_2x"); }));
                lbForecastTemp4.Invoke(new Action(() => { lbForecastTemp4.Text = weatherData[3].temp + " °C"; }));
                lbForecastDay4.Invoke(new Action(() => { lbForecastDay4.Text = getDayFromDateString(weatherData[3].from.ToString()); }));

                if (weatherData[4].icon1 != null) lbForecastImage5.Invoke(new Action(() => { lbForecastImage5.Image = global::Wetterstation.Properties.Resources.ResourceManager.GetObject("_" + weatherData[4].icon1 + "_2x"); }));
                lbForecastTemp5.Invoke(new Action(() => { lbForecastTemp5.Text = weatherData[4].temp + " °C"; }));
                lbForecastDay5.Invoke(new Action(() => { lbForecastDay5.Text = getDayFromDateString(weatherData[4].from.ToString()); }));
            }
            catch (Exception ignored) { }
        }

        public String getDayFromDateString(String strDate)
        {
            DateTime dt = DateTime.ParseExact(strDate, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
            CultureInfo culture = new CultureInfo("de-DE");
            return culture.DateTimeFormat.GetDayName(dt.DayOfWeek).Substring(0, 2).ToString();
        }

        public void updateFormSensors(String message)
        {
            Console.WriteLine("Entered updateFormSensors");
            try
            {
                dynamic weatherData = JsonConvert.DeserializeObject(message.ToString());
                //lbInnenTemp.Invoke(new Action(() => { lbInnenTemp.Text = weatherData.sensors[0].temperature + " °C"; }));
            }
            catch (Exception ignored) { }
        }

        public void updateFormComplete()
        {
            WeatherstationSettings = SqliteDataAccess.LoadWeatherstationSettings();
            lbCity.Text = WeatherstationSettings.city;
        }

        public void updateSettings2Mqtt()
        {
            Console.WriteLine(JsonConvert.SerializeObject(WeatherstationSettings).ToString());
            this.msgPublish(WeatherstationSettings.mqtt_topic_backend + "settings", JsonConvert.SerializeObject(WeatherstationSettings).ToString());
        }

        private void BtSystemKnopf_Click(object sender, EventArgs e)
        {
            Form settings = new Settings();
            // Settings als Dialog starten, dann wird das Frontend geblockt und auf abschluss gewartet
            settings.ShowDialog();
            updateFormComplete();
            // MQTT beenden und Verbindung neu aufbauen
            this.myClient.Disconnect();
            this.mqttStart();
            // Neue Einstellungen an Backend senden
            this.updateSettings2Mqtt();
        }

        private void Hintergrund_Load(object sender, EventArgs e)
        {

        }

        private void Hintergrund_FormClosed(object sender, FormClosedEventArgs e)
        {
            this.myClient.Disconnect();
            Application.Exit();
        }

        private void CartesianChart1_ChildChanged(object sender, System.Windows.Forms.Integration.ChildChangedEventArgs e)
        {

        }

        private void LbHintergrund_Click(object sender, EventArgs e)
        {

        }
    }
}