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 System.Threading;
using System.Runtime.InteropServices;
using System.IO;
using N_Series_SDK.Properties;
using System.Linq.Expressions;
using System.Diagnostics;

namespace N_Series_SDK
{    
    public partial class NSeries : Form
    {
        public KSPLIB_NSeries m_KSPLIB_NSeries;

        public KSPLIB_NSeries._DeviceList[] m_stDevList;
        public KSPLIB_NSeries._DevInformation[] m_stDeviceInfo;
        public int selDev = 0;
        short sTotChnl;
       
        static public string gROMData;
        public double[] dCoefficient = new double[4];

        public Thread m_Thread;

        public NSeries()
        {
            InitializeComponent();
            m_KSPLIB_NSeries = new KSPLIB_NSeries();
            init();

            dgvDeviceInfo.Rows.Clear();
        }
        private void init()
        {
            rb_trigPrev.Checked = true;
            dgvDeviceInfo.Rows[0].Selected = false;
#if __KRVER
            textBox1.Text = "\r\n\r\nSpectrometer from Korea Spectral Products, Inc.";
            pictureBox1.Image = Resources.SM32ProMX_L;
#endif

            chkIPRangeScan.Checked = false;

            txtScanStartHostID.Enabled = false;
            txtScanEndHosID.Enabled = false;
            txtScanNetworkID.Enabled = false;

            rbCalPointCalWL.CheckedChanged += SelWLTableRadio_CheckChanged;
            rbCoefficientCalWL.CheckedChanged += SelWLTableRadio_CheckChanged;
            rbFactoryDefaultCalWL.CheckedChanged += SelWLTableRadio_CheckChanged;
        }

        private void GetDataSet()
        {
            short sRtn;
            int[] DataArray = new int[m_stDeviceInfo[selDev].iTotPixel];
            string streamTxt;

            selDev = dgvDeviceInfo.SelectedRows[0].Index;

            SaveFileDialog pFileDlg = new SaveFileDialog();
            pFileDlg.Filter = "Text Files(*.txt)|*.txt|All Files(*.*)|*.*";
            pFileDlg.FileName = "SDK_Data_1.txt";
            pFileDlg.Title = "Please specify the location to save";

            if (m_stDeviceInfo[selDev].sTrgMode == (short)KSPLIB_NSeries.emTriggerMode.SP_TRIGGER_EXTERNAL)
            {
                do
                {
                    sRtn = m_KSPLIB_NSeries.NReadDataEx(DataArray, m_stDeviceInfo[selDev].sChannel);
                } while (sRtn == -99);
            }
            else
            {
                sRtn = m_KSPLIB_NSeries.NReadDataEx(DataArray, m_stDeviceInfo[selDev].sChannel);
            }

            if (pFileDlg.ShowDialog() == DialogResult.OK)
            {
                System.IO.FileStream filestream = new System.IO.FileStream(pFileDlg.FileName, System.IO.FileMode.Create, System.IO.FileAccess.Write);
                StreamWriter streamwriter = new StreamWriter(filestream);

                streamTxt = "Index\tWavelength(nm)\tIntensity\t\r\n";
                for (int i = 0; i < m_stDeviceInfo[selDev].iRealPixel; i++)
                {
                    streamTxt +=  i.ToString() + "\t" + m_stDeviceInfo[selDev].dWLTable[i].ToString("####.##") + "\t" + DataArray[m_stDeviceInfo[selDev].iDummyPixel + i].ToString("####.##") + "\r\n";
                }                                
                
                streamwriter.WriteLine(streamTxt);

                streamwriter.Close();
            }
        }

        private void ScanDevice()
        {
            if(dgvDeviceInfo.Rows.Count > 0)
            {
                for (int i = 0; i < dgvDeviceInfo.Rows.Count; i++)
                {
                    if(dgvDeviceInfo.Rows[i].Cells[2].Value != null)
                        if ((bool)dgvDeviceInfo.Rows[i].Cells[2].Value)
                            m_KSPLIB_NSeries.NDevClose(m_stDeviceInfo[i].sChannel);
                }
            }

            dgvDeviceInfo.Rows.Clear();

            short sRtn = -1;

            if (!chkIPRangeScan.Checked)
            {
                sRtn = m_KSPLIB_NSeries.NScanDevice((short)KSPLIB_NSeries.emScanMode.SP_SCAN_ALLDEVICE);

                if (sRtn < 0)
                {
                    string strLine = "There are no matching devices.\nError String : " + m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString();
                    MessageBox.Show(strLine, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
            {
                char[] pcNetworkID = txtScanNetworkID.Text.ToCharArray();
                short sStartHostID = short.Parse(txtScanStartHostID.Text),sEndHostID = short.Parse(txtScanEndHosID.Text);

                sRtn = m_KSPLIB_NSeries.NScanDevice_IP(pcNetworkID, sStartHostID, sEndHostID);
                if (sRtn < 0)
                {
                    string strLine = "There are no matching devices.\nError String : " + m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString();
                    MessageBox.Show(strLine, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            
            sTotChnl = (short)(sRtn);
            m_stDevList = new KSPLIB_NSeries._DeviceList[sTotChnl];
            m_stDeviceInfo = new KSPLIB_NSeries._DevInformation[sTotChnl];


            sRtn = m_KSPLIB_NSeries.NGetDeviceList(m_stDevList);
            dgvDeviceInfo.AllowUserToAddRows = false;
            for (int i=0; i<sTotChnl;i++)
            {
                string strInterface = "";
                if (m_stDevList[i].sInterfaceType == (short)KSPLIB_NSeries.emInterfaceType.SP_INTERFACE_ETHERNET)
                    strInterface = "TCP/IP";
                else if (m_stDevList[i].sInterfaceType == (short)KSPLIB_NSeries.emInterfaceType.SP_INTERFACE_USB)
                    strInterface = "USB";
                dgvDeviceInfo.Rows.Add((i+1).ToString(), strInterface, false, m_stDevList[i].strModel, m_stDevList[i].strSerial, m_stDevList[i].strIPAddr, m_stDevList[i].strCOM);
            }
        }

        public void buttenEnable()
        {
            btnGraph.Enabled = true;
            btnSaveData.Enabled = true;        
            for(int i = 0; i < dgvDeviceInfo.Rows.Count; i++)            
                dgvDeviceInfo.Rows[i].Cells[2].Value = false;
            
            dgvDeviceInfo.Rows[dgvDeviceInfo.CurrentCell.RowIndex].Cells[2].Value = true;
            btnApply.Enabled = true;
            rb_trigNext.Enabled = true;
            rb_trigPrev.Enabled = true;
            rb_trigSW.Enabled = true;
            rb_trigExternal.Enabled = true;            

            m_dIntTime.Enabled = true;
            m_iTimeAvg.Enabled = true;
            chkAutoDark.Enabled = true;
            btnBurstMode.Enabled = true;
            btnWLCalibration.Enabled = true;
            rbCalPointCalWL.Enabled = true;
            rbCoefficientCalWL.Enabled = true;
            rbFactoryDefaultCalWL.Enabled = true;

            if(m_stDeviceInfo[selDev].strModel == "SM303NP" || m_stDeviceInfo[selDev].strModel == "SM303N")
                rb_SyncTrgMode.Enabled = true;
        }

        private void btnRescan_Click_1(object sender, EventArgs e)
        {
            ScanDevice();
        }

        private void btnConnect_Click_1(object sender, EventArgs e)
        {
            short sRtn = -1;
            selDev = dgvDeviceInfo.SelectedRows[0].Index;

            if (m_stDevList[selDev].sInterfaceType == (short)KSPLIB_NSeries.emInterfaceType.SP_INTERFACE_ETHERNET)
                sRtn = m_KSPLIB_NSeries.NConnect(m_stDevList[selDev].sInterfaceType, m_stDevList[selDev].strIPAddr);
            else if (m_stDevList[selDev].sInterfaceType == (short)KSPLIB_NSeries.emInterfaceType.SP_INTERFACE_USB)
                sRtn = m_KSPLIB_NSeries.NConnect(m_stDevList[selDev].sInterfaceType, m_stDevList[selDev].strCOM);

            if (sRtn < 0)
            {
                string strLine; 

                strLine = string.Format("Error Function : SPNConnect().\nError String : ", m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString());
                MessageBox.Show(strLine, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);

                return;
            }

            sRtn = m_KSPLIB_NSeries.NGetDevParam(ref m_stDeviceInfo[selDev], sRtn);
            if (sRtn < 0)
            {
                MessageBox.Show("Error Function : spNGetDevParam().\nError String : " + m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (m_stDeviceInfo[selDev].sCCDType == (short)KSPLIB_NSeries.emCCDType.SP_CCD_SONY)
                m_dIntTime.Value = (decimal)m_stDeviceInfo[selDev].iInttime;
            else
                m_dIntTime.Value = (decimal)(m_stDeviceInfo[selDev].iInttime / 1000.0);

            m_iTimeAvg.Value = (decimal)m_stDeviceInfo[selDev].iTimeavg;
            
            buttenEnable();

           // sRtn = m_KSPLIB_NSeries.NSetShutterPos(0, 0);

            if(rbFactoryDefaultCalWL.Checked)
            {
                sRtn = m_KSPLIB_NSeries.NGetWLTable(m_stDeviceInfo[selDev].dWLTable, m_stDeviceInfo[selDev].sChannel);
                if(sRtn < 0)
                {
                    MessageBox.Show("Error Function : spNGetWLTable().\nError String : " + m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }
            else if(rbCoefficientCalWL.Checked)
            {
                sRtn = m_KSPLIB_NSeries.NGetWLTable_User(m_stDeviceInfo[selDev].dWLTable, (short)KSPLIB_NSeries.emCalWavelength.SP_CALWL_COEFFICIENT , m_stDeviceInfo[selDev].sChannel);
                if (sRtn < 0)
                {
                    MessageBox.Show("Error Function : NGetWLTable_User().\nError String : " + m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }
            else if (rbCalPointCalWL.Checked)
            {
                sRtn = m_KSPLIB_NSeries.NGetWLTable_User(m_stDeviceInfo[selDev].dWLTable, (short)KSPLIB_NSeries.emCalWavelength.SP_CALWL_CALPOINT, m_stDeviceInfo[selDev].sChannel);
                if (sRtn < 0)
                {
                    MessageBox.Show("Error Function : NGetWLTable_User().\nError String : " + m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }

            btnGraph.Enabled = true;
        }

        private void btnDataSave_Click(object sender, EventArgs e)
        {
            GetDataSet();
        }

        private void btnApply_Click(object sender, EventArgs e)
        {
            int selDev;
            short sRtn;

            selDev = dgvDeviceInfo.SelectedRows[0].Index;

            if (selDev >= 0)
            {
                if (rb_trigNext.Checked)
                    m_stDeviceInfo[selDev].sTrgMode = (short)KSPLIB_NSeries.emTriggerMode.SP_TRIGGER_FREERUN_NEXT;
                else if (rb_trigPrev.Checked)
                    m_stDeviceInfo[selDev].sTrgMode = (short)KSPLIB_NSeries.emTriggerMode.SP_TRIGGER_FREERUN_PREV;
                else if (rb_trigSW.Checked)
                    m_stDeviceInfo[selDev].sTrgMode = (short)KSPLIB_NSeries.emTriggerMode.SP_TRIGGER_SOFTWARE;
                else if (rb_trigExternal.Checked)
                    m_stDeviceInfo[selDev].sTrgMode = (short)KSPLIB_NSeries.emTriggerMode.SP_TRIGGER_EXTERNAL;
                else if (rb_SyncTrgMode.Checked)
                    m_stDeviceInfo[selDev].sTrgMode = (short)KSPLIB_NSeries.emTriggerMode.SP_TRIGGER_SYNCHRONOUS;
            }

            if (m_stDeviceInfo[selDev].sCCDType == (short)KSPLIB_NSeries.emCCDType.SP_CCD_SONY)
                sRtn = m_KSPLIB_NSeries.NSetIntTime((int)m_dIntTime.Value, m_stDeviceInfo[selDev].sChannel);
            else
                sRtn = m_KSPLIB_NSeries.NSetDBLIntTime((double)m_dIntTime.Value, m_stDeviceInfo[selDev].sChannel);

            if (sRtn < 0)
            {
                MessageBox.Show("Error Function : spNSetIntTime().\nError String : " + m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            sRtn = m_KSPLIB_NSeries.NSetTimeAvg((short)m_iTimeAvg.Value, m_stDeviceInfo[selDev].sChannel);

            if (sRtn < 0)
            {
                MessageBox.Show("Error Function : spNSetTimeAvg().\nError String : " + m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            sRtn = m_KSPLIB_NSeries.NSetTrgMode(m_stDeviceInfo[selDev].sTrgMode, m_stDeviceInfo[selDev].sChannel);
            if (sRtn < 0)
            {
                MessageBox.Show("Error Function : spNSetTrgMode().\nError String : " + m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (m_stDeviceInfo[selDev].sCCDType == (short)KSPLIB_NSeries.emCCDType.SP_CCD_SONY)
                m_stDeviceInfo[selDev].iInttime = (int)m_dIntTime.Value;
            else
                m_stDeviceInfo[selDev].iInttime = (int)m_dIntTime.Value * 1000;
            m_stDeviceInfo[selDev].iTimeavg = (int)m_iTimeAvg.Value;

        }

        private void btnGetDataAll_Click(object sender, EventArgs e)
        {
            GetDataSet();
        }
        
        private void btnGraph_Click(object sender, EventArgs e)
        {
            Graph frm = new Graph();
            frm.pParent = this;

            selDev = dgvDeviceInfo.SelectedRows[0].Index;

            frm.DataArray = new int[m_stDeviceInfo[selDev].iTotPixel];
            frm.YPlotDataArray = new Int32[m_stDeviceInfo[selDev].iRealPixel];
            frm.Show();
            if (frm._worker == null)
            {
                frm._worker = new BackgroundWorker();
                frm._worker.DoWork += new DoWorkEventHandler(frm.Woker);
                frm._worker.WorkerSupportsCancellation = true;
                frm._worker.RunWorkerAsync();
            }
            else if (frm._worker.IsBusy == false)
            {
                frm._worker = new BackgroundWorker();
                frm._worker.DoWork += new DoWorkEventHandler(frm.Woker);
                frm._worker.WorkerSupportsCancellation = true;
                frm._worker.RunWorkerAsync();
            }
        }

        private void chkAutoDark_CheckedChanged(object sender, EventArgs e)
        {
            short sRtn;
            selDev = dgvDeviceInfo.SelectedRows[0].Index;

            if (chkAutoDark.Checked)
                sRtn = m_KSPLIB_NSeries.NAutoDark(1, m_stDeviceInfo[selDev].sChannel);
            else
                sRtn = m_KSPLIB_NSeries.NAutoDark(0, m_stDeviceInfo[selDev].sChannel);
            if (sRtn < 0)
            {
                MessageBox.Show("Error Function : NAutoDark().\nError String : " + m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        private void btnClose_Click(object sender, EventArgs e)
        {     
            m_KSPLIB_NSeries.NDevClose(m_stDeviceInfo[selDev].sChannel);
        }

        private void NSeries_FormClosing(object sender, FormClosingEventArgs e)
        {
            for (int i = 0; i < sTotChnl; i++)
            {
                if ((bool)dgvDeviceInfo.Rows[i].Cells[2].Value == true)
                    m_KSPLIB_NSeries.NDevClose(m_stDeviceInfo[i].sChannel);
            }
        }

        private void chkIPRangeScan_CheckedChanged(object sender, EventArgs e)
        {
            if(chkIPRangeScan.Checked)
            {
                txtScanStartHostID.Enabled = true;
                txtScanEndHosID.Enabled = true;
                txtScanNetworkID.Enabled = true;
            }
            else
            {
                txtScanStartHostID.Enabled = false;
                txtScanEndHosID.Enabled = false;
                txtScanNetworkID.Enabled = false;
            }
        }

        private void btnBurstMode_Click(object sender, EventArgs e)
        {
            BurstMode frm = new BurstMode();
                         
            frm.pParent = this;
            frm.iSelDev = dgvDeviceInfo.SelectedRows[0].Index;

            if (m_stDeviceInfo[frm.iSelDev].strModel == "SM303NP" || m_stDeviceInfo[frm.iSelDev].strModel == "SM303N")
                frm.chkSyncTriggerMode.Visible = true;

            if (m_stDeviceInfo[selDev].sTrgMode == (short)KSPLIB_NSeries.emTriggerMode.SP_TRIGGER_SYNCHRONOUS)
                frm.chkSyncTriggerMode.Checked = true;

            frm.Show();
        }

        private void btnWLCalibration_Click(object sender, EventArgs e)
        {
            CalWavelength frm = new CalWavelength(this);

            frm.Show();
        }

        public void SelWLTableRadio_CheckChanged(object sender, EventArgs e)
        {
            RadioButton rbCheck = sender as RadioButton;
            short sRtn;

            if (rbCheck.Checked == false)
                return;

            if((string)rbCheck.Tag == "Coefficient")
            {
                sRtn = m_KSPLIB_NSeries.NGetWLTable_User(m_stDeviceInfo[selDev].dWLTable, (short)KSPLIB_NSeries.emCalWavelength.SP_CALWL_COEFFICIENT, m_stDeviceInfo[selDev].sChannel);
                if (sRtn < 0)
                    MessageBox.Show("Error Function : NGetWLTable_User().\nError String : " + m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else if ((string)rbCheck.Tag == "Point")
            {
                sRtn = m_KSPLIB_NSeries.NGetWLTable_User(m_stDeviceInfo[selDev].dWLTable, (short)KSPLIB_NSeries.emCalWavelength.SP_CALWL_CALPOINT, m_stDeviceInfo[selDev].sChannel);
                if (sRtn < 0)
                    MessageBox.Show("Error Function : NGetWLTable_User().\nError String : " + m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else if ((string)rbCheck.Tag == "Factory")
            {
                sRtn = m_KSPLIB_NSeries.NGetWLTable(m_stDeviceInfo[selDev].dWLTable, m_stDeviceInfo[selDev].sChannel);
                if (sRtn < 0)
                    MessageBox.Show("Error Function : spNGetWLTable().\nError String : " + m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}
