using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;
using System.Threading;
using System.Diagnostics;
using Microsoft.SqlServer.Server;

namespace SM_Series_SDK
{
    public struct DeviceInfo
    {
        public StringBuilder Model, Serial;
        public int nTOTPixelNo, nRealPixelNo, EffectivePixelIndex;
        public int lIntTime, lTimeAvg;
        public short USBSpeed;
        public short CCDType;
    }
    public partial class SDK_USBm : Form
    {
        short sTotChnlNum = 0;
        public short CurrentCh = 0;
        public double[] dCoefficient = new double[4];
        public DeviceInfo[] pDeviceInfo;
        bool bExtTrigger = false;

        public SDK_USBm()
        {
            InitializeComponent();
            cbSelExOutTrgPin.SelectedIndex = 0;
            SaveFileName.Text = "SKD_Data";
            nIntTime.Value = 35;
            EnableCtl(false);
            InitDev();
        }
        public void CheckConnections_Click(object sender, EventArgs e)
        {
            InitDev();
        }
        public void InitDev()
        {

            short sRtn;
            cbSelChannel.Items.Clear();

            sRtn = SPdbUSBm.spTestAllChannels(0);

            if (sRtn > 0)
            {
                sTotChnlNum = sRtn;

                pDeviceInfo = new DeviceInfo[sTotChnlNum];

                CheckConText.Text = ("Testing the USB borad... OK!  Dev Num : " + sTotChnlNum.ToString());

                sRtn = SPdbUSBm.spSetupAllChannels();
                Debug.Assert(sRtn < 0, "spSetupAllChannels Error");

                for (int i = 0; i < sTotChnlNum; i++)
                {
                    pDeviceInfo[i].Model = new StringBuilder(100);
                    pDeviceInfo[i].Serial = new StringBuilder(100);

                    SPdbUSBm.spDevInfo(pDeviceInfo[i].Model, pDeviceInfo[i].Serial, (short)i);     //Get Device Infomation
                    cbSelChannel.Items.Add("Ch#" + i.ToString()+" : " + pDeviceInfo[i].Model.ToString()+"-"+ pDeviceInfo[i].Serial.ToString());

                    //Include spInitGivenChannel
                    DeviceSetup(pDeviceInfo[i].Model.ToString(), (short)i);

                    if(pDeviceInfo[i].Model.ToString() == "SM304")
                    {
                        sRtn = SPdbUSBm.spSetTEC(1,(short)i);
                        Debug.Assert(sRtn < 0, "spSetupAllChannels Error");

                        sRtn = SPdbUSBm.spSelectCF(1, (short)i);
                        Debug.Assert(sRtn < 0, "spSetupAllChannels Error");
                    }

                    if (SPdbUSBm.spGetDevIsNew((short)i) == 1)
                    {
                        SPdbUSBm.spSetIntMode((short)InternalTriggerMode.SP_INTMODE_SWTRIGGER, pDeviceInfo[i].lIntTime, (short)i);
                        rbSWTrigger.Checked = true;
                    }
                    else
                    {
                        SPdbUSBm.spSetTrgEx((short)TriggerMode.SP_TRIGGER_INTERNAL, (short)i);
                        rbFreeRunPrev.Checked = true;
                    }
                }

                cbSelChannel.SelectedIndex = 0;
                CurrentCh = 0;
                EnableCtl(true);

            }
            else
            {
                CheckConText.Text = ("The USB board does not work correctly.");
            }

        }
        public short DeviceSetup(string Model, short Channel)
        {
            if (Model.Contains("SM24"))
            {
                pDeviceInfo[Channel].nTOTPixelNo = 2080;
                pDeviceInfo[Channel].nRealPixelNo = 2048;
                pDeviceInfo[Channel].EffectivePixelIndex = 32;
                pDeviceInfo[Channel].CCDType = (short)CCDType.SP_CCD_SONY;
            }
            else if (Model.Contains("SM44"))
            {
                pDeviceInfo[Channel].nTOTPixelNo = 3680;
                pDeviceInfo[Channel].nRealPixelNo = 3648;
                pDeviceInfo[Channel].EffectivePixelIndex = 32;
                pDeviceInfo[Channel].CCDType = (short)CCDType.SP_CCD_TOSHIBA;
            }
            else if (Model.Contains("SM303"))
            {
                pDeviceInfo[Channel].nTOTPixelNo = 1056;
                pDeviceInfo[Channel].nRealPixelNo = 1024;
                pDeviceInfo[Channel].EffectivePixelIndex = 10;
                pDeviceInfo[Channel].CCDType = (short)CCDType.SP_CCD_PDA;
            }
            else if (Model.Contains("SM304"))
            {
                pDeviceInfo[Channel].nTOTPixelNo = 512;
                pDeviceInfo[Channel].nRealPixelNo = 512;
                pDeviceInfo[Channel].EffectivePixelIndex = 0;
                pDeviceInfo[Channel].CCDType = (short)CCDType.SP_CCD_G9212;
            }
            else if (Model.Contains("SM642"))
            {
                pDeviceInfo[Channel].nTOTPixelNo = 2080;
                pDeviceInfo[Channel].nRealPixelNo = 2048;
                pDeviceInfo[Channel].EffectivePixelIndex = 10;
                pDeviceInfo[Channel].CCDType = (short)CCDType.SP_CCD_S10420;
            }
            pDeviceInfo[Channel].USBSpeed = 2;
            pDeviceInfo[Channel].lIntTime = 30;
            pDeviceInfo[Channel].lTimeAvg = 1;
            

            return SPdbUSBm.spInitGivenChannel(pDeviceInfo[Channel].CCDType, Channel);

        }
        private void cbSelChannel_SelectedIndexChanged(object sender, EventArgs e)
        {
            short sRtn = 0;
            CurrentCh = (short)cbSelChannel.SelectedIndex;

            nIntTime.Value = pDeviceInfo[CurrentCh].lIntTime;
            nTimeAvg.Value = pDeviceInfo[CurrentCh].lTimeAvg;

            if (pDeviceInfo[CurrentCh].Model.ToString().Contains("SM44"))
            {
                sRtn = SPdbUSBm.spSetDblIntEx((double)pDeviceInfo[CurrentCh].lIntTime, (short)CurrentCh);
                Debug.Assert(sRtn < 0, "spSetDblEx Error");

            }
            else
            {
                sRtn = SPdbUSBm.spSetIntEx(pDeviceInfo[CurrentCh].lIntTime, (short)CurrentCh);
                Debug.Assert(sRtn<0, "spSetIntEx Error");

                if (pDeviceInfo[CurrentCh].Model.ToString().Contains("SM304"))
                    btnReadDark.Enabled = false;
            }
        }

        private void nIntTime_ValueChanged(object sender, EventArgs e)
        {
            int sRtn;

            if (sTotChnlNum <= 0)
                return;
            pDeviceInfo[CurrentCh].lIntTime = (int)nIntTime.Value;

            if (pDeviceInfo[CurrentCh].Model.ToString().Contains("SM44"))
            {
                sRtn = SPdbUSBm.spSetDblIntEx((double)pDeviceInfo[CurrentCh].lIntTime, (short)CurrentCh);
                Debug.Assert(sRtn < 0, "spSetDblIntEx Error");
            }
            else
            {
                sRtn = SPdbUSBm.spSetIntEx(pDeviceInfo[CurrentCh].lIntTime, (short)CurrentCh);
                Debug.Assert(sRtn < 0, "spSetIntEx Error");
            }
        }

        public void Graph_Click(object sender, EventArgs e)
        {
            int sRtn;

            Graph cGraph = new Graph();
            cGraph.pParent = this;
            cGraph.TOTNo = pDeviceInfo[CurrentCh].nTOTPixelNo;
            cGraph.RealNo = pDeviceInfo[CurrentCh].nRealPixelNo;

            double[] WLTableArray = new double[pDeviceInfo[CurrentCh].nRealPixelNo];
            double[] dWL = new double[pDeviceInfo[CurrentCh].nRealPixelNo];
            
            sRtn = SPdbUSBm.spGetWLTable(WLTableArray, CurrentCh);
            Debug.Assert(sRtn < 0, "spGetWLTable");

            if (rb_UserData.Checked == true)
            {
                for (int i = 0; i < pDeviceInfo[CurrentCh].nRealPixelNo; i++)
                {
                    SPdbUSBm.spPolyCalc(dCoefficient, 3, (i + 1), dWL);
                    cGraph.dWL = dWL;
                }
            }

            cGraph.DataArray = new Int32[cGraph.TOTNo];
            cGraph.YPlotDataArray = new Int32[cGraph.RealNo];

            if (cGraph.DataThread == null)
            {
                cGraph.DataThread = new Thread(new ThreadStart(cGraph.Woker));
                cGraph.DataThread.Start();

            }
            if (cGraph.DataThread.IsAlive == false)
            {
                cGraph.DataThread = new Thread(new ThreadStart(cGraph.Woker));
                cGraph.DataThread.Start();
            }

            cGraph.WLTableArray = WLTableArray;
            cGraph.ShowDialog();    
        }
        public void GetDataAll_Click(object sender, EventArgs e)
        {
            //Thread GetData = new Thread(new ThreadStart(GetDataNSave));
            //GetData.Start();
            GetDataNSave();
        }
        private void GetDataNSave()
        {

            int sRtn;

            DeviceInfo getDevInfo = pDeviceInfo[CurrentCh];

            Int32[] DataArray = new Int32[getDevInfo.nTOTPixelNo];
            double[] WLTableArray = new double[getDevInfo.nRealPixelNo];
            double[] dWL = new double[getDevInfo.nRealPixelNo];
            Int32[] tempArray = new Int32[getDevInfo.nTOTPixelNo];

            string savePath = AppDomain.CurrentDomain.BaseDirectory + SaveFileName.Text + ".txt";
            string text = "Index\tWavelength(nm)\t\tIntensity" + "\r\n";
            System.IO.File.WriteAllText(savePath, text);

            sRtn = SPdbUSBm.spGetWLTable(WLTableArray, CurrentCh);
            Debug.Assert(sRtn < 0, "spGetWLTable Error");

            if (!bExtTrigger)       //When in internal trigger mode
            {
                for (int i = 0; i < getDevInfo.lTimeAvg; i++)
                {
                    if (ChkOutTrigger.Checked)
                    {
                        sRtn = SPdbUSBm.spReadDataExOutTrg(DataArray, CurrentCh);
                        Debug.Assert(sRtn < 0, "spReadDataExOutTrg Error");
                    }

                    else
                    {
                        sRtn = SPdbUSBm.spReadDataEx(DataArray, CurrentCh);
                        Debug.Assert(sRtn < 0, "spReadDataEx Error");

                        for (int j = 0; j < getDevInfo.nRealPixelNo; j++)
                            tempArray[j + getDevInfo.EffectivePixelIndex] += DataArray[j + getDevInfo.EffectivePixelIndex];
                    }
                }
            }
            else                                   //When in external trigger mode
            {
                for (int i = 0; i < getDevInfo.lTimeAvg; i++)
                {
                    do
                    {
                        sRtn = SPdbUSBm.spReadDataEx(DataArray, CurrentCh);

                    } while (sRtn == 99);

                    for (int j = 0; j < getDevInfo.nRealPixelNo; j++)
                        tempArray[j + getDevInfo.EffectivePixelIndex] += DataArray[j + getDevInfo.EffectivePixelIndex];
                }
            }

                if (getDevInfo.lTimeAvg == 1)
                {
                    System.Buffer.BlockCopy(tempArray, sizeof(Int32) * getDevInfo.EffectivePixelIndex, DataArray, 0, sizeof(Int32) * getDevInfo.nRealPixelNo);
                }
                else
                {
                    for (int j = 0; j < getDevInfo.nRealPixelNo; j++)
                    {
                        DataArray[j + getDevInfo.EffectivePixelIndex] = (int)(tempArray[j + getDevInfo.EffectivePixelIndex] / (double)getDevInfo.lTimeAvg + 0.5);
                    }
                }


                if (rb_UserData.Checked == true)
                {
                    for (int j = 0; j < getDevInfo.nRealPixelNo; j++)
                    {

                        SPdbUSBm.spPolyCalc(dCoefficient, 3, (j + 1), dWL);
                        string textValue = (j + 1).ToString() + "\t" + dWL[0].ToString("####.####") + "\t\t" + DataArray[j + getDevInfo.EffectivePixelIndex].ToString("####.####") + "\r\n";
                        System.IO.File.AppendAllText(savePath, textValue, Encoding.Default);
                    }
                }
                else if (rb_FactoryData.Checked == true)
                {

                    for (int j = 0; j < getDevInfo.nRealPixelNo; j++)
                    {
                        string textValue = (j + 1).ToString() + "\t" + WLTableArray[j].ToString("####.####") + "\t\t" + DataArray[j + getDevInfo.EffectivePixelIndex].ToString("####.####") + "\r\n";
                        System.IO.File.AppendAllText(savePath, textValue, Encoding.Default);
                    }
                }

        }
        
        private void Close_Click_1(object sender, EventArgs e)
        {
            this.Close();
        }
        private void EnableCtl(bool state)
        {
   
            GetDataAll.Enabled = state;
            Graph.Enabled = state;
            SaveFileName.Enabled = state;
            nIntTime.Enabled = state;
            nTimeAvg.Enabled = state;
            rb_FactoryData.Checked = state;
            CheckConnections.Enabled = state;

            if (state)
            {
                if (pDeviceInfo[CurrentCh].Model.ToString() == "SM304")
                {
                    btnReadDark.Enabled = true;
                    chkBaselineCorreection.Enabled = true;
                    chkOffsetCorrection.Enabled = true;
                }
            }
        }
       


        public void rb_UserData_CheckedChanged(object sender, EventArgs e)
        {

            //SM240, SM245 Example
            int nCalibNo;
            DeviceInfo getDevInfo = pDeviceInfo[CurrentCh];
          
            nCalibNo = 12;
            double[] dWaveLength = new double[nCalibNo];
            double[] dPixelNo = new double[nCalibNo];
            double[] dRCoefficient = new double[5];
            double[] dCoefficient = new double[5];
            double[] fData = new double[getDevInfo.nRealPixelNo];
            dWaveLength[0] = 253.7; dPixelNo[0] = 348;
            dWaveLength[1] = 313.2; dPixelNo[1] = 465;
            dWaveLength[2] = 365.0; dPixelNo[2] = 567;
            dWaveLength[3] = 404.7; dPixelNo[3] = 643;
            dWaveLength[4] = 435.8; dPixelNo[4] = 703;
            dWaveLength[5] = 546.1; dPixelNo[5] = 910;
            dWaveLength[6] = 577.0; dPixelNo[6] = 967;
            dWaveLength[7] = 579.1; dPixelNo[7] = 971;
            dWaveLength[8] = 696.5; dPixelNo[8] = 1186;
            dWaveLength[9] = 763.5; dPixelNo[9] = 1306;
            dWaveLength[10] = 811.5; dPixelNo[10] = 1392;
            dWaveLength[11] = 912.3; dPixelNo[11] = 1570;

            SPdbUSBm.spPolyFit(dPixelNo,dWaveLength, 12, dCoefficient, 3);


        }
        private void TimeAverage_TextChanged(object sender, EventArgs e)
        {
            pDeviceInfo[CurrentCh].lTimeAvg = (int)nTimeAvg.Value;
        }

        private void cbSelExOutTrgPin_SelectedIndexChanged(object sender, EventArgs e)
        {
            short sSelPin = (short)cbSelExOutTrgPin.SelectedIndex;
            short sRtn;

            sRtn = SPdbUSBm.spSetOutTrgPin(sSelPin, (short)CurrentCh);
            Debug.Assert(sRtn < 0, "spSetExOutTrgPin Error");
        }

        private void btnReadDark_Click(object sender, EventArgs e)
        {
            int[] lDarkData;
            short sRtn;

            lDarkData = new int[pDeviceInfo[CurrentCh].nTOTPixelNo];

            sRtn = SPdbUSBm.spReadDark(lDarkData,(int)nTimeAvg.Value, (short)CurrentCh);
            Debug.Assert(sRtn < 0, "spSetExOutTrgPin Error");

            chkBaselineCorreection.Enabled = true;
            chkOffsetCorrection.Enabled = true;
        }

        private void chkBaselineCorreection_CheckedChanged(object sender, EventArgs e)
        {
            short sRtn;
            short sOffset = 2000;
            double dGain = 1.5;

            sRtn = SPdbUSBm.spSetBaseLineCorrection(chkBaselineCorreection.Checked, sOffset,dGain, (short)CurrentCh);
            Debug.Assert(sRtn < 0, "spSetBaseLineCorrection Error");
        }

        private void chkOffsetCorrection_CheckedChanged(object sender, EventArgs e)
        {
            short sRtn;

            sRtn = SPdbUSBm.spSetOffsetCorrection(chkOffsetCorrection.Checked, (short)CurrentCh);
            Debug.Assert(sRtn < 0, "spSetOffsetCorrection Error");
        }

        private void btnTriggerMode_Click(object sender, EventArgs e)
        {
            short sRtn;
            short sDevVersion;

            sDevVersion = SPdbUSBm.spGetDevIsNew(CurrentCh);
            bExtTrigger = false;

            if(sDevVersion == 1)
            {
                if (rbFreeRunPrev.Checked)
                    sRtn = SPdbUSBm.spSetIntMode((short)InternalTriggerMode.SP_INTMODE_FREERUN_PREV, pDeviceInfo[CurrentCh].lIntTime, CurrentCh);
                else if(rbFreeRunNext.Checked)
                    sRtn = SPdbUSBm.spSetIntMode((short)InternalTriggerMode.SP_INTMODE_FREERUN_NEXT, pDeviceInfo[CurrentCh].lIntTime, CurrentCh);
                else if(rbSWTrigger.Checked)
                    sRtn = SPdbUSBm.spSetIntMode((short)InternalTriggerMode.SP_INTMODE_SWTRIGGER, pDeviceInfo[CurrentCh].lIntTime, CurrentCh);
                else if(rbExternalTrgFalling.Checked)
                {
                    bExtTrigger = true;
                    sRtn = SPdbUSBm.spSetExtEdgeMode((short)ExternalTriggerEdgeMode.SP_EXTEDGE_FALLING, CurrentCh);
                }
                else if(rbExternalTrgRising.Checked)
                {
                    bExtTrigger = true;
                    sRtn = SPdbUSBm.spSetExtEdgeMode((short)ExternalTriggerEdgeMode.SP_EXTEDGE_RISING, CurrentCh);
                }
            }
            else
            {
                if (rbFreeRunPrev.Checked)
                    sRtn = SPdbUSBm.spSetTrgEx((short)TriggerMode.SP_TRIGGER_INTERNAL, CurrentCh);
                else if(rbFreeRunPrev.Checked || rbSWTrigger.Checked)
                    MessageBox.Show(string.Format("The device of USB Port #{0} does not support.",CurrentCh));
                else if(rbExternalTrgFalling.Checked)
                {
                    bExtTrigger = true;
                    sRtn = SPdbUSBm.spSetExtEdgeMode((short)ExternalTriggerEdgeMode.SP_EXTEDGE_FALLING, CurrentCh);
                }
                else if(rbExternalTrgRising.Checked)
                    MessageBox.Show(string.Format("The device of USB Port #{0} does not support.", CurrentCh));
            }
        }
    }
}




    

