using IMCS.Device.HeiDenHainBase;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using HeidenhainDNCLib;
namespace IMCS.Device
{
    public class DeviceHeidenhainHandle
    {
        public enum ApplicationState { disconnected, connecting, connected, disconnecting }
        private delegate void OnStateChangedHandler(HeidenhainDNCLib.DNC_EVT_STATE eventValue);
        /// 
        /// 海德汉德连接
        /// 
        internal HeidenhainDNCLib.JHMachineInProcess Machine { get; private set; }
        #region 海德汉文件系统,上传下载
        /// 
        /// 海德汉文件系统,上传下载
        /// 
        private HeidenhainDNCLib.JHFileSystem m_FileSystem = null;
        // --- Helper objects
        private HeidenhainDNCLib.JHFileAttributes m_AttributesSelection = null;
        private HeidenhainDNCLib.JHFileAttributes m_AttributesState = null;
        #endregion
        private ApplicationState m_AppState = ApplicationState.disconnected;
        private HeidenhainDNCLib.JHAutomatic m_Automatic = null;
        private HeidenhainDNCLib.JHError m_Error = null;
        #region 刀具管理
        private HeidenhainDNCLib.JHDataAccess m_Tool = null;
        private bool initOkay = false;
        private HeidenhainDNCLib.DNC_CNC_TYPE ControlType { get; set; }
        private ListViewItem selectedTool = null;
        // --- data access path -----------------------------------------------------------------------
        private string ToolColumnNamesAccessor = string.Empty;  // see Init() 
        private string ToolTableAccessor = @"\TABLE\TOOL\T";
        private string ToolTableAccessorReadingWholeTyble = @"\TABLE\TOOL";
        #endregion
        #region 系统错误
        // --- other HEIDENHAIN helper objects and enumerations ---------------------------------------
        private HeidenhainDNCLib.DNC_CNC_TYPE CncType { get; set; }
        // --- other fields ---------------------------------------------------------------------------
        #endregion
        bool IsNck { get; set; }
        private List m_DirectoryEntryList = new List();
        /// 
        /// 海德汉连接状态
        /// 
        private HeidenhainDNCLib.DNC_STATE m_ControlState;
        private HeidenhainDNCLib.DNC_STATE m_PreviousControlState;
        internal ApplicationState AppState
        {
            get
            {
                return m_AppState;
            }
            private set
            {
                m_AppState = value;
            }
        }
        internal HeidenhainDNCLib.DNC_STATE ControlState
        {
            get
            {
                return m_ControlState;
            }
            private set
            {
                AppState = ApplicationState.connecting;
                m_ControlState = value;
                if (m_ControlState == HeidenhainDNCLib.DNC_STATE.DNC_STATE_MACHINE_IS_AVAILABLE)
                    AppState = ApplicationState.connected;
            }
        }
        private string m_Path = @"TNC:\";
        /// 
        /// 海德汉默认文件路径
        /// 
        private string ActPath
        {
            get
            {
                return m_Path;
            }
            set
            {
                m_Path = value;
            }
        }
        string connectionname;
        public DeviceHeidenhainHandle(string _connectionname)
        {
            connectionname = _connectionname;
            Machine_Init(connectionname);
        }
        #region 海德汉连接
        /// 
        /// 海德汉连接
        /// 
        /// 
        public void Machine_Init(string bstrConnectionName)
        {
            try
            {
                Machine = new HeidenhainDNCLib.JHMachineInProcess();
                Machine.ConnectRequest(bstrConnectionName);
                Machine.OnStateChanged += new HeidenhainDNCLib._DJHMachineEvents2_OnStateChangedEventHandler(Machine_OnStateChanged);
                ControlState = Machine.GetState();
            }
            catch (COMException cex)
            {
                ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_NOT_INITIALIZED;
                string strClassName = this.GetType().Name;
                string strMethodName = MethodInfo.GetCurrentMethod().Name;
                MyHelper.ShowComException(cex.ErrorCode, strClassName, strMethodName);
            }
            catch (Exception ex)
            {
                ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_NOT_INITIALIZED;
                string strClassName = this.GetType().Name;
                string strMethodName = MethodInfo.GetCurrentMethod().Name;
                MyHelper.ShowException(ex, strClassName, strMethodName);
            }
        }
        private void Machine_StateMachineNCK(HeidenhainDNCLib.DNC_EVT_STATE evtState)
        {
            // internal state machine of the NCK based controls
            // --> See HeidenhainDNC COM component dokumentation for more informations
            m_PreviousControlState = ControlState;
            switch (ControlState)
            {
                case HeidenhainDNCLib.DNC_STATE.DNC_STATE_NOT_INITIALIZED:
                    switch (evtState)
                    {
                        case HeidenhainDNCLib.DNC_EVT_STATE.DNC_EVT_STATE_HOST_NOT_AVAILABLE:
                            ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_HOST_IS_NOT_AVAILABLE;
                            break;
                    }
                    break;
                case HeidenhainDNCLib.DNC_STATE.DNC_STATE_HOST_IS_NOT_AVAILABLE:
                    switch (evtState)
                    {
                        case HeidenhainDNCLib.DNC_EVT_STATE.DNC_EVT_STATE_HOST_AVAILABLE:
                            ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_HOST_IS_AVAILABLE;
                            break;
                    }
                    break;
                case HeidenhainDNCLib.DNC_STATE.DNC_STATE_HOST_IS_AVAILABLE:
                    switch (evtState)
                    {
                        case HeidenhainDNCLib.DNC_EVT_STATE.DNC_EVT_STATE_HOST_NOT_AVAILABLE:
                            ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_HOST_IS_NOT_AVAILABLE;
                            break;
                        case HeidenhainDNCLib.DNC_EVT_STATE.DNC_EVT_STATE_WAIT_PERMISSION:
                            ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_WAITING_PERMISSION;
                            break;
                    }
                    break;
                case HeidenhainDNCLib.DNC_STATE.DNC_STATE_WAITING_PERMISSION:
                    switch (evtState)
                    {
                        case HeidenhainDNCLib.DNC_EVT_STATE.DNC_EVT_STATE_DNC_AVAILABLE:
                            ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_DNC_IS_AVAILABLE;
                            break;
                        case HeidenhainDNCLib.DNC_EVT_STATE.DNC_EVT_STATE_DNC_STOPPED:
                            ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_DNC_IS_STOPPED;
                            break;
                        case HeidenhainDNCLib.DNC_EVT_STATE.DNC_EVT_STATE_PERMISSION_DENIED:
                            ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_NO_PERMISSION;
                            break;
                    }
                    break;
                case HeidenhainDNCLib.DNC_STATE.DNC_STATE_DNC_IS_AVAILABLE:
                    switch (evtState)
                    {
                        case HeidenhainDNCLib.DNC_EVT_STATE.DNC_EVT_STATE_MACHINE_BOOTED:
                            ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_MACHINE_IS_BOOTED;
                            break;
                        case HeidenhainDNCLib.DNC_EVT_STATE.DNC_EVT_STATE_DNC_STOPPED:
                            ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_DNC_IS_STOPPED;
                            break;
                    }
                    break;
                case HeidenhainDNCLib.DNC_STATE.DNC_STATE_MACHINE_IS_BOOTED:
                    switch (evtState)
                    {
                        case HeidenhainDNCLib.DNC_EVT_STATE.DNC_EVT_STATE_MACHINE_INITIALIZING:
                            ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_MACHINE_IS_INITIALIZING;
                            break;
                        case HeidenhainDNCLib.DNC_EVT_STATE.DNC_EVT_STATE_DNC_STOPPED:
                            ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_DNC_IS_STOPPED;
                            break;
                    }
                    break;
                case HeidenhainDNCLib.DNC_STATE.DNC_STATE_MACHINE_IS_INITIALIZING:
                    switch (evtState)
                    {
                        case HeidenhainDNCLib.DNC_EVT_STATE.DNC_EVT_STATE_MACHINE_AVAILABLE:
                            ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_MACHINE_IS_AVAILABLE;
                            break;
                        case HeidenhainDNCLib.DNC_EVT_STATE.DNC_EVT_STATE_DNC_STOPPED:
                            ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_DNC_IS_STOPPED;
                            break;
                    }
                    break;
                case HeidenhainDNCLib.DNC_STATE.DNC_STATE_MACHINE_IS_AVAILABLE:
                    switch (evtState)
                    {
                        case HeidenhainDNCLib.DNC_EVT_STATE.DNC_EVT_STATE_MACHINE_SHUTTING_DOWN:
                            ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_MACHINE_IS_SHUTTING_DOWN;
                            break;
                        case HeidenhainDNCLib.DNC_EVT_STATE.DNC_EVT_STATE_DNC_STOPPED:
                            ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_DNC_IS_STOPPED;
                            break;
                    }
                    break;
                case HeidenhainDNCLib.DNC_STATE.DNC_STATE_MACHINE_IS_SHUTTING_DOWN:
                    switch (evtState)
                    {
                        case HeidenhainDNCLib.DNC_EVT_STATE.DNC_EVT_STATE_DNC_STOPPED:
                            ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_DNC_IS_STOPPED;
                            break;
                    }
                    break;
                case HeidenhainDNCLib.DNC_STATE.DNC_STATE_DNC_IS_STOPPED:
                    switch (evtState)
                    {
                        case HeidenhainDNCLib.DNC_EVT_STATE.DNC_EVT_STATE_CONNECTION_LOST:
                            ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_HOST_IS_STOPPED;
                            break;
                    }
                    break;
                case HeidenhainDNCLib.DNC_STATE.DNC_STATE_HOST_IS_STOPPED:
                    switch (evtState)
                    {
                        case HeidenhainDNCLib.DNC_EVT_STATE.DNC_EVT_STATE_DNC_STOPPED:
                            ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_DNC_IS_STOPPED;
                            break;
                    }
                    break;
                case HeidenhainDNCLib.DNC_STATE.DNC_STATE_NO_PERMISSION:
                    break;
            }
            Debug.WriteLine(m_PreviousControlState.ToString() + " --> " + ControlState.ToString());
        }
        private void Machine_OnStateChanged(HeidenhainDNCLib.DNC_EVT_STATE eventValue)
        {
            // Make sure the implementation is called asynchronously
            // Otherwise you may get a deadlock at unadvising the OnStateChanged event handler
            // BeginInvoke(new OnStateChangedHandler(Machine_OnStateChangedImpl), eventValue);
            Machine_OnStateChangedImpl(eventValue);
        }
        private void Machine_Disconnect()
        {
            AppState = ApplicationState.disconnecting;
            try
            {
                // 1. Dispose all panels which contains the COM interfaces (JHVersion, JHAutomatic, etc.)
                //    Release all COM interfaces (Marshal.ReleaseComObject(JH...)) in the panel classes
                if (Machine != null)
                {
                    // 2. Unsubscribe all events 
                    Machine.OnStateChanged -= new HeidenhainDNCLib._DJHMachineEvents2_OnStateChangedEventHandler(Machine_OnStateChanged);
                    ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_NOT_INITIALIZED;
                    // 3. Disconect from control
                    Machine.Disconnect();
                    // 4. Release machine object
                    Marshal.ReleaseComObject(Machine);
                    Machine = null;
                }
                AppState = ApplicationState.disconnected;
            }
            catch (COMException cex)
            {
                string strClassName = this.GetType().Name;
                string strMethodName = MethodInfo.GetCurrentMethod().Name;
                MyHelper.ShowComException(cex.ErrorCode, strClassName, strMethodName);
            }
            catch (Exception ex)
            {
                string strClassName = this.GetType().Name;
                string strMethodName = MethodInfo.GetCurrentMethod().Name;
                MyHelper.ShowException(ex, strClassName, strMethodName);
            }
        }
        private void Machine_OnStateChangedImpl(HeidenhainDNCLib.DNC_EVT_STATE eventValue)
        {
            try
            {
                Machine_StateMachineNCK(eventValue);
                switch (eventValue)
                {
                    case HeidenhainDNCLib.DNC_EVT_STATE.DNC_EVT_STATE_DNC_STOPPED:
                        AppState = ApplicationState.disconnecting;
                        Debug.WriteLine("--- automatic Disconnect ---");
                        Machine_Disconnect();
                        Debug.WriteLine("--- automatic ConnectRequest ---");
                        Machine_Init(connectionname);
                        break;
                }
            }
            catch (COMException cex)
            {
                string strClassName = this.GetType().ToString();
                string strMethodName = MethodInfo.GetCurrentMethod().Name;
                MyHelper.ShowComException(cex.ErrorCode, strClassName, strMethodName);
            }
            catch (Exception ex)
            {
                string strClassName = this.GetType().ToString();
                string strMethodName = MethodInfo.GetCurrentMethod().Name;
                MyHelper.ShowException(ex, strClassName, strMethodName);
            }
        }
        #endregion
        #region 当前机床异常情况
        public void Error_Init()
        {
            m_Error = Machine.GetInterface(HeidenhainDNCLib.DNC_INTERFACE_OBJECT.DNC_INTERFACE_JHERROR);
            m_Error.OnError += new HeidenhainDNCLib._DJHErrorEvents_OnErrorEventHandler(M_Error_OnError);
        }
        private void M_Error_OnError(HeidenhainDNCLib.DNC_ERROR_GROUP errorGroup, int lErrorNumber, HeidenhainDNCLib.DNC_ERROR_CLASS errorClass, string bstrError, int lChannel)
        {
        }
        #endregion
        #region 机床启动停止
       
        
        public void Progam_Init()
        {
            m_Automatic = Machine.GetInterface(HeidenhainDNCLib.DNC_INTERFACE_OBJECT.DNC_INTERFACE_JHAUTOMATIC);
        }
        /// 
        /// 
        /// 
        /// 选择执行脚本的名称
        /// 
        public void Program_Select(string progamname, int channel = 0)
        {
            m_Automatic.SelectProgram(0, progamname);
        }
        /// 
        /// 
        /// 
        /// 机床加工的脚本名称
        public void Program_Start(string progamname)
        {
            m_Automatic.StartProgram(progamname);
        }
        /// 
        /// 
        /// 
        /// 
        /// 
        public void Program_Stop(string progamname, int channel = 0)
        {
            m_Automatic.StopProgram(channel, false);
        }
        #endregion
        #region 上传文件
        private void File_Init()
        {
            m_FileSystem = Machine.GetInterface(HeidenhainDNCLib.DNC_INTERFACE_OBJECT.DNC_INTERFACE_JHFILESYSTEM);
            m_AttributesSelection = new HeidenhainDNCLib.JHFileAttributes();
            m_AttributesState = new HeidenhainDNCLib.JHFileAttributes();
        }
        /// 
        /// 上传文件
        /// 
        /// 文件路径+文件名称
        /// 文件路径
        public void File_Upload(string filename, string path = @"TNC:\")
        {
            m_FileSystem.TransmitFile(filename, path);
        }
        /// 
        /// 删除文件
        /// 
        /// 文件路径+文件名称
        public void File_DelFile(string path)
        {
            m_FileSystem.DeleteFile(path);
        }
        /// 
        /// 创建文件夹
        /// 
        /// 文件夹名称
        /// 文件路径
        public void File_CreateDir(string dirname, string path = @"TNC:\")
        {
            m_FileSystem.MakeDirectory(dirname);
        }
        /// 
        /// 判断文件是否存在
        /// 
        /// 需要查找的文件名称
        /// 查找文件路径
        /// 
        public bool File_FileExists(string filename, string findpath = @"TNC:\")
        {
            HeidenhainDNCLib.IJHDirectoryEntryList directoryEntryList = null;
            HeidenhainDNCLib.IJHDirectoryEntry directoryEntry = null;
            HeidenhainDNCLib.JHFileAttributes fileAttributes = null;
            m_DirectoryEntryList.Clear();
            try
            {
                directoryEntryList = m_FileSystem.ReadDirectory(ActPath, m_AttributesSelection, m_AttributesState);
                int iDirCount = directoryEntryList.Count;
                for (int i = 0; i < iDirCount; i++)
                {
                    directoryEntry = directoryEntryList[i];
                    // get entry informations
                    MyDirectoryEntry entry = new MyDirectoryEntry();
                    entry.Name = directoryEntry.name;
                    entry.TimeStamp = directoryEntry.dateTime;
                    entry.FileSize = directoryEntry.size;
                    // get file attributes
                    fileAttributes = directoryEntry.attributes;
                    entry.Dir = fileAttributes.IsAttributeSet(HeidenhainDNCLib.DNC_ATTRIBUTE_TYPE.DNC_ATTRIBUTE_DIR);
                    entry.Hidden = fileAttributes.IsAttributeSet(HeidenhainDNCLib.DNC_ATTRIBUTE_TYPE.DNC_ATTRIBUTE_HIDDEN);
                    entry.Locked = fileAttributes.IsAttributeSet(HeidenhainDNCLib.DNC_ATTRIBUTE_TYPE.DNC_ATTRIBUTE_LOCKED);
                    entry.Modified = fileAttributes.IsAttributeSet(HeidenhainDNCLib.DNC_ATTRIBUTE_TYPE.DNC_ATTRIBUTE_MODIFIED);
                    entry.ReadOnly = fileAttributes.IsAttributeSet(HeidenhainDNCLib.DNC_ATTRIBUTE_TYPE.DNC_ATTRIBUTE_READONLY);
                    entry.System = fileAttributes.IsAttributeSet(HeidenhainDNCLib.DNC_ATTRIBUTE_TYPE.DNC_ATTRIBUTE_SYSTEM);
                    // add to list
                    m_DirectoryEntryList.Add(entry);
                    if (directoryEntry != null)
                        Marshal.ReleaseComObject(directoryEntry);
                    if (fileAttributes != null)
                        Marshal.ReleaseComObject(fileAttributes);
                }
            }
            catch (COMException cex)
            {
                string strClassName = this.GetType().Name;
                string strMethodName = MethodInfo.GetCurrentMethod().Name;
                MyHelper.ShowComException(cex.ErrorCode, strClassName, strMethodName);
            }
            catch (Exception ex)
            {
                string strClassName = this.GetType().Name;
                string strMethodName = MethodInfo.GetCurrentMethod().Name;
                MyHelper.ShowException(ex, strClassName, strMethodName);
            }
            finally
            {
                if (fileAttributes != null)
                    Marshal.ReleaseComObject(fileAttributes);
                if (directoryEntry != null)
                    Marshal.ReleaseComObject(directoryEntry);
                if (directoryEntryList != null)
                    Marshal.ReleaseComObject(directoryEntryList);
                
            }
            return m_DirectoryEntryList.Where(m => m.Name.Equals(filename)).Count() > 0 ? true : false;
        }
        /// 
        /// 下载文件
        /// 
        /// 路径+文件名称
        /// 路径+文件名称
        public void File_DownFile(string bstrSourceFileName, string destfile)
        {
            m_FileSystem.ReceiveFile(bstrSourceFileName, destfile);
        }
        #endregion
        #region 刀具管理
        /// 
        /// 刀具
        /// 
        public void Tool_Init()
        {
            try
            {
                ToolColumnNamesAccessor = @"\TABLE\TOOL";
                m_Tool = Machine.GetInterface(HeidenhainDNCLib.DNC_INTERFACE_OBJECT.DNC_INTERFACE_JHDATAACCESS);
                m_Tool.SetAccessMode(HeidenhainDNCLib.DNC_ACCESS_MODE.DNC_ACCESS_MODE_TABLEDATAACCESS, "");
            }
            catch (COMException cex)
            {
                ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_NOT_INITIALIZED;
                string strClassName = this.GetType().Name;
                string strMethodName = MethodInfo.GetCurrentMethod().Name;
                MyHelper.ShowComException(cex.ErrorCode, strClassName, strMethodName);
            }
            catch (Exception ex)
            {
                ControlState = HeidenhainDNCLib.DNC_STATE.DNC_STATE_NOT_INITIALIZED;
                string strClassName = this.GetType().Name;
                string strMethodName = MethodInfo.GetCurrentMethod().Name;
                MyHelper.ShowException(ex, strClassName, strMethodName);
            }
        }
        /// 
        /// 
        /// 
        /// 
        public ListViewItem[] Tool_Read()
        {
            IJHDataEntry2 ToolTable = null;
            IJHDataEntry2List ToolLines = null;
            IJHDataEntry2 ToolLine = null;
            IJHDataEntry2List ToolCells = null;
            IJHDataEntry2 ToolCell = null;
            IJHDataEntryProperty2List CellPropertyList = null;
            IJHDataEntryProperty2 CellProperty = null;
            object CellValue = null;
            string sCellValue = null;
            ToolTable = m_Tool.GetDataEntry2(ToolTableAccessor, DNC_DATA_UNIT_SELECT.DNC_DATA_UNIT_SELECT_METRIC, false);
            ToolLines = ToolTable.GetChildList();
            //找到刀的总数量
            int ToolLinesCount = ToolLines.Count;
            ListViewItem[] ListViewToolLines = new ListViewItem[ToolLinesCount];
            for (int i = 0; i < ToolLinesCount; i++)
            {
                // check if worker has to be stoped
                ToolLine = ToolLines[i];
                // get child list from server
                ToolCells = ToolLine.GetChildList();
                ListViewItem ListViewToolLine = null;
                for (int j = 0; j < ToolCells.Count; j++)
                {
                    ToolCell = ToolCells[j];
                    // get property from server
                    CellValue = ToolCell.GetPropertyValue(DNC_DATAENTRY_PROPKIND.DNC_DATAENTRY_PROPKIND_DATA);
                    if (CellValue != null)
                    {
                        sCellValue = CellValue.ToString();
                        if (ToolCell.bstrName == "T")
                        {
                            sCellValue = sCellValue.Replace(",", ".");
                        }
                    }
                    else
                    {
                        sCellValue = "";
                    }
                    if (ListViewToolLine == null)
                    {
                        ListViewToolLine = new ListViewItem(sCellValue);
                        /* MSDN INFO:
                         * The Name property corresponds to the key for a ListViewItem in the ListView.ListViewItemCollection.
                         * The key comparison is not case-sensitive. If the key parameter is null or an empty string, IndexOfKey returns -1.
                         * --> We need the key to remove the item from list in a handy way
                         */
                        ListViewToolLine.Name = sCellValue;
                    }
                    else
                        ListViewToolLine.SubItems.Add(sCellValue);
                    if (ToolCell != null)
                        Marshal.ReleaseComObject(ToolCell);
                    if (CellPropertyList != null)
                        Marshal.ReleaseComObject(CellPropertyList);
                    if (CellProperty != null)
                        Marshal.ReleaseComObject(CellProperty);
                }
                ListViewToolLines[i] = ListViewToolLine;
                if (ToolLine != null)
                    Marshal.ReleaseComObject(ToolLine);
                if (ToolCells != null)
                    Marshal.ReleaseComObject(ToolCells);
            }
            return ListViewToolLines;
        }
        #endregion
    }
}