using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Maser.Feanor.Biz;
using Maser.Feanor.Model;
using Maser.Feanor.Server;
using System.Globalization;
using System.Collections.ObjectModel;
using System.Net;
using System.IO;
using System.Data.SqlClient;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Button;

namespace FeanorConfig
{
    public partial class Manager : Form
    {
        public Manager()
        {
            InitializeComponent();
            groupBox2.Visible = false;
            pnlDatabaseBackup.Visible = false;
            groupBox1.Visible = false;

            System.Reflection.Assembly ass = System.Reflection.Assembly.GetEntryAssembly(); // report build version 
            string exe = System.IO.Path.GetFullPath(ass.Location);
            DateTime dt = new System.IO.FileInfo(exe).LastWriteTimeUtc;
            this.Text = String.Format("Feanor - Manager" + "   v{0:0000}{1:00}{2:00}", dt.Year, dt.Month, dt.Day);


            // super user default setup where options are disabled by default
            nudChambersEditInterval.Enabled = false;
            cboxChambersEditActive.Enabled = false;
            cboxRS485.Enabled = false;
            cbHumidity.Enabled = false;
            cboxSensorEditEnabled.Enabled = false;
            cboxChambersEditServerType.Enabled = false;
            txtbChambersEditMIDS.Enabled = false;
            txtbChambersEditDescription.Enabled = false;
            txtbChambersEditNetwork.Enabled = false;
        }


        private void menuChambers_Click(object sender, EventArgs e)
        {
            pnlDatabaseBackup.Visible = false;
            // Layout
            pnlMenuChambers.BringToFront();

            // Fill listbox
            lboxChambers.Items.Clear();
            try
            {
                List<Chamber> chambers;
                if (cboxChambersFilterActive.Checked)
                    chambers = new Chambers().GetAllActive();
                else
                    chambers = new Chambers().GetAll();

                foreach (Chamber chamber in chambers)
                    lboxChambers.Items.Add(chamber.MIDSandDescription); // MD
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Chambers", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // Fill groupbox
            txtbChambersEditDescription.Text = "";
            txtbChambersEditMIDS.Text = "";
            txtbChambersEditNetwork.Text = "";
            lblChambersEditPK.Text = "-1"; // PK is set to -1 if a new chamber is to be added
            btnChambersEditUpdate.Text = "Create";
            cboxChambersEditActive.Checked = true;
            cbHumidity.Checked = true;
            gboxChamberEdit.Text = "New chamber";
            cboxChambersEditServerType.Enabled = true;

            // Listbox sensors
            gbSensorsEdit.Visible = false;
        }

        private void lboxChambers_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lboxChambers.SelectedIndex < 0)
                return;

            Chamber chamber;
            try
            {
                 chamber = new Chambers().GetAll().ToList().Find(delegate (Chamber c) { return (c.MIDSandDescription == (string)lboxChambers.SelectedItem); });
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Chamber", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (chamber.ServerType == ServerType.RaspberryDELTA | chamber.ServerType == ServerType.RaspberryHAMEG)
            {
                gbDeltaIP.Visible = true;
            }
            else
            {
                gbDeltaIP.Visible = false;
            }


            if (chamber == null)
                return;

            // Fill groupbox
            cboxChambersEditServerType.Text = chamber.ServerType.ToText();
            txtbChambersEditDescription.Text = chamber.Description;
            txtbChambersEditMIDS.Text = string.Format("{0:00000}", chamber.MIDS);
            txtbChambersEditNetwork.Text = chamber.Network;
            lblChambersEditPK.Text = chamber.PK.ToString(); // PK is set to -1 if a new chamber is added
            btnChambersEditUpdate.Text = "Modify";
            gboxChamberEdit.Text = chamber.MIDSandDescription;
            cboxChambersEditActive.Checked = chamber.Active;
            cbHumidity.Checked = chamber.Humidity;
            nudChambersEditInterval.Value = chamber.Interval;
            cboxRS485.Checked = chamber.RS485;

            if(cboxRS485.Checked == false)
            {
                RS485btn.Visible = false;
            }
            else
            {
                RS485btn.Visible = true;
            }

            // Block servertype from being changed
            cboxChambersEditServerType.Enabled = false;

            // Fill Sensors
            List<Sensor> sensors;
            try
            {
                sensors = new Sensors().GetByChamber(chamber.PK);
                
                if (sensors.Count > 0)
                {
                    gbSensorsEdit.Text = String.Format("Sensors in chamber {0:00000} ({1:0})", chamber.MIDS, sensors.Count);
                    lbSensorsEdit.Items.Clear();
                    foreach (Sensor s in sensors)
                        lbSensorsEdit.Items.Add(s.ToString());
                    gbSensorsEdit.Visible = true;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, String.Format("Sensors in chamber {0:00000}", chamber.MIDS), MessageBoxButtons.OK, MessageBoxIcon.Error);
                gbSensorsEdit.Visible = false;
                return;
            }
            lbSensorsEdit.ClearSelected();
            pnlSensorEdit.Visible = false;
        }

        private Chamber GetChamber_FormChambersEdit()
        {
            int MIDS = 0;
            if (!Int32.TryParse(txtbChambersEditMIDS.Text, out MIDS))
            {
                MessageBox.Show("Use integer value for MIDS!", "Chamber", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return null;
            }
            if( MIDS < 0)
            {
                MessageBox.Show("Use positive value for MIDS!", "Chamber", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return null;
            }

            if (MIDS >99999 )
            {
                MessageBox.Show("MIDS must be less than 100000!", "Chamber", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return null;
            }

            string description = txtbChambersEditDescription.Text.Trim();
            if (description.Length < 3)
            {
                MessageBox.Show("Description should be at least 3 characters!", "Chamber", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return null; 
            }

            int Interval = (int)nudChambersEditInterval.Value;
            

            string network = txtbChambersEditNetwork.Text.Trim();
            if (network.Length < 3)
            {
                MessageBox.Show("Network should be at least 3 characters!", "Chamber", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return null; 
            }

            int PK = int.Parse(lblChambersEditPK.Text);

            // Check existing items
            List<Chamber> chambers;
            try
            {
                chambers = new Chambers().GetAllActive().ToList();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Chamber", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }

            // Check if chamber with given MIDS already exists
            if (PK < 0 && chambers.FindIndex(delegate (Chamber c) { return (c.MIDS == MIDS); }) >= 0)
            {
                MessageBox.Show("Chamber with MIDS already exists", "Chamber", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }

            // Check if chamber with given Network already exists
            if (PK < 0 && chambers.FindIndex(delegate (Chamber c) { return (c.Network == network); }) >= 0)
            {
                MessageBox.Show("Chamber with network already exists", "Chamber", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }

            // Server type
            ServerType serverType = ServerType.NONE;
            foreach (ServerType s in Enum.GetValues(typeof(ServerType)))
            {
                if (s.ToText() == (string)cboxChambersEditServerType.SelectedItem)
                {
                    serverType = s;
                    break;
                }
            }

            // Construct chamber
            Chamber chamber = new Chamber(PK, MIDS, description, Interval, network, serverType, cboxChambersEditActive.Checked,cboxRS485.Checked,cbHumidity.Checked);
            return chamber;
        }



        private void btnChambersEditUpdate_Click(object sender, EventArgs e)        // Create / modify chamber
        {   
            Chamber chamber = GetChamber_FormChambersEdit();
           
            if (chamber == null)
                return;

            // New (PK=-1) or modify (PK from DB)
            if (chamber.PK < 0)                                                     // New chamber --> create
            {
                try
                {
                    chamber.PK = new Chambers().Add(chamber);
                    Server server = Servers.GetInstanceByChamber(chamber);
                    Sensors SensorsBiz = new Sensors();
                    foreach (Sensor s in server.StandardSensors())
                        SensorsBiz.Add(s);
                    MessageBox.Show(string.Format("New chamber {0:00000} created!", chamber.MIDS), "Chamber", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                catch (Exception ex)
                {
                    String msg = String.Format("Could not add chamber!\n{0}", ex.Message);
                    MessageBox.Show(msg, "Add chamber", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }
            else                                                                        // Existing chamber --> modify
            {
                try
                {
                    new Chambers().Modify(chamber);
                    MessageBox.Show(string.Format("Chamber {0:00000} modified!", chamber.MIDS), "Chamber", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                catch (Exception ex)
                {
                    String msg = String.Format("Could not modify chamber!\n{0}", ex.Message);
                    MessageBox.Show(msg, "Modify chamber", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }

            // Send interval and time to server
            try
            {
                this.Cursor = Cursors.WaitCursor;
                ShowInfoLabel(string.Format("Uploading chamber details to server ({0}) connected to chamber {1:00000}...", chamber.Network, chamber.MIDS));
                Server server = Servers.GetInstanceByChamber(chamber);
                server.WriteInterval(chamber.Interval);
                server.WriteDatetime(Time.UTC);
            }
            catch (Exception ex)
            {
                HideInfoLabel(); // Called in finally, but also here to update GUI before ex-message is shown
                String msg = String.Format("Could not connect to server chamber!\n{0}", ex.Message);
                MessageBox.Show(msg, "Modify chamber", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
            finally
            {
                this.Cursor = Cursors.Default;
                HideInfoLabel();
            }


            // Refresh and reselect
            menuChambers_Click(null, null);
            for (int i = 0; i < lboxChambers.Items.Count; i++)
            {
                if ((string)lboxChambers.Items[i] == chamber.MIDSandDescription)
                {
                    lboxChambers.SelectedIndex = i;
                    break;
                }
            }

            MessageBox.Show("Please restart FEANOR Client and Manager!");
        }


        private void Manager_Load(object sender, EventArgs e)
        {
            // Init combobox with server types
            cboxChambersEditServerType.Items.Clear();
            foreach (ServerType serverType in Enum.GetValues(typeof(ServerType)))
                cboxChambersEditServerType.Items.Add(serverType.ToText());
            cboxChambersEditServerType.SelectedIndex = 0;


            // Init pnl Chambers
            menuChambers_Click(null, null);
        }

        private void cboxChambersFilterActive_CheckedChanged(object sender, EventArgs e)
        {
            menuChambers_Click(null, null);
        }

        private void lbSensorsEdit_SelectedIndexChanged(object sender, EventArgs e)
        {
            pnlSensorEdit.Visible = false;

            if (lboxChambers.SelectedIndex < 0)
                return;

            if (lbSensorsEdit.SelectedIndex < 0)
                return;

            lblSensorEditPK.Text = "-1";
            lblSensorEditCalibrationPK.Text = "-1";

            Sensor sensor;
            try
            {
                int ChamberPK = Int32.Parse(lblChambersEditPK.Text);
                sensor = new Sensors().GetByChamber(ChamberPK).Find(delegate (Sensor s) { return (s.ID == lbSensorsEdit.SelectedIndex); });
                lblSensorEditPK.Text = sensor.PK.ToString();
                if (sensor == null)
                    return;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Could not retrieve sensor details!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            txtbSensorEditID.Text = String.Format("{0:00}", sensor.ID);
            txtbSensorEditType.Text = sensor.TypeToString();
            txtbSensorEditDescription.Text = sensor.Description;
            cboxSensorEditEnabled.Checked = sensor.Enabled;
            cboxSensorEditCalibrationEnabled.Checked = sensor.ApplyCalibration;
            

            Calibration calibration;
            try
            {
                calibration = new Calibrations().GetLastCreatedBySensorPK(sensor.PK);                

                if (calibration == null) // if no calibration is found
                {
                    calibration = new Calibration(-1, sensor.PK, DateTime.Now, DateTime.Now.AddMonths(12), DateTime.Now, new double[4] { 0, 1, 0, 0 }, 0, new double[4] { 0, 0, 1, 1 });
                    cboxSensorEditCalibrationEnabled.Checked = false;
                }
                else
                {
                    lblSensorEditCalibrationPK.Text = calibration.PK.ToString();
                }

                // display X1..X4 and C0 + C1
                label17.Text = Math.Round(calibration.Coefficients[0],5).ToString();
                label18.Text = Math.Round(calibration.Coefficients[1],5).ToString();
                tbX1.Text = Math.Round(calibration.Xvalues[0], 5).ToString();
                tbX2.Text = Math.Round(calibration.Xvalues[1], 5).ToString();
                tbX3.Text = Math.Round(calibration.Xvalues[2], 5).ToString();
                tbX4.Text = Math.Round(calibration.Xvalues[3], 5).ToString();

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Could not retrieve calibration details!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

   
            for (int i = 0; i < Coefficient_TextBoxes.Count; i++)
            {
                Coefficient_TextBoxes[i].Text = calibration.Coefficients[i].ToString("0.000000E0");
            }
            txtbSensorsEditCalibrationU.Text = calibration.Uncertainty.ToString("0.000000E0");
            dtpSensorEditRelease.Value = calibration.Release;
            dtpSensorEditExpiry.Value = calibration.Expiry;
            //dtpSensorEditCreation.Value = calibration.Creation;

            pnlSensorEdit.Visible = true;
        }

        public List<TextBox> Coefficient_TextBoxes
        {
            get
            {
                List<TextBox> txtbList = new List<TextBox>();
                
                
                return txtbList;
            }
        }


        private Sensor GetSensor_FormSensorEdit()
        {
            Sensor sensor;
            try
            {
                int PK = int.Parse(lblSensorEditPK.Text);
                sensor = new Sensors().GetByPK(PK);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Could not retrieve sensor from database!\n" + ex.Message, "Modify sensor", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }

            string description = txtbSensorEditDescription.Text.Trim();
            if (description.Length < 3)
            {
                MessageBox.Show("Description should be at least 3 characters!", "Chamber", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return null;
            }
            sensor.Description = description;
            sensor.Enabled = cboxSensorEditEnabled.Checked;
            sensor.ApplyCalibration = cboxSensorEditCalibrationEnabled.Checked;

            return sensor;
        }

        private Calibration GetCalibration_FormSensorEdit()
        {
            int PK = int.Parse(lblSensorEditCalibrationPK.Text);
            int SensorPK = int.Parse(lblSensorEditPK.Text);

            double X1 = 0.0;
            double X2 = 0.0;
            double X3 = 0.0;
            double X4 = 0.0;

            if (!tbX1.Text.TryParseToDouble(out X1))
            {
                MessageBox.Show("X1" + X1.ToString() + " should be a decimal number!\n\n(You can use format 0.0E0 or 0.0 with 6 decimals)", "Sensor calibration", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return null;
            }
            if (!tbX2.Text.TryParseToDouble(out X2))
            {
                MessageBox.Show("X2" + X2.ToString() + " should be a decimal number!\n\n(You can use format 0.0E0 or 0.0 with 6 decimals)", "Sensor calibration", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return null;
            }
            if (!tbX3.Text.TryParseToDouble(out X3))
            {
                MessageBox.Show("X3" + X3.ToString() + " should be a decimal number!\n\n(You can use format 0.0E0 or 0.0 with 6 decimals)", "Sensor calibration", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return null;
            }
            if (!tbX4.Text.TryParseToDouble(out X4))
            {
                MessageBox.Show("X4" + X4.ToString() + " should be a decimal number!\n\n(You can use format 0.0E0 or 0.0 with 6 decimals)", "Sensor calibration", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return null;
            }
           
            double a = (X3 - X1) / (X4 - X2);
            double b = X1 - a * X2;

            double[] Xvalues = new double[4] { X1, X2, X3, X4 };

            double[] c = new double[4] { 0, 1, 0, 0 };

            if (cboxSensorEditCalibrationEnabled.Checked == true)  // if calibration is true --> a and b are used
            {
                c[0] = Math.Round(b, 5);
                c[1] = Math.Round(a, 5) ;
            }
            else // if calibration is disabled --> use gain = 1 and offset = 0
            {
                c[0] = 0.0;
                c[1] = 1.0;
            }


            label17.Text = c[0].ToString();
            label18.Text = c[1].ToString();


            double U = 0;

            if (!txtbSensorsEditCalibrationU.Text.TryParseToDouble(out U))
            {
                MessageBox.Show("U should be a decimal number!\n\n(You can use format 0.0E0 or 0.0 with 6 decimals)", "Sensor calibration", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return null;
            }

            // for(int i =0; i<3; i++) Console.WriteLine(c[i]);
            //Console.WriteLine(U);
           
            return new Calibration(PK, SensorPK, dtpSensorEditRelease.Value, dtpSensorEditExpiry.Value, DateTime.Now, c, U, Xvalues);
            
        }

        private void btnSensorEditClearCalibration_Click(object sender, EventArgs e)
        {
            tbX1.Text = "0.0";
            tbX2.Text = "0.0";
            tbX3.Text = "1.0";
            tbX4.Text = "1.0";
            txtbSensorsEditCalibrationU.Text = "0";
            dtpSensorEditRelease.Value = DateTime.Now;
            dtpSensorEditExpiry.Value = DateTime.Now.AddYears(1);
        }

        private void btnSensorEditModify_Click(object sender, EventArgs e) // modify button click
        {           
            // Get from GUI
            Sensor sensor = GetSensor_FormSensorEdit();
            if (sensor == null)
                return;

            Calibration calibration = GetCalibration_FormSensorEdit();
            if (calibration == null)
                return;
                        
            String InformationMsg = "";
            Boolean WriteToServerRequired = false;

            // Modify sensor in DB
            try
            {
                Sensor existing = new Sensors().GetByPK(sensor.PK); // obtain sensor from DB
                if (!new Sensors().Equal(sensor, existing))         // check if new sensor data is different (does not check for change of c0,c1...)
                {
                    new Sensors().Modify(sensor);
                    //InformationMsg += "Changes to sensor saved!";
                    WriteToServerRequired = true;
                }
                else
                {
                    //InformationMsg += "Sensor has not changed.";
                }

            }
            catch (Exception ex)
            {
                String msg = String.Format("Could not modify sensor!\n{0}", ex.Message);
                MessageBox.Show(msg, "Modify sensor", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // Modify or add calibration in/to DB
            if( calibration.PK < 0) 
            {
                // Calibration for sensor was not found. Add new one.
                try
                {
                    new Calibrations().Add(calibration);
                    InformationMsg += "\nNew calibration added!";
                    //InformationMsg += "\n\nPlease restart the server!";
                }
                catch (Exception ex)
                {
                    String msg = String.Format("Could not create calibration!\n{0}", ex.Message);
                    MessageBox.Show(msg, "Calibration", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

            }
            else
            {
                // Sensor has a calibration. Add new one if changed.
                try
                {
                    Calibration existing = new Calibrations().GetByPK(calibration.PK);
                   if (!new Calibrations().Equal(calibration, existing) || calibration.Uncertainty != existing.Uncertainty) // if c[] of U is changed                   
                    {
                        int pk = new Calibrations().Add(calibration);
                        lblSensorEditCalibrationPK.Text = pk.ToString();
                        InformationMsg += "\nNew calibration added replacing previous calibration!";
                        //InformationMsg += "\n\nPlease restart the server!";
                        WriteToServerRequired = true;
                    }
                    else 
                        InformationMsg += "\nCalibration has not changed.";
                    
                }
                catch (Exception ex)
                {
                    String msg = String.Format("Could not save calibration!\n{0}", ex.Message);
                    MessageBox.Show(msg, "Modify sensor", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }
            MessageBox.Show(InformationMsg, "Modify sensor", MessageBoxButtons.OK, MessageBoxIcon.Information);


            // Is there a need to update server?
            if(WriteToServerRequired)
            {
                Chamber chamber;
                try
                {
                    int ChamberPK = Int32.Parse(lblChambersEditPK.Text);                    
                    chamber = new Chambers().GetByPK(ChamberPK);
                }
                catch (Exception ex)
                {
                    string msg = "Could not find chamber network information in database!\n\n" + ex.Message;
                    MessageBox.Show(msg, "Sensor upload", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }
                try
                {
                    this.Cursor = Cursors.WaitCursor;
                  
                    ShowInfoLabel(string.Format("Uploading sensor details to server ({0}) connected to chamber {1:00000}...", chamber.Network, chamber.MIDS));

                    Server server = Servers.GetInstanceByChamber(chamber);

                    if (!server.ModifySensor(sensor, calibration))
                    {
                        string msg = string.Format("Failed to upload sensor details to server ({0}) connected to chamber {1:00000}!", server.URL, chamber.MIDS);
                        MessageBox.Show(msg,"Sensor upload", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    }
                }
                catch (Exception ex)
                {
                    HideInfoLabel();
                    string msg = string.Format("Sensor details could not be uploaded to server ({0}) connected to chamber {1:00000}!\n\n", chamber.Network, chamber.MIDS);
                    msg += ex.Message;
                    MessageBox.Show(msg, "Sensor upload", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                finally
                {
                    this.Cursor = Cursors.Default;
                    HideInfoLabel();
                }
            }

            // Refresh and reselect
            int indexChamber = lboxChambers.SelectedIndex;
            int indexSensor = lbSensorsEdit.SelectedIndex;
            lboxChambers.ClearSelected();
            lboxChambers.SelectedIndex = indexChamber;
            lbSensorsEdit.ClearSelected();
            lbSensorsEdit.SelectedIndex = indexSensor;
        }


        private void ShowInfoLabel(string msg)
        {
            this.Cursor = Cursors.WaitCursor;
            pnlInfoLabel.Location = new Point(191, 285);
            lblInfo.Text = msg;
            int x = (int)Math.Round((double)(pnlInfoLabel.Width - lblInfo.Width) / 2.0);
            int y = lblInfo.Location.Y;
            lblInfo.Location = new Point(x, y);
            pnlInfoLabel.BringToFront();
            pnlInfoLabel.Visible = true;
            pnlInfoLabel.Refresh();
        }
        private void HideInfoLabel()
        {
            lblInfo.Text = "";
            pnlInfoLabel.Visible = false;
            this.Cursor = Cursors.Default;
        }
            

        private void Reboot_Click(object sender, EventArgs e) // reboot raspberry pi
        {
            Chamber chamber;
            int ChamberPK = Int32.Parse(lblChambersEditPK.Text);
            chamber = new Chambers().GetByPK(ChamberPK);
            Server server = Servers.GetInstanceByChamber(chamber);
            try
            {
                using (WebClient client = new WebClient())
                {
                    string dta = client.DownloadString(server.URL + "reboot");                   
                    // Console.WriteLine(dta);
                    if(dta == "OK")
                    {
                        MessageBox.Show("Reboot successful");
                    }
                    else
                    {
                        MessageBox.Show("Reboot command not received successfully");
                    }
                }
            }
            catch
            {
                //Console.WriteLine("Reboot RPI");
            }
        }

        private void Shutdown_Click(object sender, EventArgs e) // shutdown raspberry pi
        {
            Chamber chamber;
            int ChamberPK = Int32.Parse(lblChambersEditPK.Text);
            chamber = new Chambers().GetByPK(ChamberPK);
            Server server = Servers.GetInstanceByChamber(chamber);
            try
            {
                using (WebClient client = new WebClient())
                {
                    string dta = client.DownloadString(server.URL + "shutdown");
                    //Console.WriteLine(dta);
                    if (dta == "OK")
                    {
                        MessageBox.Show("Shutdown successful");
                    }
                    else
                    {
                        MessageBox.Show("Shutdown command not received successfully");
                    }
                }
            }
            catch
            {
                //Console.WriteLine("Shutdown RPI");
            }
        }

        public void NodeState_Click(object sender, EventArgs e)
        {
            Chamber chamber;
            int ChamberPK = Int32.Parse(lblChambersEditPK.Text);
            chamber = new Chambers().GetByPK(ChamberPK);
            Server server = Servers.GetInstanceByChamber(chamber);                   

            try
            {
                using (WebClient client = new WebClient())
                {
                    string dta = client.DownloadString(server.URL + "status");          // send status HTTP request to cms node
                    //Console.WriteLine(server.URL + "status");                           // output URL

                    Nodestatus nodestate = new Nodestatus();                    
                    nodestate.Show();                                                   // create HTML viewer

                    nodestate.webBrowser1.Navigate("about:blank");                      // empty HTML viewer
                    if (nodestate.webBrowser1.Document != null)
                    {
                        nodestate.webBrowser1.Document.Write(string.Empty);
                    }
                    nodestate.webBrowser1.DocumentText = dta;                           // put received HTML into web viewer

                    string nodestatusurl = server.URL + "status";                       // put used URL in text box for further use (update button)
                    nodestate.nodeURL.Text = nodestatusurl;
                }
            }
            catch
            {
                Console.WriteLine("Status request error!");
                System.Windows.Forms.MessageBox.Show("No response from CMS-2 node");
            }
        }

        private void RS485btn_Click(object sender, EventArgs e)
        {
            RS485_Comm RScomm = new RS485_Comm();
            RScomm.Show();

            Chamber chamber;
            int ChamberPK = Int32.Parse(lblChambersEditPK.Text);
            chamber = new Chambers().GetByPK(ChamberPK);
            Server server = Servers.GetInstanceByChamber(chamber);

            RScomm.RSurl.Text = server.URL;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Chamber chamber;
            int ChamberPK = Int32.Parse(lblChambersEditPK.Text);
            chamber = new Chambers().GetByPK(ChamberPK);
            Server server = Servers.GetInstanceByChamber(chamber);

            string http = "<socket>,";          
            http += textBox1.Text;
            http += ",";
            http += int.Parse(textBox2.Text);
            http += ",</socket>";

            // Send unix timestamp string to RPI
            try
            {
                using (WebClient client = new WebClient())
                {
                   
                    string URL = "http://" + chamber.Network + ":8080/";
                    //Console.WriteLine(URL);
                    string url = client.UploadString(URL, http);
                    //Console.WriteLine(url);
                }
            }
            catch
            {

            }
        }

        private void databaseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            pnlDatabaseBackup.Visible = true;
            groupBox1.Visible = true;

            //SqlConnection connection = new SqlConnection("Data Source=tcp:192.168.0.241\\FEANOR,1434; Initial Catalog = FEANOR; Persist Security Info=True; User " +"ID = sa; Password= ; connection timeout=15");
            SqlConnection connection = new SqlConnection("Data Source=tcp:10.126.21.47\\FEANOR,1434; Initial Catalog=FEANOR; User ID=sa; Password=resam@123resam; timeout=15; Persist Security Info=True; TrustServerCertificate=True");

            DateTime st;
            try
            {
                using (connection)
                {
                    SqlCommand command = new SqlCommand(
                      "USE FEANOR SELECT TOP 1 TimeStamp FROM dbo.Results ORDER BY TimeStamp ASC;",
                      connection);
                    connection.Open();

                    st = (DateTime)command.ExecuteScalar();
                    lblFirstResult.Text = st.ToString();
                }
            }
            catch
            {
                st = DateTime.Now;
            }

            txtbBackupFile.Text = "C:\\FeanorDB_Backup\\CMS2backup (period " + st.ToString("yyyy dd MM") + " to " + DateTime.Now.ToString("yyyy dd MM") + ").bak";
            txtbBackupFileCopy.Text = @"Z:\projects\2020\P201339\sub1\4. Software\6. CMS2_Database_Backup\CMS2backup (period " + st.ToString("yyyy dd MM") + " to " + DateTime.Now.ToString("yyyy dd MM") + ").bak";

        }

        private void btnDatabaseBackup_Click(object sender, EventArgs e)
        {
            
            SqlConnection myConnection = new SqlConnection("Data Source=tcp:10.126.21.47\\FEANOR,1434; Initial Catalog=FEANOR; User ID=sa; Password=resam@123resam; timeout=15; Persist Security Info=True; TrustServerCertificate=True");

                while (File.Exists(txtbBackupFile.Text) == false)
            {
                // backup to local drive
                try
                {
                    myConnection.Open();
                    SqlCommand cmd = new SqlCommand(@"BACKUP DATABASE FEANOR TO DISK='" + txtbBackupFile.Text + "'", myConnection);
                    cmd.ExecuteNonQuery();
                    
                }
                catch
                {
                    MessageBox.Show("Error during local DB backup!");
                }
                finally
                {
                    myConnection.Close();
                }
                
            }
            MessageBox.Show("Local DB backup succesful!");

            // Check if server file is actually there
            while (File.Exists(txtbBackupFileCopy.Text) == false)
            {
                try
                {
                    File.Copy(txtbBackupFile.Text, txtbBackupFileCopy.Text, true);
                   
                }
                catch
                {
                    MessageBox.Show("Error during server DB backup!");
                }                
            }
            MessageBox.Show("Server DB backup succesful!");
        }

        private void button2_Click(object sender, EventArgs e)
        {
            pnlDatabaseBackup.Visible = false;
            pnlDatabaseBackup.Visible = false;
            groupBox1.Visible = false;
        }

        private void dtpSensorEditCreation_ValueChanged(object sender, EventArgs e)
        {

        }

        private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {

        }

        private void label28_Click(object sender, EventArgs e)
        {

        }

        private void label30_Click(object sender, EventArgs e)
        {

        }

        private void cboxSensorEditCalibrationEnabled_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void button3_Click(object sender, EventArgs e)
        {
            CalibrationHelpPage CHP = new CalibrationHelpPage();
            CHP.Show();
        }

        private void rS485ChambersToolStripMenuItem_Click(object sender, EventArgs e)
        {
            groupBox2.Visible = true;

            dgvRS485.DefaultCellStyle.ForeColor = Color.Black;
            dgvRS485.Rows.Clear();

            List<Chamber> chambers;
            chambers = new Chambers().GetAllActive();
            foreach (Chamber chamber in chambers)                
                if (chamber.RS485 == true)
                {
                    //Console.WriteLine(chamber.MIDS);
                    dgvRS485.Rows.Add(chamber.MIDS.ToString());
                }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            groupBox2.Visible = false;

            
        }

        private void timerDBbackup_Tick(object sender, EventArgs e)
        {
            Console.WriteLine("Making DB backup......");
            timerDBbackup.Enabled = false;    // only 1 tick
           
            
        }

        private void btnDeleteOneYear_Click(object sender, EventArgs e)
        {
            DialogResult dialogResult = MessageBox.Show("Are you sure you want to delete Database results older than 1 year?", "Delete Results", MessageBoxButtons.YesNo);
            if (dialogResult == DialogResult.Yes)
            {
                SqlConnection myConnection = new SqlConnection("Data Source=tcp:10.126.21.47\\FEANOR,1434; Initial Catalog=FEANOR; User ID=sa; Password=resam@123resam; timeout=15; Persist Security Info=True; TrustServerCertificate=True");

                try
                {
                    myConnection.Open();
                    SqlCommand cmd = new SqlCommand(@"DELETE FROM RESULTS WHERE TimeStamp < (GETDATE() - 365);", myConnection);
                    cmd.ExecuteNonQuery();

                    myConnection.Open();
                    cmd = new SqlCommand(@"DELETE FROM RESULTSOUDEHAL WHERE TimeStamp < (GETDATE() - 365);", myConnection);
                    cmd.ExecuteNonQuery();
                    MessageBox.Show("Deleting Database results succesful");
                }
                catch
                {
                    MessageBox.Show("Error during deleting DataBase results");
                }
                finally
                {
                    myConnection.Close();
                }
                
            }
            else if (dialogResult == DialogResult.No)
            {
                //do something else
            }
        }

        private void btnDeleteHalfYear_Click(object sender, EventArgs e)
        {
            DialogResult dialogResult = MessageBox.Show("Are you sure you want to delete Database results older than half a year?", "Delete Results", MessageBoxButtons.YesNo);
            if (dialogResult == DialogResult.Yes)
            {
                SqlConnection myConnection = new SqlConnection("Data Source=tcp:10.126.21.47\\FEANOR,1434; Initial Catalog=FEANOR; User ID=sa; Password=resam@123resam; timeout=15; Persist Security Info=True; TrustServerCertificate=True");

                try
                {
                    myConnection.Open();
                    SqlCommand cmd = new SqlCommand(@"DELETE FROM RESULTS WHERE TimeStamp < (GETDATE() - 188);", myConnection);
                    cmd.ExecuteNonQuery();
                    myConnection.Open();
                    cmd = new SqlCommand(@"DELETE FROM RESULTSOUDEHAL WHERE TimeStamp < (GETDATE() - 188);", myConnection);
                    cmd.ExecuteNonQuery();
                    MessageBox.Show("Deleting Database results succesful");
                }
                catch
                {
                    MessageBox.Show("Error during deleting DataBase results");
                }
                finally
                {
                    myConnection.Close();
                }

            }
            else if (dialogResult == DialogResult.No)
            {
                //do something else
            }
        }

        private void btnDeleteTwoYear_Click(object sender, EventArgs e)
        {
            DialogResult dialogResult = MessageBox.Show("Are you sure you want to delete Database results older than 2 years?", "Delete Results", MessageBoxButtons.YesNo);
            if (dialogResult == DialogResult.Yes)
            {
                SqlConnection myConnection = new SqlConnection("Data Source=tcp:10.126.21.47\\FEANOR,1434; Initial Catalog=FEANOR; User ID=sa; Password=resam@123resam; timeout=15; Persist Security Info=True; TrustServerCertificate=True");

                try
                {
                    myConnection.Open();
                    SqlCommand cmd = new SqlCommand(@"DELETE FROM RESULTS WHERE TimeStamp < (GETDATE() - 730);", myConnection);
                    cmd.ExecuteNonQuery();
                    myConnection.Open();
                    cmd = new SqlCommand(@"DELETE FROM RESULTSOUDEHAL WHERE TimeStamp < (GETDATE() - 730);", myConnection);
                    cmd.ExecuteNonQuery();
                    MessageBox.Show("Deleting Database results succesful");
                }
                catch
                {
                    MessageBox.Show("Error during deleting DataBase results");
                }
                finally
                {
                    myConnection.Close();
                }

            }
            else if (dialogResult == DialogResult.No)
            {
                //do something else
            }
        }

        private void label33_Click(object sender, EventArgs e)
        {

        }

        private void cboxRS485_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void cbHumidity_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void cbSuperUser_CheckedChanged(object sender, EventArgs e)
        {
            cbSuperUser.CheckedChanged -= cbSuperUser_CheckedChanged;
            if(cbSuperUser.Checked == true)
            {
                DialogResult dialogResult = MessageBox.Show("Are you sure that you want to edit node information?", "Super user", MessageBoxButtons.YesNo);
                if (dialogResult == DialogResult.Yes)
                {
                    cbSuperUser.Checked = true;
                }
                else if (dialogResult == DialogResult.No)
                {
                    cbSuperUser.Checked = false;
                }
            }           
            cbSuperUser.CheckedChanged += cbSuperUser_CheckedChanged;

            if (cbSuperUser.Checked == true)
            {
                nudChambersEditInterval.Enabled = true;
                cboxChambersEditActive.Enabled = true;
                cboxRS485.Enabled = true;
                cbHumidity.Enabled = true;
                cboxSensorEditEnabled.Enabled = true;
                cboxChambersEditServerType.Enabled = true;
                txtbChambersEditMIDS.Enabled = true;
                txtbChambersEditDescription.Enabled = true;
                txtbChambersEditNetwork.Enabled = true;
            }
            else
            {
                nudChambersEditInterval.Enabled = false;
                cboxChambersEditActive.Enabled = false;
                cboxRS485.Enabled = false;
                cbHumidity.Enabled = false;
                cboxSensorEditEnabled.Enabled = false;
                cboxChambersEditServerType.Enabled = false;
                txtbChambersEditMIDS.Enabled = false;
                txtbChambersEditDescription.Enabled = false;
                txtbChambersEditNetwork.Enabled = false;
            }
        }
    }
}



