using GlobalPayments.Api.Terminals;
using GlobalPayments.Api.Terminals.Abstractions;
using GlobalPayments.Api.Terminals.Ingenico;
using GlobalPaymentsTestApp.Entities;
using GlobalPaymentsTestApp.Forms;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace GlobalPaymentsTestApp.Control {
    public partial class StandardModeControl : UserControl {
        private ResponseControl _responseControl;
        private Processing _processing;
        private IDeviceInterface _device;

        private string raw;
        private decimal? _amount;
        private decimal? _cashBack;

        public string TransactionId { get; set; }
        public bool IsSerial { get; set; }
        public bool IsTcpIp { get; set; }
        private bool isAutoTicketEnabled;

        public StandardModeControl(IDeviceInterface device) {
            InitializeComponent();

            _responseControl = new ResponseControl();
            _processing = new Processing();
            _device = device;

            SetDefaultValues();
        }

        #region Event Listener
        public void DeviceOnMessageSent(string message) {
            Invoker.SetRichTextBox(txtRawRequest, message);
        }

        public void DeviceOnBroadcastMessage(string code, string message) {
            raw += "Broadcast: \r\n" + code + " | " + message + "\r\n\r\n";
            Invoker.SetRichTextBox(txtAdditionalDataRecv, raw);
        }
        #endregion

        #region Form
        private void SetDefaultValues() {
            Invoker.SetComboBoxItem(cmbPaymentType, new ComboBoxItem("SALE", 0));
            Invoker.SetComboBoxItem(cmbPaymentType, new ComboBoxItem("REFUND", 1));
            Invoker.SetComboBoxItem(cmbPaymentType, new ComboBoxItem("HOTEL MODE COMPLETION", 2));
            Invoker.SetComboBoxItem(cmbPaymentType, new ComboBoxItem("HOTEL MODE PRE AUTH", 3));
            Invoker.SetComboBoxItem(cmbPaymentType, new ComboBoxItem("TAXFREE CREDIT REFUND", 4));
            Invoker.SetComboBoxItem(cmbPaymentType, new ComboBoxItem("TAXFREE CASH REFUND", 5));
            Invoker.SetComboBoxItem(cmbPaymentType, new ComboBoxItem("ACCOUNT VERIFICATION", 6));
            Invoker.SetComboBoxItem(cmbPaymentType, new ComboBoxItem("REFERRAL CONFIRMATION", 9));

            this.Clear();
            _responseControl.Clear();
        }

        private void Clear() {
            raw = string.Empty;

            Invoker.SetRichTextBox(txtRawRequest, string.Empty);
            Invoker.SetRichTextBox(txtAdditionalDataRecv, string.Empty);
            Invoker.SetTextBox(txtEPoSNumber, "00");
            Invoker.SetTextBox(txtAmount, "6.18");
            Invoker.SetTextBox(txtReturnRep, "1");
            Invoker.SetTextBox(txtPaymentMode, "0");
            Invoker.SetTextBox(txtCurrency, "826");
            Invoker.SetTextBox(txtPrivData, "EXT01");
            Invoker.SetTextBox(txtImmediateAns, "0");
            Invoker.SetTextBox(txtForceOnline, "0");
            Invoker.SetTextBox(txtExtendedVal, string.Empty);
            Invoker.SetTextBox(txtTableNumber, string.Empty);
            Invoker.SetTextBox(txtAuthCode, string.Empty);
            Invoker.SetTextBox(txtAuthCode, false);
            Invoker.SetTextBox(txtCashback, string.Empty);
            Invoker.SetTextBox(txtCashback, false);

            Invoker.SetComboBoxSelectedIndex(cmbPaymentType, -1);
        }

        private void tabControlMessages_SelectedIndexChanged(object sender, EventArgs e) {
            if(tabControlMessages.SelectedIndex == 1) {
                tabPageResponse.Controls.Clear();
                tabPageResponse.Controls.Add(_responseControl);
            }
        }

        private void cmbPaymentType_SelectedIndexChanged(object sender, EventArgs e) {
            ComboBoxItem item = (ComboBoxItem)cmbPaymentType.SelectedItem;

            if (item != null) {
                switch (item.Value) {
                    case 0:
                        Invoker.SetTextBox(txtAuthCode, false);
                        Invoker.SetTextBox(txtAuthCode, string.Empty);
                        Invoker.SetTextBox(txtCashback, true);
                        Invoker.SetTextBox(txtCashback, string.Empty);
                        break;

                    case 2:
                    case 9:
                        Invoker.SetTextBox(txtAuthCode, true);
                        Invoker.SetTextBox(txtAuthCode, string.Empty);
                        Invoker.SetTextBox(txtCashback, false);
                        Invoker.SetTextBox(txtCashback, string.Empty);
                        break;

                    default:
                        Invoker.SetTextBox(txtAuthCode, false);
                        Invoker.SetTextBox(txtAuthCode, string.Empty);
                        Invoker.SetTextBox(txtCashback, false);
                        Invoker.SetTextBox(txtCashback, string.Empty);
                        break;
                }
            }
        }

        private void txtEPoSNumber_KeyPress(object sender, KeyPressEventArgs e) {
            if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar)) {
                e.Handled = true;
            }
        }

        private void txtAmount_KeyPress(object sender, KeyPressEventArgs e) {
            if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && (e.KeyChar != '.')) {
                e.Handled = true;
            } else {
                if (e.KeyChar == '.') {
                    int len = txtAmount.TextLength;
                    txtAmount.MaxLength = len + 3;
                } else if (!txtAmount.Text.Contains(".") && txtAmount.MaxLength != 8) {
                    txtAmount.MaxLength = 8;
                }
            }
        }

        private void txtCashback_KeyPress(object sender, KeyPressEventArgs e) {
            if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && (e.KeyChar != '.')) {
                e.Handled = true;
            } else {
                if (e.KeyChar == '.') {
                    int len = txtAmount.TextLength;
                    txtAmount.MaxLength = len + 3;
                } else if (!txtAmount.Text.Contains(".") && txtAmount.MaxLength != 8) {
                    txtAmount.MaxLength = 8;
                }
            }
        }

        private void ShowProcessingDialog() {
            new Thread(() => {
                var cancelled = _processing.ShowDialog();
                if (cancelled == DialogResult.OK) {
                    if (IsSerial && !IsTcpIp) {
                        MessageBox.Show("CANCEL COMMAND IS NOT YET IMPLEMENTED IN SERIAL.");
                    } else {
                        var resp = _device.Cancel();
                        _responseControl = new ResponseControl(resp);
                    }
                }
            }).Start();
        }

        private void CloseProcessingDialog() {
            new Thread(() => {
                if(_processing.Visible)
                    _processing.Invoke((MethodInvoker)delegate { _processing.Close(); });
            }).Start();
        }

        #endregion

        #region Button
        private void btnSendRequestMessage_Click(object sender, EventArgs e) {
            ComboBoxItem item = (ComboBoxItem)cmbPaymentType.SelectedItem;

            if(IsSerial && !IsTcpIp) {
                if(_device == null) {
                    MessageBox.Show("No Device Connected.", "Error");
                    return;
                }
            } else {
                if (_device.ConnectedDevicesCount() == 0) {
                    MessageBox.Show("No Device Connected.", "Error");
                    return;
                }
            }

            if(item != null) {
                switch (item.Value) {
                    case 0: Sale(); break;
                    case 1: Refund();  break;
                    case 2: CompletionMode(); break;
                    case 3: PreAuthMode(); break;
                    case 4: TaxFreeCreditRefund(); break;
                    case 5: TaxFreeCashRefund(); break;
                    case 6: AccountVerification(); break;
                    case 9: ReferralConfirmation();  break;
                    default: MessageBox.Show("Invalid Payment Type.", "Error"); break;
                }
            } else {
                MessageBox.Show("Please select Payment Type.", "Error");
            }
        }

        private void btnDuplicate_Click(object sender, EventArgs e) {
            new Thread(() => {
                try {
                    IDeviceResponse resp;

                    if (IsSerial && !IsTcpIp) {
                        if (_device == null)
                            throw new Exception("No Device Connected.");
                    } else {
                        if (_device.ConnectedDevicesCount() == 0)
                            throw new Exception("No Device Connected.");
                    }

                    ShowProcessingDialog();

                    resp = _device.Duplicate(isAutoTicketEnabled);

                    CloseProcessingDialog();

                    //Handle error if ticket failed
                    if (((IngenicoTerminalResponse)resp).IsReceiptSuccess == false && isAutoTicketEnabled)
                    {
                        MessageBox.Show(((IngenicoTerminalResponse)resp).ReceiptErrorMessage, "Error");
                    }

                    _responseControl = new ResponseControl(resp);

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        private void btnReverse_Click(object sender, EventArgs e) {
            new Thread(() => {
                try {
                    IDeviceResponse resp;

                    if (IsSerial && !IsTcpIp) {
                        if (_device == null)
                            throw new Exception("No Device Connected.");
                    } else {
                        if (_device.ConnectedDevicesCount() == 0)
                            throw new Exception("No Device Connected.");
                    }

                    var result = MessageBox.Show("Would like to reverse a specific transaction?", "SDK Information", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                    
                    if(result == DialogResult.Yes) {
                        TransactionNumber transaction = new TransactionNumber(this);
                        result = transaction.ShowDialog();
                    }

                    ShowProcessingDialog();

                    resp = _device.Reverse(Convert.ToDecimal(txtAmount.Text))
                                .WithTransactionId(TransactionId)
                                .WithReferenceNumber(Convert.ToInt32(txtEPoSNumber.Text))
                                .WithTicket(isAutoTicketEnabled)
                                .Execute();

                    CloseProcessingDialog();

                    //Handle error if ticket failed
                    if (((IngenicoTerminalResponse)resp).IsReceiptSuccess == false && isAutoTicketEnabled)
                    {
                        MessageBox.Show(((IngenicoTerminalResponse)resp).ReceiptErrorMessage, "Error");
                    }

                    _responseControl = new ResponseControl(resp);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        private void btnClear_Click(object sender, EventArgs e) {
            try {
                this.Clear();
                _responseControl.Clear();
            } catch (Exception ex) {
                MessageBox.Show(ex.Message, "Error");
            }
        }

        private void btnEOD_Click(object sender, EventArgs e) {
            new Thread(() => {
                try {

                    if (IsSerial && !IsTcpIp) {
                        if (_device == null)
                            throw new Exception("No Device Connected.");
                    } else {
                        if (_device.ConnectedDevicesCount() == 0)
                            throw new Exception("No Device Connected.");
                    }

                    ShowProcessingDialog();

                    var resp = _device.GetReport(ReportType.EOD)
                                    .Execute();

                    CloseProcessingDialog();

                    _responseControl = new ResponseControl(resp, 0);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        private void btnBanking_Click(object sender, EventArgs e) {
            new Thread(() => {
                try {

                    if (IsSerial && !IsTcpIp) {
                        if (_device == null)
                            throw new Exception("No Device Connected.");
                    } else {
                        if (_device.ConnectedDevicesCount() == 0)
                            throw new Exception("No Device Connected.");
                    }

                    ShowProcessingDialog();

                    var resp = _device.GetReport(ReportType.BANKING)
                                    .Execute();

                    CloseProcessingDialog();                   

                    _responseControl = new ResponseControl(resp, 0);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        private void btnXBalance_Click(object sender, EventArgs e) {
            new Thread(() => {
                try {

                    if (IsSerial && !IsTcpIp) {
                        if (_device == null)
                            throw new Exception("No Device Connected.");
                    } else {
                        if (_device.ConnectedDevicesCount() == 0)
                            throw new Exception("No Device Connected.");
                    }

                    ShowProcessingDialog();

                    var resp = _device.GetReport(ReportType.XBAL)
                                        .Execute();

                    CloseProcessingDialog();

                    _responseControl = new ResponseControl(resp, 0);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        private void btnZBalance_Click(object sender, EventArgs e) {
            new Thread(() => {
                try {

                    if (IsSerial && !IsTcpIp) {
                        if (_device == null)
                            throw new Exception("No Device Connected.");
                    } else {
                        if (_device.ConnectedDevicesCount() == 0)
                            throw new Exception("No Device Connected.");
                    }

                    ShowProcessingDialog();

                    var resp = _device.GetReport(ReportType.ZBAL)
                                    .Execute();

                    CloseProcessingDialog();

                    _responseControl = new ResponseControl(resp, 0);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        private void btnReport_Click(object sender, EventArgs e) {
            new Thread(() => {
                try {

                    if (IsSerial && !IsTcpIp) {
                        if (_device == null)
                            throw new Exception("No Device Connected.");
                    } else {
                        if (_device.ConnectedDevicesCount() == 0)
                            throw new Exception("No Device Connected.");
                    }

                    ShowProcessingDialog();

                    var resp = _device.GetLastReceipt(ReceiptType.REPORT)
                                    .Execute();

                    CloseProcessingDialog();

                    _responseControl = new ResponseControl(resp, 1);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        private void btnTicket_Click(object sender, EventArgs e) {
            new Thread(() => {
                try {

                    if (IsSerial && !IsTcpIp) {
                        if (_device == null)
                            throw new Exception("No Device Connected.");
                    } else {
                        if (_device.ConnectedDevicesCount() == 0)
                            throw new Exception("No Device Connected.");
                    }

                    ShowProcessingDialog();

                    var resp = _device.GetLastReceipt()
                                    .Execute();

                    CloseProcessingDialog();

                    _responseControl = new ResponseControl(resp, 1);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        private void btnSplitReport_Click(object sender, EventArgs e) {
            new Thread(() => {
                try {

                    if (IsSerial && !IsTcpIp) {
                        if (_device == null)
                            throw new Exception("No Device Connected.");
                    } else {
                        if (_device.ConnectedDevicesCount() == 0)
                            throw new Exception("No Device Connected.");
                    }

                    ShowProcessingDialog();

                    var resp = _device.GetLastReceipt(ReceiptType.SPLITR)
                                    .Execute();

                    CloseProcessingDialog();

                    _responseControl = new ResponseControl(resp, 1);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        private void btnTaxFreeReceipt_Click(object sender, EventArgs e) {
            new Thread(() => {
                try {

                    if (IsSerial && !IsTcpIp) {
                        if (_device == null)
                            throw new Exception("No Device Connected.");
                    } else {
                        if (_device.ConnectedDevicesCount() == 0)
                            throw new Exception("No Device Connected.");
                    }

                    ShowProcessingDialog();

                    var resp = _device.GetLastReceipt(ReceiptType.TAXFREE)
                                    .Execute();

                    CloseProcessingDialog();

                    _responseControl = new ResponseControl(resp, 1);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        private void btnCallTMS_Click(object sender, EventArgs e) {
            new Thread(() => {
                try {

                    if (IsSerial && !IsTcpIp) {
                        if (_device == null)
                            throw new Exception("No Device Connected.");
                    } else {
                        if (_device.ConnectedDevicesCount() == 0)
                            throw new Exception("No Device Connected.");
                    }

                    ShowProcessingDialog();

                    var resp = _device.GetTerminalConfiguration();

                    CloseProcessingDialog();

                    _responseControl = new ResponseControl(resp);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        private void btnLogon_Click(object sender, EventArgs e) {
            new Thread(() => {
                try {

                    if (IsSerial && !IsTcpIp) {
                        if (_device == null)
                            throw new Exception("No Device Connected.");
                    } else {
                        if (_device.ConnectedDevicesCount() == 0)
                            throw new Exception("No Device Connected.");
                    }

                    ShowProcessingDialog();

                    var resp = _device.TestConnection(isAutoTicketEnabled);

                    CloseProcessingDialog();

                    //Handle error if ticket failed
                    if (((IngenicoTerminalResponse)resp).IsReceiptSuccess == false && isAutoTicketEnabled)
                    {
                        MessageBox.Show(((IngenicoTerminalResponse)resp).ReceiptErrorMessage, "Error");
                    }

                    _responseControl = new ResponseControl(resp);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        private void btnReset_Click(object sender, EventArgs e) {
            new Thread(() => {
                try {

                    if (_device.ConnectedDevicesCount() == 0)
                        throw new Exception("No Device Connected.");

                    ShowProcessingDialog();

                    var resp = _device.Reboot();

                    CloseProcessingDialog();

                    _responseControl = new ResponseControl(resp);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        private void btnState_Click(object sender, EventArgs e) {
            new Thread(() => {
                try {

                    if (IsSerial && !IsTcpIp) {
                        if (_device == null)
                            throw new Exception("No Device Connected.");
                    } else {
                        if (_device.ConnectedDevicesCount() == 0)
                            throw new Exception("No Device Connected.");
                    }

                    ShowProcessingDialog();

                    var resp = _device.GetTerminalStatus();

                    CloseProcessingDialog();

                    _responseControl = new ResponseControl((StateResponse)resp);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        private void btnPID_Click(object sender, EventArgs e) {
            new Thread(() => {
                try {

                    if(IsSerial && !IsTcpIp) {
                        if(_device == null)
                            throw new Exception("No Device Connected.");
                    } else {
                        if (_device.ConnectedDevicesCount() == 0)
                            throw new Exception("No Device Connected.");
                    }

                    ShowProcessingDialog();

                    var resp = _device.Initialize();

                    CloseProcessingDialog();

                    _responseControl = new ResponseControl(resp);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }
        #endregion

        #region Payment Transactions
        private void Sale() {
            new Thread(() => {
                try {

                    ValidateFields(0);

                    ShowProcessingDialog();

                    var resp = _device.Sale(_amount)
                                    .WithReferenceNumber(Convert.ToInt32(txtEPoSNumber.Text))
                                    .WithPaymentMode((PaymentMode)Convert.ToInt32(txtPaymentMode.Text))
                                    .WithCurrencyCode(txtCurrency.Text)
                                    .WithTableNumber(txtTableNumber.Text)
                                    .WithCashBack(_cashBack)
                                    .WithTicket(isAutoTicketEnabled)
                                    .Execute();

                    CloseProcessingDialog();

                    //Handle error if ticket failed
                    if (((IngenicoTerminalResponse)resp).IsReceiptSuccess == false && isAutoTicketEnabled)
                    {
                        MessageBox.Show(((IngenicoTerminalResponse)resp).ReceiptErrorMessage, "Error");
                    }

                    _responseControl = new ResponseControl(resp);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        private void Refund() {
            new Thread(() => {
                try {
                    ValidateFields(1);

                    ShowProcessingDialog();

                    var resp = _device.Refund(_amount)
                                    .WithReferenceNumber(Convert.ToInt32(txtEPoSNumber.Text))
                                    .WithPaymentMode((PaymentMode)Convert.ToInt32(txtPaymentMode.Text))
                                    .WithCurrencyCode(txtCurrency.Text)
                                    .WithTableNumber(txtTableNumber.Text)
                                    .WithTicket(isAutoTicketEnabled)
                                    .Execute();

                    CloseProcessingDialog();

                    //Handle error if ticket failed
                    if (((IngenicoTerminalResponse)resp).IsReceiptSuccess == false && isAutoTicketEnabled)
                    {
                        MessageBox.Show(((IngenicoTerminalResponse)resp).ReceiptErrorMessage, "Error");
                    }

                    _responseControl = new ResponseControl(resp);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        private void CompletionMode() {
            new Thread(() => {
                try {
                    ValidateFields(2);

                    ShowProcessingDialog();

                    var resp = _device.Capture(_amount)
                                    .WithReferenceNumber(Convert.ToInt32(txtEPoSNumber.Text))
                                    .WithCurrencyCode(txtCurrency.Text)
                                    .WithAuthCode(txtAuthCode.Text)
                                    .WithTicket(isAutoTicketEnabled)
                                    .Execute();

                    CloseProcessingDialog();

                    //Handle error if ticket failed
                    if (((IngenicoTerminalResponse)resp).IsReceiptSuccess == false && isAutoTicketEnabled)
                    {
                        MessageBox.Show(((IngenicoTerminalResponse)resp).ReceiptErrorMessage, "Error");
                    }

                    _responseControl = new ResponseControl(resp);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        private void PreAuthMode() {
            new Thread(() => {
                try {
                    ValidateFields(3);

                    ShowProcessingDialog();

                    var resp = _device.Authorize(_amount)
                                    .WithReferenceNumber(Convert.ToInt32(txtEPoSNumber.Text))
                                    .WithCurrencyCode(txtCurrency.Text)
                                    .WithPaymentMode((PaymentMode)Convert.ToInt32(txtPaymentMode.Text))
                                    .WithTableNumber(txtTableNumber.Text)
                                    .WithTicket(isAutoTicketEnabled)
                                    .Execute();

                    CloseProcessingDialog();

                    //Handle error if ticket failed
                    if (((IngenicoTerminalResponse)resp).IsReceiptSuccess == false && isAutoTicketEnabled)
                    {
                        MessageBox.Show(((IngenicoTerminalResponse)resp).ReceiptErrorMessage, "Error");
                    }

                    _responseControl = new ResponseControl(resp);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        private void TaxFreeCreditRefund() {
            new Thread(() => {
                try {
                    ValidateFields(4);

                    ShowProcessingDialog();

                    var resp = _device.Refund(_amount)
                                    .WithReferenceNumber(Convert.ToInt32(txtEPoSNumber.Text))
                                    .WithCurrencyCode(txtCurrency.Text)
                                    .WithTaxFree(TaxFreeType.CREDIT)
                                    .Execute();

                    CloseProcessingDialog();

                    _responseControl = new ResponseControl(resp);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        private void TaxFreeCashRefund() {
            new Thread(() => {
                try {
                    ValidateFields(5);

                    ShowProcessingDialog();

                    var resp = _device.Refund(_amount)
                                    .WithReferenceNumber(Convert.ToInt32(txtEPoSNumber.Text))
                                    .WithCurrencyCode(txtCurrency.Text)
                                    .WithTaxFree(TaxFreeType.CASH)
                                    .Execute();

                    CloseProcessingDialog();

                    _responseControl = new ResponseControl(resp);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        #region TO FIX WHEN CONFIRMED
        //private void TaxFreeCreditRefund() {
        //    try {
        //        // TO BE FINALIZE
        //        var response = _device.CompletionMode(Convert.ToDecimal(txtAmount.Text))
        //            .WithReferenceNumber(Convert.ToInt32(txtEPOS.Text))
        //            .WithCurrency(CurrencyType.CASH_BENEFITS)
        //            .WithPaymentMode((IngenicoPaymentMethod)Convert.ToInt32(txtPaymentMode.Text))
        //            .WithAuthCode("022049")
        //            .Execute();

        //        //if (response.ResponseCode == "00") {
        //        #region ResponseClass
        //        var _response = new ResponseMessageClass() {
        //            EposNumber = response.ReferenceNumber,
        //            TransactionStatus = (int)response.TransactionStatus,
        //            Amount = (response.TransactionAmount *= 100)?.ToString("00000000"),
        //            Payment = (int)response.IngenicoPaymentType,
        //            ResponseData = response.ResponseData,
        //            Currency = (int)response.DynamicCurrencyCode,
        //            PrivateData = response.PrivateData
        //        };
        //        #endregion

        //        WriteEposSafe(_response.EposNumber);
        //        WriteStatusSafe(_response.TransactionStatus.ToString());
        //        WriteAmountSafe(_response.Amount);
        //        WritePaymentSafe(_response.Payment.ToString());
        //        WriteResponseDataSafe(_response.ResponseData);
        //        WriteCurrencySafe(_response.Currency.ToString());
        //        WritePrivateDataSafe(_response.PrivateData);
        //        DisplayRawResponse(_response);
        //        //}
        //    }
        //    catch (Exception e) {
        //        if (_device == null) { } else MessageBox.Show(e.Message, "SDK Information");
        //    }
        //}

        //private void TaxFreeCashRefund() {
        //    try {
        //        // TO BE FINALIZE
        //        var response = _device.CompletionMode(Convert.ToDecimal(txtAmount.Text))
        //            .WithReferenceNumber(Convert.ToInt32(txtEPOS.Text))
        //            .WithCurrency(CurrencyType.CASH_BENEFITS)
        //            .WithPaymentMode((IngenicoPaymentMethod)Convert.ToInt32(txtPaymentMode.Text))
        //            .WithAuthCode("022049")
        //            .Execute();

        //        //if (response.ResponseCode == "00") {
        //        #region ResponseClass
        //        var _response = new ResponseMessageClass() {
        //            EposNumber = response.ReferenceNumber,
        //            TransactionStatus = (int)response.TransactionStatus,
        //            Amount = (response.TransactionAmount *= 100)?.ToString("00000000"),
        //            Payment = (int)response.IngenicoPaymentType,
        //            ResponseData = response.ResponseData,
        //            Currency = (int)response.DynamicCurrencyCode,
        //            PrivateData = response.PrivateData
        //        };
        //        #endregion

        //        WriteEposSafe(_response.EposNumber);
        //        WriteStatusSafe(_response.TransactionStatus.ToString());
        //        WriteAmountSafe(_response.Amount);
        //        WritePaymentSafe(_response.Payment.ToString());
        //        WriteResponseDataSafe(_response.ResponseData);
        //        WriteCurrencySafe(_response.Currency.ToString());
        //        WritePrivateDataSafe(_response.PrivateData);
        //        DisplayRawResponse(_response);
        //        //}
        //    }
        //    catch (Exception e) {
        //        if (_device == null) { } else MessageBox.Show(e.Message, "SDK Information");
        //    }
        //}
        #endregion

        private void AccountVerification() {
            new Thread(() => {
                try {
                    ValidateFields(6);

                    ShowProcessingDialog();

                    var resp = _device.Verify()
                                    .WithAmount(_amount)
                                    .WithReferenceNumber(Convert.ToInt32(txtEPoSNumber.Text))
                                    .WithPaymentMode((PaymentMode)Convert.ToInt32(txtPaymentMode.Text))
                                    .WithCurrencyCode(txtCurrency.Text)
                                    .WithTicket(isAutoTicketEnabled)
                                    .Execute();

                    CloseProcessingDialog();

                    //Handle error if ticket failed
                    if (((IngenicoTerminalResponse)resp).IsReceiptSuccess == false && isAutoTicketEnabled)
                    {
                        MessageBox.Show(((IngenicoTerminalResponse)resp).ReceiptErrorMessage, "Error");
                    }

                    _responseControl = new ResponseControl(resp);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }

        private void ReferralConfirmation() {
            new Thread(() => {
                try {
                    ValidateFields(9);

                    ShowProcessingDialog();

                    var resp = _device.ReferralConfirmation()
                                    .WithReferenceNumber(Convert.ToInt32(txtEPoSNumber.Text))
                                    .WithCurrencyCode(txtCurrency.Text)
                                    .WithAuthCode(txtAuthCode.Text)
                                    .WithTicket(isAutoTicketEnabled)
                                    .Execute();

                    CloseProcessingDialog();

                    //Handle error if ticket failed
                    if (((IngenicoTerminalResponse)resp).IsReceiptSuccess == false && isAutoTicketEnabled)
                    {
                        MessageBox.Show(((IngenicoTerminalResponse)resp).ReceiptErrorMessage, "Error");
                    }

                    _responseControl = new ResponseControl(resp);

                    TransactionId = string.Empty;

                } catch (Exception e) {
                    CloseProcessingDialog();
                    MessageBox.Show(e.Message, "Error");
                } finally {
                    MessageBox.Show("Transaction Complete!", "Success");
                }
            }).Start();
        }
        #endregion

        #region Validation
        private void ValidateFields(int paymentValue) {
            decimal? amount;

            _amount = null;
            _cashBack = null;

            if (paymentValue.Equals(null))
                throw new Exception("Please select type of Payment");

            if (string.IsNullOrEmpty(txtEPoSNumber.Text))
                throw new Exception("Please fill the EPoS Number.");

            if (string.IsNullOrEmpty(txtCurrency.Text))
                throw new Exception("Please fill the Currency.");

            switch (paymentValue) {
                case 0:
                case 1:
                case 3:
                case 6:
                    if (string.IsNullOrEmpty(txtPaymentMode.Text))
                        throw new Exception("Please fill the Payment Mode.");

                    if (string.IsNullOrEmpty(txtAmount.Text))
                        throw new Exception("Please fill the Amount.");

                    if (txtAmount.Text.Equals("."))
                        Invoker.SetTextBox(txtAmount, "0.0");

                    if (txtAmount.Text.Count(f => (f == '.')) > 1)
                        throw new Exception("Invalid Amount.");

                    amount = decimal.Parse(txtAmount.Text);

                    if (amount > 99999999 || amount <= 0)
                        throw new Exception("Amount must be less than or equal 8 but not be equal or less than to 0 numerics.");

                    _amount = amount;
                    break;

                case 2:
                case 4:
                case 5:
                    if (string.IsNullOrEmpty(txtAmount.Text))
                        throw new Exception("Please fill the Amount.");

                    if (txtAmount.Text.Equals("."))
                        Invoker.SetTextBox(txtAmount, "0.0");

                    if (txtAmount.Text.Count(f => (f == '.')) > 1)
                        throw new Exception("Invalid Amount.");

                    amount = decimal.Parse(txtAmount.Text);

                    if (amount > 99999999 || amount <= 0)
                        throw new Exception("Amount must be less than or equal 8 but not be equal or less than to 0 numerics.");

                    _amount = amount;
                    break;

                default:
                    break;
            }

            if(!string.IsNullOrEmpty(txtCashback.Text)) {
                if (txtCashback.Text.Equals("."))
                    Invoker.SetTextBox(txtCashback, "0.0");

                if (txtCashback.Text.Count(f => (f == '.')) > 1)
                    throw new Exception("Invalid Cashback Amount.");

                amount = decimal.Parse(txtCashback.Text);

                if (amount > 99999999 || amount <= 0)
                    throw new Exception("Cashback Amount must be less than or equal 8 but not be equal or less than to 0 numerics.");

                _cashBack = amount;
            }
        }

        #endregion

        private void chkEnableAutoTicket_CheckedChanged(object sender, EventArgs e)
        {
            if (chkEnableAutoTicket.Checked)
                isAutoTicketEnabled = true;
            else
                isAutoTicketEnabled = false;
        }
    }
}