using System;
using System.IO.Ports;
using System.Windows.Forms;
using Sensirion.SHDLC;
using Sensirion.SHDLC.SFC5xxx;

namespace SFC5xxxSampleProjects
{
  public partial class frmMain : Form
  {
    private ShdlcConnection _Connection;
    private SFC5xxxDevice _Device;

    #region Constructor

    public frmMain()
    {
      InitializeComponent();
      RefreshComPortList();
    }

    #endregion

    #region Private Memberfunctions

    private void Connect()
    {
      try
      {
        // disable connect button
        cmdConnect.Enabled = false;

        // create connection string
        string xConStr = cboPort.SelectedItem.ToString() + ", "       // selected serial port
                       + cboBaudrate.SelectedItem.ToString() + ", "   // selected baudrate
                       + "ECHOOFF";

        // create and open new connection
        _Connection = new ShdlcConnection();
        _Connection.OpenPort(PortType.Serial, xConStr);

        // create SFC5xxx Device
        _Device = new SFC5xxxDevice(_Connection, (int)updAddress.Value);

        // load system infos
        LoadSystemInfos();

        // load calibration data
        LoadAllCalibrations();
        ShowCalibInfo(_Device.GetCurrentCalibInfo());

        // start continuous measurement
        tmrReadFlow.Enabled = true;

        // update GUI controls
        panConnectionConfig.Enabled = false;
        gbxDevice.Enabled = true;
        cmdConnect.Enabled = true;
        cmdConnect.Text = "Disconnect";
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK);
        Disconnect();
        cmdConnect.Enabled = true;
      }
    }

    private void Disconnect()
    {
      try
      {
        // stop continuous measurement
        tmrReadFlow.Enabled = false;

        // update gui
        panConnectionConfig.Enabled = true;
        gbxDevice.Enabled = false;
        cmdConnect.Text = "Connect";

        // close connection
        if (_Connection != null)
          _Connection.ClosePort();
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK);
      }
      finally
      {
        _Device = null;
        _Connection = null;
      }
    }

    private void LoadSystemInfos()
    {
      DeviceVersion version = _Device.Version;
      lblProductName.Text = _Device.ProductName;
      lblArticleCode.Text = _Device.ArticleCode;
      lblSerialNumber.Text = _Device.SerialNumber;
      lblVersion.Text = string.Format("Hardware: V{0}.{1}, Firmware: V{2}.{3}",
        version.HwMajor,
        version.HwMinor,
        version.FwMajor,
        version.FwMinor);
    }

    private void LoadAllCalibrations()
    {
      cboCalibration.Items.Clear();
      for (UInt32 i = 0; i < _Device.NumberOfFlashLocations; i++)
      {
        CalibInfo calibInfo = _Device.GetFlashCalibInfo(i);
        if (calibInfo.CalibValid)
        {
          cboCalibration.Items.Add(calibInfo);
          // select the currently active calibration in the combobox
          if (calibInfo.FlashLocation == _Device.ActiveCalibration)
            cboCalibration.SelectedItem = calibInfo;
        }
      }
    }

    private void ShowCalibInfo(CalibInfo calibInfo)
    {
      lblMediumId.Text = calibInfo.MediumId.ToString();
      lblMediumName.Text = calibInfo.MediumDescription.ToString();
      lblFullscaleFlow.Text = calibInfo.FullscaleFlow.ToString("G4");
      lblMediumUnit.Text = calibInfo.MediumUnit.UnitStringShort;
    }

    private void RefreshComPortList()
    {
      try
      {
        string selectedItemBackup = cboPort.Text;
        cboPort.Items.Clear();
        cboPort.Items.AddRange(SerialPort.GetPortNames());
        cboPort.Text = selectedItemBackup;

        if (cboPort.SelectedItem == null)
          cboPort.SelectedIndex = cboPort.Items.Count - 1;
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK);
      }
    }

    #endregion

    #region Control Event Handlers

    private void cboPort_DropDown(object sender, EventArgs e)
    {
      RefreshComPortList();
    }

    private void cmdConnect_Click(object sender, EventArgs e)
    {
      if (_Device == null)
        Connect();
      else
        Disconnect();
    }

    private void cboCalibration_SelectedIndexChanged(object sender, EventArgs e)
    {
      try
      {
        CalibInfo calibInfo = ((CalibInfo)cboCalibration.SelectedItem);
        _Device.LoadAndSelectCalibration((UInt32)calibInfo.FlashLocation);
        ShowCalibInfo(calibInfo);
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK);
      }
    }

    private void cboCalibration_Format(object sender, ListControlConvertEventArgs e)
    {
      e.Value = ((CalibInfo)e.ListItem).MediumDescription;
    }

    private void cmdSetSetpoint_Click(object sender, EventArgs e)
    {
      try
      {
        _Device.SetSetpoint((float)(updSetpoint.Value / 100), DataScaling.Normalized);
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK);
      }
    }

    private void tmrReadFlow_Tick(object sender, EventArgs e)
    {
      try
      {
        lblMeasuredFlow.Text = _Device.ReadMeasuredValue(DataScaling.Normalized).ToString("P2") + " of Fullscale";
      }
      catch (Exception ex)
      {
        lblMeasuredFlow.Text = ex.Message;
      }
    }

    private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
    {
      if (_Device != null)
        Disconnect();
    }

    #endregion
  }
}