/// <summary>
        /// Automatically pushes the current hand
        /// </summary>
        public override void AutoPush()
        {
            // Update children
            UpdateChildren();

            // Get the bet box
            ChildWindow box = getBetBox();

            // If we found the bet box, set it's value
            if (box != null)
            {
                Thread t = new Thread(new ThreadStart(delegate()
                {
                    string betValue = "99";

                    for (int i = 0; i <= 5; i++)
                    {
                        // Make sure the window has focus, and it's the active window, otherwise the window might not recognize the text update
                        Win32.ShowWindow(handle, (int)Win32.SW.SHOWNORMAL);
                        Win32.SetForegroundWindow(handle);
                        Win32.BringWindowToTop((IntPtr)handle);

                        // Click the raise box to ensure that we've got focus
                        Win32.ClickButton(box.Handle);

                        // Set the value
                        Win32.SetText(box.Handle, betValue);

                        // Add a 9 to the betvalue
                        betValue += "9";

                        Thread.Sleep(5);
                    }

                    // Sleep 25ms to make sure the amount get's a chance to be entered
                    System.Threading.Thread.Sleep(10);

                    // Push the raise button
                    this.BetRaise();
                }));

                t.Start();
            }
        }
        /// <summary>
        /// Clicks the Bet / Raise button on the table
        /// </summary>
        public override void BetRaise()
        {
            // Update children
            UpdateChildren();

            ChildWindow betRaiseButton = null;

            // Loop children to find bet/raise button
            foreach (ChildWindow child in children.Values)
            {
                if (child.ControlID == 1033)                 // RAISE/BET
                {
                    if (child.IsVisible)
                    {
                        betRaiseButton = child;
                    }
                }
            }

            // If we found the raise button, raise
            if (betRaiseButton != null)
            {
                ChildWindow betBox = getBetBox();

                // If it's NL, check that the user has entered a raise amount before raising, otherwise, just raise
                if (betBox != null)
                {
                    if (!Settings.AllowNoAmountBetRaise && Win32.GetTextLength(betBox.Handle) > 0)
                    {
                        Win32.ClickButton(betRaiseButton.Handle);
                    }
                    else
                    {
                        Win32.ClickButton(betRaiseButton.Handle);
                    }
                }
                else
                {
                    Win32.ClickButton(betRaiseButton.Handle);
                }
            }
        }
        /// <summary>
        /// Clicks the Fold button on the table
        /// </summary>
        public override void Fold()
        {
            // Update children
            UpdateChildren();

            ChildWindow foldButton = null;

            foreach (ChildWindow child in children.Values)
            {
                if (child.SizeRatio < 4 && child.IsVisible && child.Text.ToLower().StartsWith("fold"))
                {
                    foldButton = child;
                    break;
                }
            }

            if (foldButton != null)
            {
                Win32.ClickButton(foldButton.Handle);
            }
        }
        /// <summary>
        /// Clicks the Fold button on the table
        /// </summary>
        public override void Fold()
        {
            // Update children
            UpdateChildren();

            ChildWindow foldButton = null;

            foreach (ChildWindow child in children.Values)
            {
                if (child.IsVisible && child.ControlID == 1031)
                {
                    foldButton = child;
                    break;
                }
            }

            if (foldButton != null)
            {
                Win32.ClickButton(foldButton.Handle);
            }
        }
        public override void SetRaiseValue(string value)
        {
            // Get the bet box
            ChildWindow box = getBetBox();

            // If we found the bet box, set it's value
            if (box != null)
            {
                // Make sure the window has focus, and it's the active window, otherwise the window might not recognize the text update

                /*
                 *      Win32.ShowWindow(handle, (int)Win32.SW.SHOWNORMAL);
                 *      Win32.SetForegroundWindow(handle);
                 *      Win32.BringWindowToTop((IntPtr)handle);
                 */

                // Click the raise box to ensure that we've got focus
                Win32.ClickButton(box.Handle);

                // Set the value
                Win32.SetText(box.Handle, value);
            }
        }
        /// <summary>
        /// Fires when a SHOWWINDOW message is received from the table
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void wh_OnMessageHook(object sender, MessageHookEventArgs e)
        {
            switch (e.msg)
            {
            // A window has been hidden / visible
            case StandardMessages.WM_SHOWWINDOW:
                string txt = Win32.GetText((int)e.hwnd).ToLower();

                if (txt.Length == 0)
                {
                    return;
                }

                Log.Write("WinHooker: WM_SHOWWINDOW - '" + txt + "', visibility: " + e.wp);

                ChildWindow child = new ChildWindow((int)e.hwnd);

                if ((txt.StartsWith("raise") || txt.StartsWith("bet") || txt.StartsWith("all") || txt.StartsWith("fold") || txt.StartsWith("wait") || txt.StartsWith("call") || txt.StartsWith("check") || txt.StartsWith("post") || txt.StartsWith("sit out")) && !txt.Contains("respond"))
                {
                    Log.Write("Window is action text");
                    if (child.SizeRatio < 4)
                    {
                        Log.Write("Window has correct size ratio, wp is: " + e.wp + ", needsAction is: " + needsAction);
                        if (Convert.ToBoolean(e.wp) && !needsAction)
                        {
                            Log.Write("Needs action now");

                            // Update children
                            UpdateChildren();

                            // We need action now, we didn't before
                            needsAction = true;

                            // If it's a tourney, check the blind level
                            if (GameForm == TableFactory.GameForm.SNG)
                            {
                                // Get blind level
                                int newBlindLevel = getBlindLevel();

                                // Save the blind level and destroy the border form
                                if (blindLevel != newBlindLevel)
                                {
                                    if (borderForm != null && !borderForm.Visible)
                                    {
                                        borderForm.Dispose();
                                        borderForm = null;
                                    }

                                    blindLevel = newBlindLevel;
                                }
                            }

                            // Fire event
                            requiresAction();

                            // Start timer
                            watch.Reset();
                            watch.Start();

                            // Update last action date
                            lastRequiredAction = DateTime.Now;
                        }
                        else if (needsAction && !Convert.ToBoolean(e.wp))
                        {
                            Log.Write("No longer needs action");

                            // We don't need action any more
                            needsAction = false;

                            // Fire event
                            noLongerRequiresAction();

                            // Stop timer
                            watch.Stop();
                            cumulativeResponseTime += watch.ElapsedMilliseconds;
                            actionCount++;

                            // Update last action date
                            lastRequiredAction = DateTime.Now;
                        }

                        actionButtonsVisible = Convert.ToBoolean(e.wp);

                        // Check if it's wait for bb button
                        if (txt == "wait for bb" && Settings.AutoWaitForBB && Convert.ToBoolean(e.wp))
                        {
                            Log.Write("Wait for BB detected, autowait enabled, clicking button");

                            Win32.ClickButton((int)e.hwnd);

                            if (Settings.AutoClickAutoPostBlind)
                            {
                                Log.Write("We've clicked wait for bb button, now click auto post blind");

                                CheckAutoPostBlind();
                            }

                            return;
                        }

                        // Check if it's post sb/bb button
                        if ((txt.StartsWith("post bb") || txt.StartsWith("post sb")) && Settings.AutoPostBlind && Convert.ToBoolean(e.wp))
                        {
                            Log.Write("Post sb/bb detected");

                            if (!Settings.AutoWaitForBB)
                            {
                                Log.Write("We're not waiting for bb, clicking post button");

                                Win32.ClickButton((int)e.hwnd);

                                if (Settings.AutoClickAutoPostBlind)
                                {
                                    Log.Write("We've posted a blind, and we're auto clicking auto post blind");

                                    CheckAutoPostBlind();
                                }
                            }
                            else
                            {
                                Log.Write("We're waiting for bb, launching delayed click of wait for sb button");

                                System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();

                                t.Interval = 80;
                                t.Tag      = e.hwnd.ToString();

                                t.Tick += new EventHandler(delegate(object tSender, EventArgs eArgs)
                                {
                                    int hwnd = Convert.ToInt32(((System.Windows.Forms.Timer)tSender).Tag);

                                    Log.Write("Delayed post blind timer tick");

                                    if (Win32.IsWindowVisible(hwnd))
                                    {
                                        if (Win32.GetText(hwnd).ToLower().StartsWith("post "))
                                        {
                                            Log.Write("Post blind button still available, clicking");

                                            Win32.ClickButton(hwnd);

                                            if (Settings.AutoClickAutoPostBlind)
                                            {
                                                Log.Write("We've posted a blind, and we're auto clicking auto post blind");

                                                CheckAutoPostBlind();
                                            }
                                        }
                                    }

                                    t.Enabled = false;
                                });

                                t.Enabled = true;
                            }
                        }
                    }
                }
                else if (txt.StartsWith("i am back") && child.SizeRatio < 4)
                {
                    Log.Write("Window is sitting out text, wp is: " + e.wp + ", IsSittingOut is: " + IsSittingOut);

                    if (Convert.ToBoolean(e.wp) && !IsSittingOut)
                    {
                        Log.Write("Sitting out now");

                        // We're sitting out now, we didn't before
                        IsSittingOut = true;

                        sittingOut();
                    }
                    else if (IsSittingOut && !Convert.ToBoolean(e.wp))
                    {
                        Log.Write("No longer sitting out");

                        // We're not sitting out any longer
                        IsSittingOut = false;
                    }
                }
                break;
            }
        }
        /// <summary>
        /// Fires when a SHOWWINDOW message is received from the table
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void wh_OnMessageHook(object sender, MessageHookEventArgs e)
        {
            switch (e.msg)
            {
                // A window has been hidden / visible
                case StandardMessages.WM_SHOWWINDOW:
                    string txt = Win32.GetText((int)e.hwnd).ToLower();

                    if (txt.Length == 0)
                        return;

                    Log.Write("WinHooker: WM_SHOWWINDOW - '" + txt + "', visibility: " + e.wp);

                    ChildWindow child = new ChildWindow((int)e.hwnd);

                    if ((txt.StartsWith("raise") || txt.StartsWith("bet") || txt.StartsWith("all") || txt.StartsWith("fold") || txt.StartsWith("wait") || txt.StartsWith("call") || txt.StartsWith("check") || txt.StartsWith("post") || txt.StartsWith("sit out")) && !txt.Contains("respond"))
                    {
                        Log.Write("Window is action text");
                        if (child.SizeRatio < 4)
                        {
                            Log.Write("Window has correct size ratio, wp is: " + e.wp + ", needsAction is: " + needsAction);
                            if (Convert.ToBoolean(e.wp) && !needsAction)
                            {
                                Log.Write("Needs action now");

                                // Update children
                                UpdateChildren();

                                // We need action now, we didn't before
                                needsAction = true;

                                // If it's a tourney, check the blind level
                                if (GameForm == TableFactory.GameForm.SNG)
                                {
                                    // Get blind level
                                    int newBlindLevel = getBlindLevel();

                                    // Save the blind level and destroy the border form
                                    if (blindLevel != newBlindLevel)
                                    {
                                        if (borderForm != null && !borderForm.Visible)
                                        {
                                            borderForm.Dispose();
                                            borderForm = null;
                                        }

                                        blindLevel = newBlindLevel;
                                    }
                                }

                                // Fire event
                                requiresAction();

                                // Start timer
                                watch.Reset();
                                watch.Start();

                                // Update last action date
                                lastRequiredAction = DateTime.Now;
                            }
                            else if (needsAction && !Convert.ToBoolean(e.wp))
                            {
                                Log.Write("No longer needs action");

                                // We don't need action any more
                                needsAction = false;

                                // Fire event
                                noLongerRequiresAction();

                                // Stop timer
                                watch.Stop();
                                cumulativeResponseTime += watch.ElapsedMilliseconds;
                                actionCount++;

                                // Update last action date
                                lastRequiredAction = DateTime.Now;
                            }

                            actionButtonsVisible = Convert.ToBoolean(e.wp);

                            // Check if it's wait for bb button
                            if (txt == "wait for bb" && Settings.AutoWaitForBB && Convert.ToBoolean(e.wp))
                            {
                                Log.Write("Wait for BB detected, autowait enabled, clicking button");

                                Win32.ClickButton((int)e.hwnd);

                                if (Settings.AutoClickAutoPostBlind)
                                {
                                    Log.Write("We've clicked wait for bb button, now click auto post blind");

                                    CheckAutoPostBlind();
                                }

                                return;
                            }

                            // Check if it's post sb/bb button
                            if ((txt.StartsWith("post bb") || txt.StartsWith("post sb")) && Settings.AutoPostBlind && Convert.ToBoolean(e.wp))
                            {
                                Log.Write("Post sb/bb detected");

                                if (!Settings.AutoWaitForBB)
                                {
                                    Log.Write("We're not waiting for bb, clicking post button");

                                    Win32.ClickButton((int)e.hwnd);

                                    if (Settings.AutoClickAutoPostBlind)
                                    {
                                        Log.Write("We've posted a blind, and we're auto clicking auto post blind");

                                        CheckAutoPostBlind();
                                    }
                                }
                                else
                                {
                                    Log.Write("We're waiting for bb, launching delayed click of wait for sb button");

                                    System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();

                                    t.Interval = 80;
                                    t.Tag = e.hwnd.ToString();

                                    t.Tick += new EventHandler(delegate(object tSender, EventArgs eArgs)
                                    {
                                        int hwnd = Convert.ToInt32(((System.Windows.Forms.Timer)tSender).Tag);

                                        Log.Write("Delayed post blind timer tick");

                                        if (Win32.IsWindowVisible(hwnd))
                                            if (Win32.GetText(hwnd).ToLower().StartsWith("post "))
                                            {
                                                Log.Write("Post blind button still available, clicking");

                                                Win32.ClickButton(hwnd);

                                                if (Settings.AutoClickAutoPostBlind)
                                                {
                                                    Log.Write("We've posted a blind, and we're auto clicking auto post blind");

                                                    CheckAutoPostBlind();
                                                }
                                            }

                                        t.Enabled = false;

                                    });

                                    t.Enabled = true;
                                }
                            }
                        }
                    }
                    else if (txt.StartsWith("i am back") && child.SizeRatio < 4)
                    {
                        Log.Write("Window is sitting out text, wp is: " + e.wp + ", IsSittingOut is: " + IsSittingOut);

                        if (Convert.ToBoolean(e.wp) && !IsSittingOut)
                        {
                            Log.Write("Sitting out now");

                            // We're sitting out now, we didn't before
                            IsSittingOut = true;

                            sittingOut();
                        }
                        else if (IsSittingOut && !Convert.ToBoolean(e.wp))
                        {
                            Log.Write("No longer sitting out");

                            // We're not sitting out any longer
                            IsSittingOut = false;
                        }
                    }
                    break;
            }
        }
        /// <summary>
        /// The callback function which saves a child window in case it's relevant
        /// </summary>
        /// <param name="hwnd"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        protected override bool EnumChildWindowCallBack(int hwnd, int lParam)
        {
            if (children.ContainsKey(hwnd))
                return true;

            StringBuilder sbc = new StringBuilder(256);

            Win32.GetClassName(hwnd, sbc, sbc.Capacity);

            string cls = sbc.ToString();

            // Only save this child if it's relevant, otherwise ban the window
            if(cls != "ComboBox" && cls != "RICHEDIT")
            {
                StringBuilder sb = new StringBuilder(256);
                Win32.GetWindowText(hwnd, sb, sb.Capacity);

                ChildWindow child = new ChildWindow(hwnd, cls);

                string txt = sb.ToString();

                if(child.IsVisible && !(cls == "static" && txt == ""))
                    children.Add(hwnd, child);
            }

            return true;
        }
        /// <summary>
        /// The callback function which saves a child window in case it's relevant
        /// </summary>
        /// <param name="hwnd"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        protected bool EnumChildWindowCallBack(int hwnd, int lParam)
        {
            StringBuilder sbc = new StringBuilder(256);

            Win32.GetClassName(hwnd, sbc, sbc.Capacity);

            string cls = sbc.ToString();

            // Only save this child if it's relevant
            if(cls == "Button")
            {
                StringBuilder sb = new StringBuilder(256);

                Win32.GetWindowText(hwnd, sb, sb.Capacity);

                ChildWindow child = new ChildWindow(hwnd, cls);

                string txt = sb.ToString();

                if(!children.ContainsKey(hwnd) && child.IsVisible)
                    children.Add(hwnd, child);
            }

            return true;
        }
        /// <summary>
        /// The callback function which saves a child window in case it's relevant
        /// </summary>
        /// <param name="hwnd"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        protected override bool EnumChildWindowCallBack(int hwnd, int lParam)
        {
            if (children.ContainsKey(hwnd))
                return true;

            StringBuilder sbc = new StringBuilder(256);

            Win32.GetClassName(hwnd, sbc, sbc.Capacity);

            string cls = sbc.ToString();

            // Only save this child if it's relevant, otherwise ban the window
            if (cls.ToLower().Trim() == "edit")
            {
                ChildWindow child = new ChildWindow(hwnd, cls);

                // Only save bet box
                if(child.SizeRatio > 2.2 && child.SizeRatio < 3.6)
                    children.Add(hwnd, child);
            }

            return true;
        }
        /// <summary>
        /// Fires when a SHOWWINDOW message is received from the table
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void wh_OnMessageHook(object sender, MessageHookEventArgs e)
        {
            switch (e.msg)
            {
                // A window has been hidden / visible
                case StandardMessages.WM_SHOWWINDOW:
                    int buttonCode = Win32.GetControlIDFromHwnd((int)e.hwnd);

                    Log.Write("WinHooker: WM_SHOWWINDOW - '" + buttonCode + "', visibility: " + e.wp);

                    ChildWindow child = new ChildWindow((int)e.hwnd);

                    if (buttonCode == 1031 || buttonCode == 1032 || buttonCode == 1033)
                    {
                        Log.Write("Window has correct size ratio, wp is: " + e.wp + ", needsAction is: " + needsAction);
                        if (Convert.ToBoolean(e.wp) && !needsAction)
                        {
                            Log.Write("Needs action now");

                            // Update children
                            UpdateChildren();

                            // We need action now, we didn't before
                            needsAction = true;

                            // Fire event
                            requiresAction();

                            // Start timer
                            watch.Reset();
                            watch.Start();

                            // Update last action date
                            lastRequiredAction = DateTime.Now;
                        }
                        else if (needsAction && !Convert.ToBoolean(e.wp))
                        {
                            Log.Write("No longer needs action");

                            // We don't need action any more
                            needsAction = false;

                            // Fire event
                            noLongerRequiresAction();

                            // Stop timer
                            watch.Stop();
                            cumulativeResponseTime += watch.ElapsedMilliseconds;
                            actionCount++;

                            // Update last action date
                            lastRequiredAction = DateTime.Now;
                        }

                        actionButtonsVisible = Convert.ToBoolean(e.wp);
                    }
                    else if (buttonCode == 1035) // "DEAL ME IN"
                    {
                        Log.Write("Window is sitting out text, wp is: " + e.wp + ", IsSittingOut is: " + IsSittingOut);

                        if (Convert.ToBoolean(e.wp) && !IsSittingOut)
                        {
                            Log.Write("Sitting out now");

                            // We're sitting out now, we didn't before
                            IsSittingOut = true;

                            sittingOut();
                        }
                        else if (IsSittingOut && !Convert.ToBoolean(e.wp))
                        {
                            Log.Write("No longer sitting out");

                            // We're not sitting out any longer
                            IsSittingOut = false;
                        }
                    }
                    break;
            }
        }
        /// <summary>
        /// The callback function which saves a child window in case it's relevant
        /// </summary>
        /// <param name="hwnd"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        protected override bool EnumChildWindowCallBack(int hwnd, int lParam)
        {
            if (children.ContainsKey(hwnd))
                return true;

            StringBuilder sbc = new StringBuilder(256);

            Win32.GetClassName(hwnd, sbc, sbc.Capacity);

            string cls = sbc.ToString();

            // Only save this child if it's relevant, otherwise ban the window
            if (cls == "FTCButton")
            {
                ChildWindow child = new ChildWindow(hwnd, cls);

                if (child.IsVisible)
                    children.Add(hwnd, child);
            }

            return true;
        }
        /// <summary>
        /// Fires when a SHOWWINDOW message is received from the table
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void wh_OnMessageHook(object sender, MessageHookEventArgs e)
        {
            switch (e.msg)
            {
            // A window has been hidden / visible
            case StandardMessages.WM_SHOWWINDOW:
                int buttonCode = Win32.GetControlIDFromHwnd((int)e.hwnd);

                Log.Write("WinHooker: WM_SHOWWINDOW - '" + buttonCode + "', visibility: " + e.wp);

                ChildWindow child = new ChildWindow((int)e.hwnd);

                if (buttonCode == 1031 || buttonCode == 1032 || buttonCode == 1033)
                {
                    Log.Write("Window has correct size ratio, wp is: " + e.wp + ", needsAction is: " + needsAction);
                    if (Convert.ToBoolean(e.wp) && !needsAction)
                    {
                        Log.Write("Needs action now");

                        // Update children
                        UpdateChildren();

                        // We need action now, we didn't before
                        needsAction = true;

                        // Fire event
                        requiresAction();

                        // Start timer
                        watch.Reset();
                        watch.Start();

                        // Update last action date
                        lastRequiredAction = DateTime.Now;
                    }
                    else if (needsAction && !Convert.ToBoolean(e.wp))
                    {
                        Log.Write("No longer needs action");

                        // We don't need action any more
                        needsAction = false;

                        // Fire event
                        noLongerRequiresAction();

                        // Stop timer
                        watch.Stop();
                        cumulativeResponseTime += watch.ElapsedMilliseconds;
                        actionCount++;

                        // Update last action date
                        lastRequiredAction = DateTime.Now;
                    }

                    actionButtonsVisible = Convert.ToBoolean(e.wp);
                }
                else if (buttonCode == 1035)                         // "DEAL ME IN"
                {
                    Log.Write("Window is sitting out text, wp is: " + e.wp + ", IsSittingOut is: " + IsSittingOut);

                    if (Convert.ToBoolean(e.wp) && !IsSittingOut)
                    {
                        Log.Write("Sitting out now");

                        // We're sitting out now, we didn't before
                        IsSittingOut = true;

                        sittingOut();
                    }
                    else if (IsSittingOut && !Convert.ToBoolean(e.wp))
                    {
                        Log.Write("No longer sitting out");

                        // We're not sitting out any longer
                        IsSittingOut = false;
                    }
                }
                break;
            }
        }