/***************************************************************************/
/**                                                                       **/
/**                               MAGICARD                                **/
/**                                                                       **/
/***************************************************************************/
/**                                                                       **/
/**  PROJECT      : SDK C# Demo - Ultima Printers                         **/
/**                                                                       **/
/**  MODULE NAME  : Printer.cs                                            **/
/**                                                                       **/
/**  COPYRIGHT    : Magicard                                              **/
/**                                                                       **/
/***************************************************************************/
using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Printing;
using System.Net;
using System.Diagnostics;
using SDKShim;

namespace CSharpDemo
{
    public partial class SDK_CSDemo : Form
    {
        #region === Initialisation ===

        static private IntPtr hSession = IntPtr.Zero;
        static private IntPtr hDC = IntPtr.Zero;
        static private PrinterSettings ps = new PrinterSettings();
        static private PrintDialog pd = new PrintDialog();
        static private Graphics g;

        private void InitPrinterTab()
        {
            InitSessionConfigCombo();
            InitErrorResponseCombo();
            InitMoveCardCombo();
            InitEjectModeCombo();
            InitIPModeCombo();

            FileVersionInfo myFileVersionInfo = FileVersionInfo.GetVersionInfo("SDKShim.dll");
            PrinterMsgBox.AppendText("Demo Version: " + Application.ProductVersion + Environment.NewLine);
            PrinterMsgBox.AppendText(myFileVersionInfo.FileDescription 
                                     + " Version: " 
                                     + myFileVersionInfo.FileVersion 
                                     + Environment.NewLine);
            PrinterMsgBox.AppendText(SDK.ID_SDKBits() + " Bit SDK" + Environment.NewLine + Environment.NewLine);
        }

        #endregion === Initialisation ===

        //*********************************************************************

        #region === Local Methods ===

        private void PrinterActionGetRadio_CheckedChanged(object sender, EventArgs e)
        {
            PrinterTabGetSetControls(false);
        }

        private void PrinterActionSet_CheckedChanged(object sender, EventArgs e)
        {
            PrinterTabGetSetControls(true);
        }

        private bool PrinterActionIsGet()
        {
            return PrinterGetRadio.Checked;
        }

        private void ClearPrinterMsgButton_Click(object sender, EventArgs e)
        {
            PrinterMsgBox.Clear();
        }

        private void PrinterTabGetSetControls(bool state)
        {
            EjectModeCombo.Enabled = state;
            IPModeCombo.Enabled    = state;
            IPAddressBox.Enabled   = state;
            IPSubnetBox.Enabled    = state;
            IPGatewayBox.Enabled   = state;
        }

        private void EnableControls(bool state)
        {
            MoveCardButton.Enabled      = state;
            MoveCardCombo.Enabled       = state;
            CleanPrinterButton.Enabled  = state;
            TestCardButton.Enabled = state;
            RestartButton.Enabled       = state;
            ErrorResponseButton.Enabled = state;
            ErrorResponseCombo.Enabled  = state;
            PrinterGetRadio.Enabled     = state;
            PrinterSetRadio.Enabled     = state;
            EjectModeButton.Enabled     = state;
            IPSettingsButton.Enabled    = state;

            PrinterTabGetSetControls(!PrinterGetRadio.Checked);

            if (state)
            {
                TabControl.Controls.Add(Information);
                TabControl.Controls.Add(MagEncoding);
                TabControl.Controls.Add(DriverSettings1);
                TabControl.Controls.Add(DriverSettings2);
                TabControl.Controls.Add(PrintDemo);
            }
            else
            {
                TabControl.Controls.Remove(Information);
                TabControl.Controls.Remove(MagEncoding);
                TabControl.Controls.Remove(DriverSettings1);
                TabControl.Controls.Remove(DriverSettings2);
                TabControl.Controls.Remove(PrintDemo);
            }
        }

        private bool PrinterConnected()
        {
            string temp_string = "";
            switch (SDK.ID_PrinterStatus(hSession))
            {
            case SDK.PrinterStatus.Ready:   return true;
            case SDK.PrinterStatus.Offline: temp_string = "Printer is offline"; break;
            case SDK.PrinterStatus.Error:   temp_string = "Printer is in error"; break;
            case SDK.PrinterStatus.Busy:    temp_string = "Printer is busy"; break;
            }
            MessageBox.Show(temp_string, "Invalid Printer", MessageBoxButtons.OK);
            return false;
        }

        #endregion === Local Methods ===

        //*********************************************************************

        #region === Open Session ===

        Dictionary<SDK.Config, string> openconfigkp = new Dictionary<SDK.Config, string>()
        {
            {SDK.Config.Normal, "Config Normal"},
            {SDK.Config.Quiet,  "Config Quiet"},
        };

        private void InitSessionConfigCombo()
        {
            SessionConfigCombo.DataSource    = new BindingSource(openconfigkp, null);
            SessionConfigCombo.DisplayMember = "Value";
            SessionConfigCombo.SelectedItem  = SDK.Config.Normal;
        }

        private void OpenSession_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;

            pd.PrinterSettings = ps;
            pd.AllowPrintToFile = true;
            if (pd.ShowDialog() == DialogResult.OK)
            {
                ps = pd.PrinterSettings;

                // Get the printer HDC
                g = ps.CreateMeasurementGraphics();
                hDC = g.GetHdc();

                SDK.Config Config = ((KeyValuePair<SDK.Config, string>)SessionConfigCombo.SelectedItem).Key;
                SDK.Return SDKReturn = SDK.ID_OpenSession(hDC, out hSession, Config);
                if (SDKReturn != SDK.Return.Success)
                {
                    HandleError("OpenSession", SDKReturn);
                }
                else
                {
                    ResinAreaWidthUpDown.Maximum = SDK.ID_CardWidth(hSession);

                    if (SDK.ID_PrinterType(hSession) != SDK.PrinterType.Ultima)
                    {
                        MessageBox.Show("Use with Ultima Only", "Invalid Printer", MessageBoxButtons.OK);
                        SDK.ID_CloseSession(hSession);
                    }
                    else
                    {
                        PrinterID.Text = "Printer: " + pd.PrinterSettings.PrinterName;
                        PrinterID.Visible = true;
                        PrinterPrefs.Visible = true;



                        if (!pd.PrintToFile)
                        {
                            SDK.EjectMode mode = new SDK.EjectMode();
                            if (GetEjectMode(ref mode) == SDK.Return.Success)
                            {
                                SetEjectModeCombo(mode);
                            }
                                
                            SDK.IPData settings = new SDK.IPData();
                            GetIPSettings(ref settings);
                            IPSettingsToCtrl(settings);

                            IPModeCombo.Enabled  = true;
                            IPAddressBox.Enabled = true;
                            IPSubnetBox.Enabled  = true;
                            IPGatewayBox.Enabled = true;
                        }
                        OpenSessionButton.Visible  = false;
                        SessionConfigCombo.Visible = false;
                        CloseSessionButton.Visible = true;

                        EnableControls(true);
                    }
                }

                Application.DoEvents();
            }

            Cursor.Current = Cursors.Default;
        }

        #endregion === Open Session ===

        //*********************************************************************

        #region === Close Session ===

        private void CloseSession_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;

            OpenSessionButton.Visible  = true;
            SessionConfigCombo.Visible = true;
            CloseSessionButton.Visible = false;

            PrinterID.Visible    = false;
            PrinterPrefs.Visible = false;

            EnableControls(false);
            PrinterTabGetSetControls(false);

            SDK.Return SDKReturn = SDK.ID_CloseSession(hSession);
            if (SDKReturn != SDK.Return.Success)
            {
                HandleError("CloseSession", SDKReturn);
            }

            Cursor.Current = Cursors.Default;
        }

        #endregion === Close Session ===

        //*********************************************************************

        #region === Error Response ===

        Dictionary<SDK.Response, string> errorresponsekp = new Dictionary<SDK.Response, string>()
        {
            {SDK.Response.OK,     "OK"},
            {SDK.Response.Cancel, "Cancel"},
        };

        private void InitErrorResponseCombo()
        {
            ErrorResponseCombo.DataSource    = new BindingSource(errorresponsekp, null);
            ErrorResponseCombo.DisplayMember = "Value";
            ErrorResponseCombo.SelectedItem  = SDK.Response.OK;
        }

        private void ErrorResponse_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;

            SDK.Response Response = ((KeyValuePair<SDK.Response, string>)ErrorResponseCombo.SelectedItem).Key;

            SDK.Return SDKReturn = SDK.ID_ErrorResponse(hSession, Response);
            if (SDKReturn != SDK.Return.Success)
            {
                HandleError("ErrorResponse", SDKReturn);
            }

            Cursor.Current = Cursors.Default;
        }

        #endregion === Error Response ===

        //*********************************************************************

        #region === Move Card ===

        Dictionary<SDK.CardPosition, string> movecardkp = new Dictionary<SDK.CardPosition, string>()
        {
            {SDK.CardPosition.TransferStandby,    "TransferStandby"},
            {SDK.CardPosition.HeatedRoller,       "HeatedRoller"},
            {SDK.CardPosition.FlipStandby,        "FlipStandby"},
            {SDK.CardPosition.Rotate,             "Rotate"},
            {SDK.CardPosition.MagEncoder,         "MagEncoder"},
            {SDK.CardPosition.ContactEncoder,     "ContactEncoder"},
            {SDK.CardPosition.Eject,              "Eject"},
            {SDK.CardPosition.Reject,             "Reject"},
            {SDK.CardPosition.Laminator,          "Laminator"},
            {SDK.CardPosition.ContactlessEncoder, "ContactlessEncoder"},
        };

        private void InitMoveCardCombo()
        {
            MoveCardCombo.DataSource = new BindingSource(movecardkp, null);
            MoveCardCombo.DisplayMember = "Value";
        }

        private void MoveCardButton_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;

            SDK.CardPosition position = ((KeyValuePair<SDK.CardPosition, string>)MoveCardCombo.SelectedItem).Key;
            SDK.Return SDKReturn = SDK.ID_MoveCard(hSession, position);
            if (SDKReturn != SDK.Return.Success)
            {
                HandleError("MoveCard", SDKReturn);
            }
            else
            {
                WaitForPrinterToFinish();
            }

            Cursor.Current = Cursors.Default;
        }

        #endregion === Move Card ===

        //*********************************************************************

        #region === Clean Printer ===

        private void CleanPrinterButton_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;

            SDK.Return SDKReturn = SDK.ID_CleanPrinter(hSession);
            if (SDKReturn != SDK.Return.Success)
            {
                HandleError("CleanPrinter", SDKReturn);
            }
            else
            {
                WaitForPrinterToFinish();
            }

            Cursor.Current = Cursors.Default;
        }

        #endregion === Clean Printer ===

        //*********************************************************************

        #region === Restart Printer ===

        private void RestartButton_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;

            SDK.Return SDKReturn = SDK.ID_RestartPrinter(hSession);
            if (SDKReturn != SDK.Return.Success)
            {
                HandleError("RestartPrinter", SDKReturn);
            }
            else
            {
                WaitForPrinterToFinish();
            }

            Cursor.Current = Cursors.Default;
        }

        #endregion === Restart Printer ===

        //*********************************************************************

        #region === Print Test Card ===

        private void PrintTestCardButton_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;

            SDK.Return SDKReturn = SDK.ID_PrintTestCard(hSession);
            if (SDKReturn != SDK.Return.Success)
            {
                HandleError("PrintTestCard", SDKReturn);
            }
            else
            {
                WaitForPrinterToFinish();
            }

            Cursor.Current = Cursors.Default;
        }

        #endregion === Print Test Card ===

        //*********************************************************************

        #region === Eject Mode ===

        Dictionary<SDK.EjectMode, string> ejectmodekp = new Dictionary<SDK.EjectMode, string>()
        {
            {SDK.EjectMode.Off, "Off"}, 
            {SDK.EjectMode.On,  "On" },  
        };

        private void InitEjectModeCombo()
        {
            EjectModeCombo.DataSource = new BindingSource(ejectmodekp, null);
            EjectModeCombo.DisplayMember = "Value";
        }

        private void EjectModeToMsgBox(SDK.Action Action, SDK.EjectMode mode)
        {
            PrinterMsgBox.AppendText("Eject Mode"
                                     + Separator(Action)
                                     + ejectmodekp[mode] 
                                     + Environment.NewLine);
            PrinterMsgBox.AppendText(Environment.NewLine);
        }

        private void SetEjectModeCombo(SDK.EjectMode mode) 
        {
            EjectModeCombo.Text = ejectmodekp[mode]; 
        }

        private SDK.Return GetEjectMode(ref SDK.EjectMode mode)
        {
            SDK.Return SDKReturn = SDK.ID_EjectMode(hSession, SDK.Action.Read, ref mode);
            if (SDKReturn != SDK.Return.Success)
            {
                HandleError("GetEjectMode", SDKReturn);
            }
            return SDKReturn;
        }

        private void EjectModeButton_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;

            SDK.EjectMode mode = ((KeyValuePair<SDK.EjectMode, string>)EjectModeCombo.SelectedItem).Key;

            if (PrinterActionIsGet())
            {
                if (GetEjectMode(ref mode) == SDK.Return.Success)
                {
                    SetEjectModeCombo(mode);
                    EjectModeToMsgBox(SDK.Action.Read, mode);
                }
            }
            else
            {
                SDK.Return SDKReturn = SDK.ID_EjectMode(hSession, SDK.Action.Write, ref mode);
                if (SDKReturn != SDK.Return.Success)
                {
                    HandleError("SetEjectMode", SDKReturn);
                }
                else
                {
                    EjectModeToMsgBox(SDK.Action.Write, mode);
                }
            }

            Cursor.Current = Cursors.Default;
        }

        #endregion === Eject Mode ===

        //*********************************************************************

        #region === IP Settings ===

        Dictionary<SDK.IPMode, string> ipaddresskp = new Dictionary<SDK.IPMode, string>()
        {
            {SDK.IPMode.Dynamic, "Dynamic"}, 
            {SDK.IPMode.Static,  "Static"},    
        };

        private void InitIPModeCombo()
        {
            IPModeCombo.DataSource    = new BindingSource(ipaddresskp, null);
            IPModeCombo.DisplayMember = "Value";
        }

        private string IntToIPAddressString(int value) 
        {
            var temp = IPAddress.HostToNetworkOrder(value);
            return new IPAddress(BitConverter.GetBytes(temp)).ToString();
        }

        private int IPAddressStringToInt(string IPAddr)
        {
            return IPAddress.NetworkToHostOrder(BitConverter.ToInt32(IPAddress.Parse(IPAddr).GetAddressBytes(), 0));
        }

        private void IPSettingsToMsgBox(SDK.Action Action, SDK.IPData settings)
        {
            string sep = Separator(Action);
            PrinterMsgBox.AppendText("Address Mode: " + ipaddresskp[settings.Mode] + Environment.NewLine);
            PrinterMsgBox.AppendText("IP Address"  + sep + IntToIPAddressString(settings.Address) + Environment.NewLine);
            PrinterMsgBox.AppendText("Subnet Mask" + sep + IntToIPAddressString(settings.Subnet)  + Environment.NewLine);
            PrinterMsgBox.AppendText("Gateway"     + sep + IntToIPAddressString(settings.Gateway) + Environment.NewLine);
            PrinterMsgBox.AppendText(Environment.NewLine);
        }

        private void IPSettingsToCtrl(SDK.IPData settings)
        {
            IPModeCombo.Text  = ipaddresskp[settings.Mode];
            IPAddressBox.Text = IntToIPAddressString(settings.Address);
            IPSubnetBox.Text  = IntToIPAddressString(settings.Subnet);
            IPGatewayBox.Text = IntToIPAddressString(settings.Gateway);
        }

        private SDK.Return GetIPSettings(ref SDK.IPData settings)
        {
            SDK.Return SDKReturn = SDK.ID_IPSettings(hSession, SDK.Action.Read, settings);
            if (SDKReturn != SDK.Return.Success)
            {
                HandleError("GetIPSettings", SDKReturn);
            }
            return SDKReturn;
        }

        private void IPSettingsButton_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;

            SDK.IPData settings = new SDK.IPData();

            if (PrinterActionIsGet())
            {
                if (GetIPSettings(ref settings) == SDK.Return.Success)
                {
                    IPSettingsToMsgBox(SDK.Action.Read, settings);
                    IPSettingsToCtrl(settings);
                }
            }
            else
            {
                GetIPSettings(ref settings);
                settings.Mode    = ((KeyValuePair<SDK.IPMode, string>)IPModeCombo.SelectedItem).Key;
                settings.Address = IPAddressStringToInt(IPAddressBox.Text);
                settings.Subnet  = IPAddressStringToInt(IPSubnetBox.Text);
                settings.Gateway = IPAddressStringToInt(IPGatewayBox.Text);

                SDK.Return SDKReturn = SDK.ID_IPSettings(hSession, SDK.Action.Write, settings);
                if (SDKReturn != SDK.Return.Success)
                {
                    HandleError("SetEraseSpeed", SDKReturn);
                }
                else
                {
                    IPSettingsToMsgBox(SDK.Action.Write, settings);
                }
            }

            Cursor.Current = Cursors.Default;
        }

        #endregion === IP Settings ===
    }
}
