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.Windows.Forms.DataVisualization.Charting;
using System.Threading;
using System.IO;
using System.Diagnostics;

namespace N_Series_SDK
{
    public partial class BurstMode : Form
    {
        public NSeries pParent;
        private Series s1;
        public short sInitTrgMode;
        public int iSelDev;
        public Thread ReadMemDataThread;
        public Thread SyncroContinousReadThrd;
        public int[][] m_lpDataList;
        public int iReadCnt;
        public int iLoadCnt;
        public bool bSyncReadStop = true;

        public BurstMode()
        {
            InitializeComponent();

            s1 = new Series("Intensity");
            s1.IsValueShownAsLabel = true;
            s1.ChartType = SeriesChartType.FastLine;
            s1.IsVisibleInLegend = false;
            s1.Color = Color.Red;
            chartDataList.Series.Add(s1);
            
        }

        private void btnMeasureStart_Click(object sender, EventArgs e)
        {
            short sRtn;
            short sChannel = pParent.m_stDeviceInfo[iSelDev].sChannel;

            if(!bSyncReadStop)
            {
                bSyncReadStop = true;
                btnMeasureStart.Text = "Start";                
                SyncroContinousReadThrd.Abort();
                sRtn = pParent.m_KSPLIB_NSeries.NStopSyncTrgData(sChannel);

                return;
            }

            if ((int)nmDataCount.Value > 0)
            {
                if (chkSyncTriggerMode.Checked)
                {
                    if (pParent.m_stDeviceInfo[iSelDev].sTrgMode != (short)KSPLIB_NSeries.emTriggerMode.SP_TRIGGER_SYNCHRONOUS)
                        sRtn = pParent.m_KSPLIB_NSeries.NSetTrgMode((short)KSPLIB_NSeries.emTriggerMode.SP_TRIGGER_SYNCHRONOUS, sChannel);

                    pParent.m_stDeviceInfo[iSelDev].sTrgMode = (short)KSPLIB_NSeries.emTriggerMode.SP_TRIGGER_SYNCHRONOUS;

                    sRtn = pParent.m_KSPLIB_NSeries.NStartSyncTrgData((int)nmDataCount.Value, sChannel);
                }
                else
                    sRtn = pParent.m_KSPLIB_NSeries.NStartBurstData((int)nmDataCount.Value, sChannel);

                if (sRtn < 0)
                {
                    if (chkSyncTriggerMode.Checked)
                        MessageBox.Show("Error Function : NStartSyncTrgData().\nError String : " + pParent.m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    else
                        MessageBox.Show("Error Function : NStartBurstData().\nError String : " + pParent.m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);

                    return;
                }

                iReadCnt = (int)nmDataCount.Value;
                iLoadCnt = 0;

                m_lpDataList = new int[iReadCnt][];

                for (int i = 0; i < iReadCnt; i++)
                    m_lpDataList[i] = new int[pParent.m_stDeviceInfo[iSelDev].iTotPixel];

                nmSelDataNum.Maximum = iReadCnt;
                tbSlideDataList.Maximum = iReadCnt;

                if (chkSyncTriggerMode.Checked)
                    txtStatusInfo.Text = "\r\nSynchronous Trigger measurement start.\r\nRead Count : " + iReadCnt.ToString();
                else
                    txtStatusInfo.Text = "\r\nBurst Mode measurement start.\r\nRead Count : " + iReadCnt.ToString();
            }
            else if ((int)nmDataCount.Value == 0)
            {
                if (chkSyncTriggerMode.Checked)
                {
                    if (pParent.m_stDeviceInfo[iSelDev].sTrgMode != (short)KSPLIB_NSeries.emTriggerMode.SP_TRIGGER_SYNCHRONOUS)
                        sRtn = pParent.m_KSPLIB_NSeries.NSetTrgMode((short)KSPLIB_NSeries.emTriggerMode.SP_TRIGGER_SYNCHRONOUS, sChannel);

                    pParent.m_stDeviceInfo[iSelDev].sTrgMode = (short)KSPLIB_NSeries.emTriggerMode.SP_TRIGGER_SYNCHRONOUS;

                    btnMeasureStart.Text = "Stop";
                    bSyncReadStop = false;

                    SyncroContinousReadThrd = new Thread(new ThreadStart(SynchroContinousReadFunc));
                    SyncroContinousReadThrd.Start();
                }
                else
                    txtStatusInfo.Text = "\r\nFor Burst Mode, Data Count must be greater than 0.";
            }
        }

        public void SynchroContinousReadFunc()
        {
            short sRtn;
            short sChannel = pParent.m_stDeviceInfo[iSelDev].sChannel;
            int[] iDataArray = new int[pParent.m_stDeviceInfo[iSelDev].iTotPixel];

            while (!bSyncReadStop)
            {
                sRtn = pParent.m_KSPLIB_NSeries.NReadDataEx(iDataArray, sChannel);
                if (sRtn < 0)
                {
                    MessageBox.Show("Error Function : NReadDataEx().\nError String : " + pParent.m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;
                }

                this.Invoke((new MethodInvoker(delegate
                {
                    s1.Points.Clear();

                    for (int i = 0; i < pParent.m_stDeviceInfo[pParent.selDev].iRealPixel; i++)
                    {
                        s1.Points.AddXY(pParent.m_stDeviceInfo[pParent.selDev].dWLTable[i], iDataArray[i + pParent.m_stDeviceInfo[pParent.selDev].iDummyPixel]);

                        txtStatusInfo.Text = "Successful data loaded from memory." +
                                             "\r\nExposure Delay : " + iDataArray[1].ToString() + " us" +
                                             "\r\nTrigger Interval : " + iDataArray[2].ToString() + " us";                                             
                    }
                })));
            }
        }

        private void btnGetSingleDataFromMem_Click(object sender, EventArgs e)
        {
            short sRtn;
            short sChannel = pParent.m_stDeviceInfo[iSelDev].sChannel;

            if (iReadCnt == iLoadCnt)
            {
                MessageBox.Show("Error! Empty memory.\nFailed to data loaded from memory." , "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            sRtn = pParent.m_KSPLIB_NSeries.NGetBurstSingleData(m_lpDataList[iLoadCnt], sChannel);
            if (sRtn < 0)
            {
                if (sRtn == (short)KSPLIB_NSeries.emErrorCode.SP_ERROR_MEMORY_EMPTY)
                    MessageBox.Show("Error! Empty memory.\nFailed to data loaded from memory.\nError String : " + pParent.m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                else
                    MessageBox.Show("Error Function : NGetBurstSingleData().\nError String : " + pParent.m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);

                return;
            }                       

            iLoadCnt++;
            Plotchart(iLoadCnt - 1);
            txtStatusInfo.Text = "Successful data loaded from memory.\r\nLoad Count : " + iLoadCnt.ToString() + "/" + iReadCnt.ToString() +
                                "\r\nCount : " + m_lpDataList[iLoadCnt - 1][0].ToString() +
                                "\r\nExposure Delay : " + m_lpDataList[iLoadCnt - 1][1].ToString() + " us" +
                                "\r\nTrigger Interval : " + m_lpDataList[iLoadCnt - 1][2].ToString() + " us";                                

            if (iReadCnt == iLoadCnt)
                sRtn = pParent.m_KSPLIB_NSeries.NStopSyncTrgData(sChannel);
        }

        private void btnGetDataFromMem_Click(object sender, EventArgs e)
        {
            short sRtn;
            short sChannel = pParent.m_stDeviceInfo[iSelDev].sChannel;
            int[][] lTempData;

            Stopwatch swReadData = new Stopwatch();

            lTempData = new int[(int)nmDataCount.Value][];

            for (int i = 0; i < iReadCnt; i++)
                lTempData[i] = new int[pParent.m_stDeviceInfo[iSelDev].iTotPixel];

            swReadData.Start();
            sRtn = pParent.m_KSPLIB_NSeries.NGetBurstData((int)nmDataCount.Value, lTempData, sChannel);
            swReadData.Stop();
            if (sRtn < 0)
            {
                if (sRtn == (short)KSPLIB_NSeries.emErrorCode.SP_ERROR_MEMORY_EMPTY)
                    MessageBox.Show("Error! Empty memory.\nFailed to data loaded from memory.\nError String : " + pParent.m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                else
                    MessageBox.Show("Error Function : NGetBurstSingleData().\nError String : " + pParent.m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);

                return;
            }

            for (int i = 0; i < sRtn; i++)
                Array.Copy(lTempData[i], m_lpDataList[i + iLoadCnt], pParent.m_stDeviceInfo[iSelDev].iTotPixel);

            iLoadCnt += sRtn;         

            if (sRtn != 0)
                Plotchart(iLoadCnt - 1);
            txtStatusInfo.Text = "\r\nSuccessful data loaded from memory.\r\nLoad Count : " + iLoadCnt.ToString() + "/" + iReadCnt.ToString();

            if (iReadCnt == iLoadCnt)
            {
                sRtn = pParent.m_KSPLIB_NSeries.NStopSyncTrgData(sChannel);
            }
        }

        public void Plotchart(int iIndex)
        {
            s1.Points.Clear();

            for (int i = 0; i < pParent.m_stDeviceInfo[pParent.selDev].iRealPixel; i++)
            {
                s1.Points.AddXY(pParent.m_stDeviceInfo[pParent.selDev].dWLTable[i], m_lpDataList[iIndex][i + pParent.m_stDeviceInfo[pParent.selDev].iDummyPixel]);
            }

            nmSelDataNum.Value = (int)(iIndex + 1);
            lbDataInfo.Text = (iIndex + 1).ToString() + "/" + iReadCnt.ToString();
        }


        private void btnExport_Click(object sender, EventArgs e)
        {
            if (iReadCnt == 0 || iLoadCnt == 0)
            {
                MessageBox.Show("Memory is empty because there is no measured data.", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            SaveFileDialog saveFileDialog = new SaveFileDialog();

            saveFileDialog.Title = "Select Save File Path";
            saveFileDialog.OverwritePrompt = true;
            saveFileDialog.Filter = "CSV File(*.csv)|*.csv";
            saveFileDialog.FileName = "SynchronousTriggerDataFile.csv";
            saveFileDialog.InitialDirectory = System.Windows.Forms.Application.StartupPath;

            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                string strSaveText = "";

                StreamWriter swFile;

                swFile = File.CreateText(saveFileDialog.FileName);

                for (int i = 0; i < pParent.m_stDeviceInfo[iSelDev].iRealPixel; i++)
                    strSaveText += "," + pParent.m_stDeviceInfo[iSelDev].dWLTable[i].ToString();

                swFile.WriteLine(strSaveText);

                for (int i = 0; i < iLoadCnt; i++)
                {
                    strSaveText = (i + 1).ToString();

                    for (int j = 0; j < pParent.m_stDeviceInfo[iSelDev].iRealPixel; j++)
                        strSaveText += "," + m_lpDataList[i][j + pParent.m_stDeviceInfo[iSelDev].iDummyPixel].ToString();

                    swFile.WriteLine(strSaveText);
                }

                txtStatusInfo.Text = "\r\nSuccessful export csv file.";

                swFile.Close();
            }
        }

        private void tbSlideDataList_ValueChanged(object sender, EventArgs e)
        {
            if ((int)tbSlideDataList.Value != (int)nmSelDataNum.Value)
            {
                short sChannel = pParent.m_stDeviceInfo[iSelDev].sChannel;

                nmSelDataNum.Value = (int)tbSlideDataList.Value;
                Plotchart((int)tbSlideDataList.Value - 1);                              

                txtStatusInfo.Text = "Measure Data Info : " + iLoadCnt.ToString() + "/" + iReadCnt.ToString() +
                                     "\r\nCount : " + m_lpDataList[(int)tbSlideDataList.Value - 1][0].ToString() +
                                     "\r\nExposure Delay : " + m_lpDataList[(int)tbSlideDataList.Value - 1][1].ToString() + " us" +
                                     "\r\nTrigger Interval : " + m_lpDataList[(int)tbSlideDataList.Value - 1][2].ToString() + " us";
            } 
        }

        private void nmSelDataNum_ValueChanged(object sender, EventArgs e)
        {
            if ((int)tbSlideDataList.Value != (int)nmSelDataNum.Value)
            {
                short sChannel = pParent.m_stDeviceInfo[iSelDev].sChannel;

                tbSlideDataList.Value = (int)nmSelDataNum.Value;
                Plotchart((int)nmSelDataNum.Value - 1);

                txtStatusInfo.Text = "Measure Data Info : " + iLoadCnt.ToString() + "/" + iReadCnt.ToString() +
                                     "\r\nCount : " + m_lpDataList[(int)nmSelDataNum.Value - 1][0].ToString() +
                                     "\r\nExposure Delay : " + m_lpDataList[(int)nmSelDataNum.Value - 1][1].ToString() + " us" +
                                     "\r\nTrigger Interval : " + m_lpDataList[(int)nmSelDataNum.Value - 1][2].ToString() + " us";
            }
        }

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

            sRtn = pParent.m_KSPLIB_NSeries.NStopSyncTrgData(pParent.m_stDeviceInfo[iSelDev].sChannel);
            if(sRtn < 0)
                MessageBox.Show("Error Function : NStopSyncTrgData().\nError String : " + pParent.m_KSPLIB_NSeries.NGetErrorString(sRtn).ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
}
