using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

using Betfair.Gamex.API;
using Betfair.Gamex.API.Entities;
using Betfair.Gamex.API.UberClient.Classes;

namespace Betfair.Gamex.API.UberClient.Controls
{
    /// <summary>
    /// Allows user to transfer funds to and from games
    /// </summary>
    public class FundsTransfer : System.Windows.Forms.Form
    {
        private System.Windows.Forms.TextBox tbTransferAmount;
        private System.Windows.Forms.RadioButton rdFromBetfair;
        private System.Windows.Forms.Button btnOk;
        private System.Windows.Forms.Button btnCancel;
        private System.Windows.Forms.Label lblBetfairBalance;
        private System.Windows.Forms.Label lblBetfairGamesBalance;
        private System.Windows.Forms.Label lblTitle;
        private System.Windows.Forms.RadioButton rdToBetfair;

        private Adapter m_Adapter;
        private MainForm m_MainForm;
        private double m_BetfairBalance = 0;
        private double m_BetfairGamesBalance = 0;
        private string m_Currency;

        public FundsTransfer(Adapter apiAdapter, MainForm main)
        {
            InitializeComponent();
            m_MainForm = main;
            m_Adapter = apiAdapter;
            _LoadBalances();
        }

        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            System.Windows.Forms.GroupBox gbFundsTransfer;
            System.Windows.Forms.Label lblAmount;
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FundsTransfer));
            System.Windows.Forms.Label lblTransfer;
            this.lblTitle = new System.Windows.Forms.Label();
            this.lblBetfairGamesBalance = new System.Windows.Forms.Label();
            this.lblBetfairBalance = new System.Windows.Forms.Label();
            this.tbTransferAmount = new System.Windows.Forms.TextBox();
            this.rdFromBetfair = new System.Windows.Forms.RadioButton();
            this.rdToBetfair = new System.Windows.Forms.RadioButton();
            this.btnOk = new System.Windows.Forms.Button();
            this.btnCancel = new System.Windows.Forms.Button();
            gbFundsTransfer = new System.Windows.Forms.GroupBox();
            lblAmount = new System.Windows.Forms.Label();
            lblTransfer = new System.Windows.Forms.Label();
            gbFundsTransfer.SuspendLayout();
            this.SuspendLayout();
            // 
            // gbFundsTransfer
            // 
            gbFundsTransfer.BackColor = System.Drawing.Color.Transparent;
            gbFundsTransfer.Controls.Add(lblAmount);
            gbFundsTransfer.Controls.Add(this.lblTitle);
            gbFundsTransfer.Controls.Add(this.lblBetfairGamesBalance);
            gbFundsTransfer.Controls.Add(this.lblBetfairBalance);
            gbFundsTransfer.Controls.Add(this.tbTransferAmount);
            gbFundsTransfer.Controls.Add(this.rdFromBetfair);
            gbFundsTransfer.Controls.Add(this.rdToBetfair);
            gbFundsTransfer.Controls.Add(this.btnOk);
            gbFundsTransfer.Controls.Add(this.btnCancel);
            gbFundsTransfer.Controls.Add(lblTransfer);
            gbFundsTransfer.Location = new System.Drawing.Point(8, 0);
            gbFundsTransfer.Name = "gbFundsTransfer";
            gbFundsTransfer.Size = new System.Drawing.Size(216, 160);
            gbFundsTransfer.TabIndex = 6;
            gbFundsTransfer.TabStop = false;
            // 
            // lblAmount
            // 
            lblAmount.Location = new System.Drawing.Point(9, 90);
            lblAmount.Name = "lblAmount";
            lblAmount.Size = new System.Drawing.Size(48, 16);
            lblAmount.TabIndex = 15;
            lblAmount.Text = "Amount:";
            // 
            // lblTitle
            // 
            this.lblTitle.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.lblTitle.Location = new System.Drawing.Point(8, 10);
            this.lblTitle.Name = "lblTitle";
            this.lblTitle.Size = new System.Drawing.Size(100, 16);
            this.lblTitle.TabIndex = 14;
            this.lblTitle.Text = "Balances:";
            // 
            // lblBetfairGamesBalance
            // 
            this.lblBetfairGamesBalance.Location = new System.Drawing.Point(8, 47);
            this.lblBetfairGamesBalance.Name = "lblBetfairGamesBalance";
            this.lblBetfairGamesBalance.Size = new System.Drawing.Size(216, 16);
            this.lblBetfairGamesBalance.TabIndex = 13;
            this.lblBetfairGamesBalance.Text = "Betfair Games: Unknown";
            // 
            // lblBetfairBalance
            // 
            this.lblBetfairBalance.Location = new System.Drawing.Point(8, 28);
            this.lblBetfairBalance.Name = "lblBetfairBalance";
            this.lblBetfairBalance.Size = new System.Drawing.Size(216, 16);
            this.lblBetfairBalance.TabIndex = 12;
            this.lblBetfairBalance.Text = "Betfair: Unknown";
            // 
            // tbTransferAmount
            // 
            this.tbTransferAmount.Location = new System.Drawing.Point(58, 87);
            this.tbTransferAmount.Name = "tbTransferAmount";
            this.tbTransferAmount.Size = new System.Drawing.Size(142, 20);
            this.tbTransferAmount.TabIndex = 7;
            this.tbTransferAmount.Text = "0";
            this.tbTransferAmount.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
            this.tbTransferAmount.TextChanged += new System.EventHandler(this.tbTransferAmount_TextChanged);
            this.tbTransferAmount.KeyDown += new System.Windows.Forms.KeyEventHandler(this.tbTransferAmount_KeyDown);
            // 
            // rdFromBetfair
            // 
            this.rdFromBetfair.BackColor = System.Drawing.Color.Transparent;
            this.rdFromBetfair.Checked = true;
            this.rdFromBetfair.ForeColor = System.Drawing.Color.Black;
            this.rdFromBetfair.Location = new System.Drawing.Point(13, 112);
            this.rdFromBetfair.Name = "rdFromBetfair";
            this.rdFromBetfair.Size = new System.Drawing.Size(88, 24);
            this.rdFromBetfair.TabIndex = 8;
            this.rdFromBetfair.TabStop = true;
            this.rdFromBetfair.Text = "From Betfair";
            this.rdFromBetfair.UseVisualStyleBackColor = false;
            // 
            // rdToBetfair
            // 
            this.rdToBetfair.BackColor = System.Drawing.Color.Transparent;
            this.rdToBetfair.ForeColor = System.Drawing.Color.Black;
            this.rdToBetfair.Location = new System.Drawing.Point(13, 129);
            this.rdToBetfair.Name = "rdToBetfair";
            this.rdToBetfair.Size = new System.Drawing.Size(88, 27);
            this.rdToBetfair.TabIndex = 9;
            this.rdToBetfair.Text = "To Betfair";
            this.rdToBetfair.UseVisualStyleBackColor = false;
            // 
            // btnOk
            // 
            this.btnOk.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("btnOk.BackgroundImage")));
            this.btnOk.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
            this.btnOk.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.btnOk.ForeColor = System.Drawing.Color.White;
            this.btnOk.Location = new System.Drawing.Point(168, 122);
            this.btnOk.Name = "btnOk";
            this.btnOk.Size = new System.Drawing.Size(31, 23);
            this.btnOk.TabIndex = 11;
            this.btnOk.Text = "OK";
            this.btnOk.Click += new System.EventHandler(this.btnOk_Click);
            // 
            // btnCancel
            // 
            this.btnCancel.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("btnCancel.BackgroundImage")));
            this.btnCancel.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
            this.btnCancel.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.btnCancel.ForeColor = System.Drawing.Color.White;
            this.btnCancel.Location = new System.Drawing.Point(112, 122);
            this.btnCancel.Name = "btnCancel";
            this.btnCancel.Size = new System.Drawing.Size(53, 23);
            this.btnCancel.TabIndex = 10;
            this.btnCancel.Text = "Cancel";
            this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
            // 
            // lblTransfer
            // 
            lblTransfer.BackColor = System.Drawing.Color.Transparent;
            lblTransfer.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            lblTransfer.ForeColor = System.Drawing.Color.Black;
            lblTransfer.Location = new System.Drawing.Point(9, 65);
            lblTransfer.Name = "lblTransfer";
            lblTransfer.Size = new System.Drawing.Size(205, 16);
            lblTransfer.TabIndex = 6;
            lblTransfer.Text = "How much would you like to transfer?";
            lblTransfer.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
            // 
            // FundsTransfer
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("$this.BackgroundImage")));
            this.ClientSize = new System.Drawing.Size(231, 166);
            this.Controls.Add(gbFundsTransfer);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.Name = "FundsTransfer";
            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            this.Text = "Transferring Funds";
            gbFundsTransfer.ResumeLayout(false);
            gbFundsTransfer.PerformLayout();
            this.ResumeLayout(false);

        }
        #endregion

        private void _LoadBalances()
        {
            m_Adapter.BeginGetAccountBetfairSnapshot(new AsyncCallback(_AsyncGetBetfairBalance), null);
            m_Adapter.BeginGetAccountSnapshot(new AsyncCallback(_AsyncGetAccountSnapshot), null);
        }

        private void _AsyncGetBetfairBalance(IAsyncResult asyncResult)
        {
            try
            {
                AsyncRequestState requestState = (AsyncRequestState)asyncResult.AsyncState;
                AsyncResponseState responseState = m_Adapter.EndGetAccountBetfairSnapshot(asyncResult);
                betfairAvailableBalance account = (betfairAvailableBalance)responseState.ReturnObject;

                m_BetfairBalance = account.availableToTransferIn;
                m_Currency = account.currency;

                // update labels
                Invoke(new UpdateLabel(_SetLabelText), new object[] { String.Format("Betfair: {0}", Util.FormatMoney(account.availableToTransferIn)), lblBetfairBalance });
                Invoke(new UpdateLabel(_SetLabelText), new object[] { String.Format("Balances ({0}):", account.currency), lblTitle });
            }
            catch
            {
                m_BetfairBalance = -1;
            }
        }

        private void _AsyncGetAccountSnapshot(IAsyncResult asyncResult)
        {
            try
            {
                AsyncRequestState requestState = (AsyncRequestState)asyncResult.AsyncState;
                AsyncResponseState responseState = m_Adapter.EndGetAccountSnapshot(asyncResult);
                accountSnapshot account = (accountSnapshot)responseState.ReturnObject;

                m_BetfairGamesBalance = account.availableToTransferOut;

                // update label
                Invoke(new UpdateLabel(_SetLabelText), new object[] { String.Format("Betfair Games: {0}", Util.FormatMoney(account.availableToTransferOut)), lblBetfairGamesBalance });
            }
            catch
            {
                m_BetfairGamesBalance = -1;
            }
        }

        private void _SetLabelText(string s, Label lbl)
        {
            lbl.Text = s;
        }

        private void btnCancel_Click(object sender, System.EventArgs e)
        {
            this.Close();
        }

        private void btnOk_Click(object sender, System.EventArgs e)
        {
            bool enableOk = false;
            try
            {
                //let's check the value being transfered is valid
                double transferAmount = double.Parse(tbTransferAmount.Text);
                if (transferAmount > 0)
                {
                    //move into games
                    if (rdFromBetfair.Checked)
                    {
                        if (transferAmount > m_BetfairBalance)
                        {
                            if (m_BetfairBalance <= 0)
                            {
                                MessageBox.Show(String.Format("Your Betfair balance is 0.\n\nNo transfer can take place.", Util.FormatMoney(m_BetfairBalance), m_Currency), "Transfer error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            }
                            else
                            {
                                MessageBox.Show(String.Format("You can't transfer more than {0}{1} to your Betfair Games account.", Util.FormatMoney(m_BetfairBalance), m_Currency), "Transfer error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            }

                            tbTransferAmount.Text = m_BetfairBalance.ToString();
                            enableOk = true;
                        }
                        else
                        {
                            m_Adapter.BeginSetAccountTransferOrder(transferAmount, m_Currency, new AsyncCallback(_AsyncSetBalance), transferAmount);
                        }
                    }
                    else //move money back to Betfair
                    {
                        if (transferAmount > m_BetfairGamesBalance)
                        {
                            if (m_BetfairGamesBalance <= 0)
                            {
                                MessageBox.Show(String.Format("You have no available funds in your Betfair Games account to transfer.", Util.FormatMoney(m_BetfairGamesBalance), m_Currency), "Transfer error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            }
                            else
                            {
                                MessageBox.Show(String.Format("A maximum of {0}{1} can be transferred back to your Betfair account.", Util.FormatMoney(m_BetfairGamesBalance), m_Currency), "Transfer error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            }

                            tbTransferAmount.Text = m_BetfairGamesBalance.ToString();
                            enableOk = true;
                        }
                        else
                        {
                            m_Adapter.BeginSetAccountTransferOrder(transferAmount * -1, m_Currency, new AsyncCallback(_AsyncSetBalance), transferAmount);
                        }
                    }
                }
                else
                {
                    enableOk = true;
                }
            }
            catch
            {
                MessageBox.Show("Please enter a valid number to transfer", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                tbTransferAmount.Text = "0";
                enableOk = true;
            }

            _UpdateOKButton(enableOk);
        }

        private void _UpdateOKButton(bool enabled)
        {
            btnOk.Text = (enabled ? "Ok" : "...");
            btnOk.Enabled = enabled;
        }

        private void _AsyncSetBalance(IAsyncResult asyncResult)
        {
            AsyncRequestState requestState = (AsyncRequestState)asyncResult.AsyncState;

            try
            {
                AsyncResponseState responseState = m_Adapter.EndSetAccountTransferOrder(asyncResult);
                responseTransferOrder rto = (responseTransferOrder)responseState.ReturnObject;

                switch (rto.message)
                {
                    case balanceResponseTypeEnum.SUCCESS:
                        MessageBox.Show(String.Format("{0} transferred successfully.", Util.FormatMoney((double)responseState.UserAsyncState)), "Transfer complete", MessageBoxButtons.OK, MessageBoxIcon.Information);

                        // refresh balance on main form
                        m_MainForm.BalanceRefresh_Click(this, null);

                        this.Close();
                        break;
                    case balanceResponseTypeEnum.INSUFFICIENT_FUNDS:
                        _LoadBalances();
                        MessageBox.Show("Insufficient funds to complete your transfer.  Please try again.", "Transfer error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        break;
                    case balanceResponseTypeEnum.FAILED:
                        MessageBox.Show("Unknown error has occurred.");
                        break;
                }
            }
            catch
            {
                MessageBox.Show("There was an error.  Your transfer could not be completed.\n\nPlease try again later.", "Transfer error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            Invoke(new EnableButton(_UpdateOKButton), new object[] { true });
        }

        private void tbTransferAmount_TextChanged(object sender, System.EventArgs e)
        {
            tbTransferAmount.Text = Util.ParseNumericValue(tbTransferAmount.Text);
        }

        private void tbTransferAmount_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
        {
            if (btnOk.Enabled)
            {
                if (e.KeyValue == 13)
                {
                    btnOk_Click(this, null);
                }
                else if (e.KeyValue == 27)
                {
                    this.Close();
                }
            }
        }
    }

    public delegate void UpdateLabel(string s, Label lbl);
    public delegate void EnableButton(bool b);
}
