using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Origin;

namespace Origin3DScatter
{
    public partial class Form3DScatter : Form
    {
        private double m_dX, m_dY, m_dZ;
        private Origin.ApplicationSI m_pOrigin;
        private Origin.Worksheet m_pWorksheet;
        private Origin.GraphLayer m_pGraphLayer;
        private Origin.DataPlot m_pDataPlot;
        private Random rnd;

        public Form3DScatter()
        {
            InitializeComponent();
        }

        private void button_Init_Click(object sender, EventArgs e)
        {
            try
            {
                m_pOrigin = new ApplicationSIClass();
            }
            catch (System.Exception ex)
            {
                String strMsg = "Failed to connect to an existing Origin instance." + "\n" + ex.Message;
                MessageBox.Show(strMsg, "Error");
                return;
            }
            m_pOrigin.Visible = MAINWND_VISIBLE.MAINWND_SHOW;

            try
            {
                String strWkName = "ScatterData";
                m_pWorksheet = m_pOrigin.FindWorksheet(strWkName);
                if ( m_pWorksheet == null ) //if check don't exist, create workbook
                    strWkName = (String)m_pOrigin.CreatePage((int)Origin.PAGETYPES.OPT_WORKSHEET, strWkName, "Origin", 2);
                m_pWorksheet = (Worksheet)m_pOrigin.WorksheetPages[strWkName].Layers[0];
                
                //prepare XYZ column for putting data
                m_pWorksheet.Cols = 3;

                Column colA = m_pWorksheet.Columns[0];
                colA.Type = COLTYPES.COLTYPE_X;

                Column colB = m_pWorksheet.Columns[1];
                colB.Type = COLTYPES.COLTYPE_Y;

                Column colC = m_pWorksheet.Columns[2];
                colC.Type = COLTYPES.COLTYPE_Z;

                //prepare graph layer for plotting
                String strGrName = "3DScatterPlot"; //if check don't exist, create it.
                m_pGraphLayer = m_pOrigin.FindGraphLayer(strGrName);
                if ( m_pGraphLayer == null )
                    strGrName = (String)m_pOrigin.CreatePage((int)Origin.PAGETYPES.OPT_GRAPH, strGrName, "3D", 2); //3D scatter need "3D" template
                m_pGraphLayer = (GraphLayer)m_pOrigin.GraphPages[strGrName].Layers[0];
                
                //parepare XYZDataRange
                DataRange drXYZ = m_pWorksheet.NewDataRange(0, 0, -1, -1);

                //plot 3D scatter on GraphLayer
                String strPlotName = "ScatterData_C"; //if exists, don't add new plot, plot name is related to workbook name and column name.
                m_pDataPlot = m_pGraphLayer.DataPlots[strPlotName];
                if ( m_pDataPlot == null )
                {
                    m_pDataPlot = m_pGraphLayer.DataPlots.Add(drXYZ, PLOTTYPES.IDM_PLOT_3D_SCATTER);
                }

                //force axis rescale as auto to make plot visible
                m_pGraphLayer.Execute("layer.x.rescale=3");
                m_pGraphLayer.Execute("layer.y.rescale=3");
                m_pGraphLayer.Execute("layer.z.rescale=3");
           }
            catch (System.Exception ex)
            {
                String strMsg = "Failed to prepare pages for plotting." + "\n" + ex.Message;
                MessageBox.Show(strMsg, "Error");
            }
            rnd = new Random();
            timer_AutoSend.Enabled = false;
            textBox_Message.Text = "Click \"Start\" to send auto generated data and update the plot.";
            enableControls(true);
        }

        private void enableControls(bool bConnected)
        {
            button_StartStop.Enabled = bConnected;
            button_Init.Enabled = !bConnected;
        }

        private void button_StartStop_Click(object sender, EventArgs e)
        {
            if (timer_AutoSend.Enabled)
            {
                button_StartStop.Text = "Start";
                timer_AutoSend.Stop();
                textBox_Message.Text = "Click \"Start\" to continue sending data.";
            }
            else
            {
                button_StartStop.Text = "Stop";
                timer_AutoSend.Interval = Int32.Parse(comboBox_TimeDelay.Text);
                timer_AutoSend.Start();
                textBox_Message.Text = "Click \"Stop\" to stop sending data.";
            }
        }

        private void timer_AutoSend_Tick(object sender, EventArgs e)
        {
            int nFactor = m_pWorksheet.Rows;
            m_dX = rnd.NextDouble() * nFactor;
            m_dY = rnd.NextDouble() * nFactor;
            m_dZ = rnd.NextDouble() * nFactor;

            InputX.Text = m_dX.ToString();
            InputY.Text = m_dY.ToString();
            InputZ.Text = m_dZ.ToString();

            double [,] Data = new double[1,3];
            Data[0, 0] = m_dX;
            Data[0, 1] = m_dY;
            Data[0, 2] = m_dZ;
            m_pWorksheet.SetData(Data, -1, 0); //append
        }

        private void button_SendOnce_Click(object sender, EventArgs e)
        {
            double[,] Data = new double[1, 3];

            String strX = InputX.Text;
            String strY = InputY.Text;
            String strZ = InputZ.Text;

            Data[0, 0] = strX.Length == 0 ? 0 : Double.Parse(strX);
            Data[0, 1] = strY.Length == 0 ? 0 : Double.Parse(strY);
            Data[0, 2] = strZ.Length == 0 ? 0 : Double.Parse(strZ);

            m_pWorksheet.SetData(Data, -1, 0);
        }

        private void Form3DScatter_Load(object sender, EventArgs e)
        {
            textBox_Message.Text = "Click \"Connect to Origin and Prepare Pages\" to connect to an existing instance of Origin and to create the pages for plotting.";
            enableControls(false);
        }

        private void InputX_KeyPress(object sender, KeyPressEventArgs e)
        {
            if ( (e.KeyChar < '0' || e.KeyChar > '9') && e.KeyChar != '.' && (Keys)e.KeyChar != Keys.Back )
            {
                e.Handled = true;
            }
            else if ( e.KeyChar == '.' )
            {
                String str = InputX.Text;
                if (str.Contains(".")) //already has
                    e.Handled = true;
            }
        }

        private void InputY_KeyPress(object sender, KeyPressEventArgs e)
        {
            if ((e.KeyChar < '0' || e.KeyChar > '9') && e.KeyChar != '.' && (Keys)e.KeyChar != Keys.Back)
            {
                e.Handled = true;
            }
            else if (e.KeyChar == '.')
            {
                String str = InputY.Text;
                if (str.Contains(".")) //already has
                    e.Handled = true;
            }
        }

        private void InputZ_KeyPress(object sender, KeyPressEventArgs e)
        {
            if ((e.KeyChar < '0' || e.KeyChar > '9') && e.KeyChar != '.' && (Keys)e.KeyChar != Keys.Back)
            {
                e.Handled = true;
            }
            else if (e.KeyChar == '.')
            {
                String str = InputZ.Text;
                if (str.Contains(".")) //already has
                    e.Handled = true;
            }
        }

        private void Form3DScatter_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (m_pOrigin != null)
            {
                System.Runtime.InteropServices.Marshal.FinalReleaseComObject(m_pOrigin);
                m_pOrigin = null;
            }
        }
    }
}