using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Xml;
using System.IO;

namespace TcBode
{
    /// <summary>
    /// Storage of one Bode diagram from Beckhoff TwinCAT tool
    /// </summary>
    public class TcBodeData
    {
        private string iTitle;
        private string iName;
        private string iCycleTime;
        private string iMode;
        private string iMeasureTime;
        private string iSignalAmplitudePosition;
        private string iSignalAmplitudeVelocity;
        private string iSignalAmplitudeTorque;
        private string iBaseAmplitude;
        private string iTorqueOffset;
        private string iBaseFrequency;
        private string iDeadTime;
        private string iProportionalGain;
        private string iIntegralTime;
        private string iMinFrequency;
        private string iMaxFrequency;
        private string iFrequencySteps;

        /// <summary>
        /// Title
        /// </summary>
        public string TcB_Title
        {
            get { return iTitle; }
            set { iTitle = value; }
        }

        /// <summary>
        /// Name
        /// </summary>
        public string TcB_Name
        {
            get { return iName; }
            set { iName = value; }
        }

        /// <summary>
        /// Cycle time
        /// </summary>
        public string TcB_CycleTime
        {
            get { return iCycleTime; }
            set { iCycleTime = value; }
        }

        /// <summary>
        /// Mode
        /// </summary>
        public string TcB_Mode
        {
            get { return iMode; }
            set { iMode = value; }
        }

        /// <summary>
        /// Measure time
        /// </summary>
        public string TcB_MeasureTime
        {
            get { return iMeasureTime; }
            set { iMeasureTime = value; }
        }

        /// <summary>
        /// Amplitude position signal
        /// </summary>
        public string TcB_SignalAmplitudePosition
        {
            get { return iSignalAmplitudePosition; }
            set { iSignalAmplitudePosition = value; }
        }

        /// <summary>
        /// Amplitude velocity signal
        /// </summary>
        public string TcB_SignalAmplitudeVelocity
        {
            get { return iSignalAmplitudeVelocity; }
            set { iSignalAmplitudeVelocity = value; }
        }

        /// <summary>
        /// Amplitude torque signal
        /// </summary>
        public string TcB_SignalAmplitudeTorque
        {
            get { return iSignalAmplitudeTorque; }
            set { iSignalAmplitudeTorque = value; }
        }

        /// <summary>
        /// Base amplitude
        /// </summary>
        public string TcB_BaseAmplitude
        {
            get { return iBaseAmplitude; }
            set { iBaseAmplitude = value; }
        }

        /// <summary>
        /// Torque offset
        /// </summary>
        public string TcB_TorqueOffset
        {
            get { return iTorqueOffset; }
            set { iTorqueOffset = value; }
        }

        /// <summary>
        /// Base frequency
        /// </summary>
        public string TcB_BaseFrequency
        {
            get { return iBaseFrequency; }
            set { iBaseFrequency = value; }
        }

        /// <summary>
        /// Dead time
        /// </summary>
        public string TcB_DeadTime
        {
            get { return iDeadTime; }
            set { iDeadTime = value; }
        }

        /// <summary>
        /// Proportional gain
        /// </summary>
        public string TcB_ProportionalGain
        {
            get { return iProportionalGain; }
            set { iProportionalGain = value; }
        }

        /// <summary>
        /// Integral time
        /// </summary>
        public string TcB_IntegralTime
        {
            get { return iIntegralTime; }
            set { iIntegralTime = value; }
        }

        /// <summary>
        /// Min frequency
        /// </summary>
        public string TcB_MinFrequency
        {
            get { return iMinFrequency; }
            set { iMinFrequency = value; }
        }

        /// <summary>
        /// Max frequency
        /// </summary>
        public string TcB_MaxFrequency
        {
            get { return iMaxFrequency; }
            set { iMaxFrequency = value; }
        }

        /// <summary>
        /// Frequency steps
        /// </summary>
        public string TcB_FrequencySteps
        {
            get { return iFrequencySteps; }
            set { iFrequencySteps = value; }
        }

        /// <summary>
        /// Unique ID of curve set. If i_ID = -1, this value is uninitialized.
        /// </summary>
        public int ID;

        /// <summary>
        /// Frequency axis
        /// </summary>
        public Collection<double> Frequency;
        /// <summary>
        /// Closed loop gain
        /// </summary>
        public Collection<double> CloseLoopGain;
        /// <summary>
        /// Closed loop phase
        /// </summary>
        public Collection<double> CloseLoopPhase;
        /// <summary>
        /// Open loop gain
        /// </summary>
        public Collection<double> OpenLoopGain;
        /// <summary>
        /// Open loop phase
        /// </summary>
        public Collection<double> OpenLoopPhase;
        /// <summary>
        /// Process gain
        /// </summary>
        public Collection<double> ProcessGain;
        /// <summary>
        /// Process phase
        /// </summary>
        public Collection<double> ProcessPhase;

        /// <summary>
        /// Constructor
        /// </summary>
        public TcBodeData()
        {
            TcB_Title = "";
            TcB_Name = "";
            TcB_CycleTime = "";
            TcB_Mode = "";
            TcB_MeasureTime = "";
            TcB_SignalAmplitudePosition = "";
            TcB_SignalAmplitudeVelocity = "";
            TcB_SignalAmplitudeTorque = "";
            TcB_BaseAmplitude = "";
            TcB_TorqueOffset = "";
            TcB_BaseFrequency = "";
            TcB_DeadTime = "";
            TcB_ProportionalGain = "";
            TcB_IntegralTime = "";
            TcB_MinFrequency = "";
            TcB_MaxFrequency = "";
            TcB_FrequencySteps = "";

            Frequency = new Collection<double>();
            CloseLoopGain = new Collection<double>();
            CloseLoopPhase = new Collection<double>();
            OpenLoopGain = new Collection<double>();
            OpenLoopPhase = new Collection<double>();
            ProcessGain = new Collection<double>();
            ProcessPhase = new Collection<double>();

            ID = -1;
        }

    }

    /// <summary>
    /// Storage of all Bode diagram in one file from Beckhoff TwinCAT tool
    /// </summary>
    public class TwinCatBode
    {
        /// <summary>
        /// Title
        /// </summary>
        public string Title;
        /// <summary>
        /// Name
        /// </summary>
        public string Name;        

        /// <summary>
        /// List of Bode diagrams 
        /// </summary>
        public List<TcBodeData> ListTcBodeData;

        /// <summary>
        /// Constructor
        /// </summary>
        public TwinCatBode()
        {
            Title = "";
            Name = "";

            ListTcBodeData = new List<TcBodeData>();
        }

        /// <summary>
        /// Load Bode diagrams from file
        /// </summary>
        /// <param name="path"></param>
        public void LoadXmlData(string path)
        {
            XmlDocument xmldoc = new XmlDocument();
            XmlNodeList xmlMainNode, xmlBodeValues, xmlMainAllNode;
            XmlNode xmlSetsNode;
            FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
            xmldoc.Load(fs);

            xmlMainAllNode = xmldoc.GetElementsByTagName("BodeProjectSerializable");
            // Properties of all measurement
            Title = xmlMainAllNode[0].SelectSingleNode("Title").InnerText;
            Name = xmlMainAllNode[0].SelectSingleNode("Name").InnerText;

            // Each measuremnt
            xmlMainNode = xmldoc.GetElementsByTagName("BodeSetSerializable");
            for (int i = 0; i < xmlMainNode.Count; i++)
            {
                ListTcBodeData.Add(new TcBodeData());

                // Properties 
                ListTcBodeData[i].TcB_Title = xmlMainNode[i].SelectSingleNode("Title").InnerText;
                ListTcBodeData[i].TcB_Name = xmlMainNode[i].SelectSingleNode("Name").InnerText;
                ListTcBodeData[i].TcB_CycleTime = xmlMainNode[i].SelectSingleNode("CycleTime").InnerText;
                ListTcBodeData[i].TcB_Mode = xmlMainNode[i].SelectSingleNode("Mode").InnerText;
                ListTcBodeData[i].TcB_MeasureTime = xmlMainNode[i].SelectSingleNode("MeasureTime").InnerText;
                ListTcBodeData[i].TcB_SignalAmplitudePosition = xmlMainNode[i].SelectSingleNode("SignalAmplitudePosition").InnerText;
                ListTcBodeData[i].TcB_SignalAmplitudeVelocity = xmlMainNode[i].SelectSingleNode("SignalAmplitudeVelocity").InnerText;
                ListTcBodeData[i].TcB_SignalAmplitudeTorque = xmlMainNode[i].SelectSingleNode("SignalAmplitudeTorque").InnerText;
                ListTcBodeData[i].TcB_BaseAmplitude = xmlMainNode[i].SelectSingleNode("BaseAmplitude").InnerText;
                ListTcBodeData[i].TcB_TorqueOffset = xmlMainNode[i].SelectSingleNode("TorqueOffset").InnerText;
                ListTcBodeData[i].TcB_DeadTime = xmlMainNode[i].SelectSingleNode("DeadTime").InnerText;
                ListTcBodeData[i].TcB_ProportionalGain = xmlMainNode[i].SelectSingleNode("ProportionalGain").InnerText;
                ListTcBodeData[i].TcB_IntegralTime = xmlMainNode[i].SelectSingleNode("IntegralTime").InnerText;
                ListTcBodeData[i].TcB_MinFrequency = xmlMainNode[i].SelectSingleNode("MinFrequency").InnerText;
                ListTcBodeData[i].TcB_MaxFrequency = xmlMainNode[i].SelectSingleNode("MaxFrequency").InnerText;
                ListTcBodeData[i].TcB_FrequencySteps = xmlMainNode[i].SelectSingleNode("FrequencySteps").InnerText;

                // Values
                xmlSetsNode = xmlMainNode[i].SelectSingleNode("Values");

                xmlBodeValues = xmlSetsNode.SelectNodes("BodeResultValue");
                for (int j = 0; j < xmlBodeValues.Count; j++)
                {
                    ListTcBodeData[i].Frequency.Add(Convert.ToDouble((xmlBodeValues[j].SelectSingleNode("Frequency")).InnerText, System.Globalization.CultureInfo.InvariantCulture));
                    ListTcBodeData[i].CloseLoopGain.Add(Convert.ToDouble((xmlBodeValues[j].SelectSingleNode("CloseLoopGain")).InnerText, System.Globalization.CultureInfo.InvariantCulture));
                    ListTcBodeData[i].CloseLoopPhase.Add(Convert.ToDouble((xmlBodeValues[j].SelectSingleNode("CloseLoopPhase")).InnerText, System.Globalization.CultureInfo.InvariantCulture));
                    ListTcBodeData[i].OpenLoopGain.Add(Convert.ToDouble((xmlBodeValues[j].SelectSingleNode("OpenLoopGain")).InnerText, System.Globalization.CultureInfo.InvariantCulture));
                    ListTcBodeData[i].OpenLoopPhase.Add(Convert.ToDouble((xmlBodeValues[j].SelectSingleNode("OpenLoopPhase")).InnerText, System.Globalization.CultureInfo.InvariantCulture));
                    ListTcBodeData[i].ProcessGain.Add(Convert.ToDouble((xmlBodeValues[j].SelectSingleNode("ProcessGain")).InnerText, System.Globalization.CultureInfo.InvariantCulture));
                    ListTcBodeData[i].ProcessPhase.Add(Convert.ToDouble((xmlBodeValues[j].SelectSingleNode("ProcessPhase")).InnerText, System.Globalization.CultureInfo.InvariantCulture));
                }

            }

        }
    }
}
