//private void anon(object target)
        //{
        //    Dictionary<string, int> handTypeCount = new Dictionary<string, int>() { { "High Card", 0 }, { "Pair", 0 }, { "Two Pair", 0 }, { "Three of a Kind", 0 }, { "Straight", 0 }, { "Flush", 0 }, { "Full House", 0 }, { "Four of a Kind", 0 }, { "Straight Flush", 0 }, { "Royal Flush", 0 } };

        //    Tuple<List<int>, List<int>, int[], Hashtable> param = (Tuple<List<int>, List<int>, int[], Hashtable>)target;

        //    foreach (string hand in CardUtilities.enumeratePossibleHands(param.Item1,param.Item2,param.Item3))
        //        {
        //            handTypeCount[hand]++;
        //        }
        //    lock (param.Item4)
        //    {
        //        param.Item4.Add(param.Item3, handTypeCount);
        //    }
        //}

        private void anon(object target)
        {
            Dictionary <string, int> handTypeCount;
            Tuple <List <int>, List <int>, int[], Hashtable> param;

            //Loop until the concurrent stack has been removed
            while (workerThreadQueue != null)
            {
                //try to pop from the stack
                if (workerThreadQueue.TryDequeue(out param))
                {
                    handTypeCount = new Dictionary <string, int>()
                    {
                        { "High Card", 0 }, { "Pair", 0 }, { "Jacks or Better", 0 }, { "Two Pair", 0 }, { "Three of a Kind", 0 }, { "Straight", 0 }, { "Flush", 0 }, { "Full House", 0 }, { "Four of a Kind", 0 }, { "Straight Flush", 0 }, { "Royal Flush", 0 }
                    };

                    if (param == null)
                    {
                        break;
                    }

                    //if you suceed in poping then calculate all the hand details
                    foreach (string hand in CardUtilities.enumeratePossibleHands(param.Item1, param.Item2, param.Item3))
                    {
                        handTypeCount[hand]++;
                    }
                    lock (param.Item4)
                    {
                        param.Item4.Add(param.Item3, handTypeCount);
                    }
                }
            }
        }
        /// <summary>
        /// Calculates all the odds for the current state. If you leave chosenMask as null the optimal strategy will be calculated and used
        /// </summary>
        /// <param name="chosenMask"></param>
        private void calculateAndDisplayProbabilities(int[] chosenMask = null)
        {
            //http://www.durangobill.com/VideoPoker.html

            //calculate the value of the hand ONCE so that we don't have to redo it for each comparison;
            string currentHandType = CardUtilities.getHandName(handCards);

            //Go through (and count the types of) every set of drawable cards, given the current discard values

            DateTime start = DateTime.Now;

            List <int> sortedDeckClone = CardUtilities.createSortedCloneOfDeck(deckContent);
            Hashtable  hashedResults   = new Hashtable();

            Thread[] workers = new Thread[4];

            if (chosenMask == null)
            {
                workerThreadQueue = new ConcurrentQueue <Tuple <List <int>, List <int>, int[], Hashtable> >();

                workers[0] = new Thread(new ParameterizedThreadStart(anon));
                workers[1] = new Thread(new ParameterizedThreadStart(anon));
                workers[2] = new Thread(new ParameterizedThreadStart(anon));
                workers[3] = new Thread(new ParameterizedThreadStart(anon));

                foreach (var maskQuad in CardUtilities.enumerateHandMasks_ThreadVersion())
                {
                    try
                    {
                        workerThreadQueue.Enqueue(new Tuple <List <int>, List <int>, int[], Hashtable>(handCards, sortedDeckClone, maskQuad.Item1, hashedResults));
                        workerThreadQueue.Enqueue(new Tuple <List <int>, List <int>, int[], Hashtable>(handCards, sortedDeckClone, maskQuad.Item2, hashedResults));
                        workerThreadQueue.Enqueue(new Tuple <List <int>, List <int>, int[], Hashtable>(handCards, sortedDeckClone, maskQuad.Item3, hashedResults));
                        workerThreadQueue.Enqueue(new Tuple <List <int>, List <int>, int[], Hashtable>(handCards, sortedDeckClone, maskQuad.Item4, hashedResults));

                        if (workers[0].ThreadState == ThreadState.Unstarted)
                        {                                                            //hand,    deck  , mask, Storage_hashTable
                            workers[0].Start(new Tuple <List <int>, List <int>, int[], Hashtable>(handCards, sortedDeckClone, maskQuad.Item1, hashedResults));
                            workers[1].Start(new Tuple <List <int>, List <int>, int[], Hashtable>(handCards, sortedDeckClone, maskQuad.Item2, hashedResults));
                            workers[2].Start(new Tuple <List <int>, List <int>, int[], Hashtable>(handCards, sortedDeckClone, maskQuad.Item3, hashedResults));
                            workers[3].Start(new Tuple <List <int>, List <int>, int[], Hashtable>(handCards, sortedDeckClone, maskQuad.Item4, hashedResults));
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                    }
                }

                workerThreadQueue.Enqueue(null);
                workerThreadQueue.Enqueue(null);
                workerThreadQueue.Enqueue(null);
                workerThreadQueue.Enqueue(null);

                workers[0].Join();
                workers[1].Join();
                workers[2].Join();
                workers[3].Join();
                Console.WriteLine(DateTime.Now.Subtract(start).ToString());

                if (workerThreadQueue.Count != 0)
                {
                    throw new Exception();
                }
                else
                {
                    workerThreadQueue = null;
                }
            }
            else //This else occurs when the user wants to know about a SPECIFIC mask, not neccessarily the optimal one
            {
                //Do the chosen mask of the user
                Dictionary <string, int> handTypeCount = new Dictionary <string, int>()
                {
                    { "High Card", 0 }, { "Pair", 0 }, { "Jacks or Better", 0 }, { "Two Pair", 0 }, { "Three of a Kind", 0 }, { "Straight", 0 }, { "Flush", 0 }, { "Full House", 0 }, { "Four of a Kind", 0 }, { "Straight Flush", 0 }, { "Royal Flush", 0 }
                };

                foreach (string hand in CardUtilities.enumeratePossibleHands(handCards, sortedDeckClone, chosenMask))
                {
                    handTypeCount[hand]++;
                }

                hashedResults.Add(chosenMask, handTypeCount);

                //Compute the draw all mask, that we use for opponent draw odds
                if (!(chosenMask[0] == 0 && chosenMask[0] == chosenMask[1] && chosenMask[1] == chosenMask[2] && chosenMask[2] == chosenMask[3] && chosenMask[3] == chosenMask[4]))
                {
                    handTypeCount = new Dictionary <string, int>()
                    {
                        { "High Card", 0 }, { "Pair", 0 }, { "Jacks or Better", 0 }, { "Two Pair", 0 }, { "Three of a Kind", 0 }, { "Straight", 0 }, { "Flush", 0 }, { "Full House", 0 }, { "Four of a Kind", 0 }, { "Straight Flush", 0 }, { "Royal Flush", 0 }
                    };

                    int[] drawAll = new int[] { 0, 0, 0, 0, 0 };
                    foreach (string hand in CardUtilities.enumeratePossibleHands(handCards, sortedDeckClone, drawAll))
                    {
                        handTypeCount[hand]++;
                    }

                    hashedResults.Add(drawAll, handTypeCount);
                }
            }

            //By this stage we have the raw count data.
            //Next thing is to use that data to find optimal strageies and caluclate the odds

            List <int[]> bestMasks = new List <int[]>()
            {
                new int[] { 1, 1, 1, 1, 1 }
            };

            int[] factorials = { 1, 2, 6, 24, 120 };

            double highestExpected = 0;

            ///Keeps track of how many tied hand masks there are
            int tiedMasks = 0;


            foreach (var singleResult in hashedResults)
            {
                double runningTotal = 0;
                double top          = sortedDeckClone.Count;
                int    draws        = 5 - ((int[])((DictionaryEntry)singleResult).Key).Sum();

                for (int i = 1; i < draws; i++)
                {
                    top = top * (sortedDeckClone.Count - i);
                }

                if (draws == 0)
                {
                    if (highestExpected < payoffTable[currentHandType])
                    {
                        highestExpected = payoffTable[currentHandType];
                        bestMasks       = new List <int[]>()
                        {
                            (int[])((DictionaryEntry)singleResult).Key
                        };                                                                         //= (int[])((DictionaryEntry)singleResult).Key;
                    }
                    continue;
                }

                foreach (var pair in ((Dictionary <string, int>)((DictionaryEntry)singleResult).Value))
                {
                    runningTotal += (payoffTable[pair.Key] * pair.Value);
                }



                if (highestExpected == runningTotal / (top / factorials[draws - 1]))
                {
                    tiedMasks++;
                    bestMasks.Add((int[])((DictionaryEntry)singleResult).Key);
                }

                if (draws > 0 && highestExpected < runningTotal / (top / factorials[draws - 1]))
                {
                    tiedMasks       = 0;
                    highestExpected = runningTotal / (top / factorials[draws - 1]);
                    bestMasks       = new List <int[]>()
                    {
                        (int[])((DictionaryEntry)singleResult).Key
                    };
                }
            }

            //Once here, we have an optimal strategy selected (or the users selected mask)

            double weaker = 0, tied = -1, better = 0;

            int[] drawAllMask = null;
            //We need to find the reference to the actual list on the hashtable ([0,0,0,0,0])
            foreach (int[] key in hashedResults.Keys)
            {
                if (key[0] == 0 && key[0] == key[1] && key[1] == key[2] && key[2] == key[3] && key[3] == key[4])
                {
                    drawAllMask = key;
                    break;
                }
            }

            foreach (var type in (Dictionary <string, int>)hashedResults[drawAllMask])
            {
                //are we still adding values to weaker and tied?
                if (tied == -1)
                {
                    if (type.Key == currentHandType)
                    {
                        tied = type.Value;
                    }
                    else
                    {
                        weaker += type.Value;
                    }
                    continue;
                }

                //Getting here means that tied is greater than -1 (so we must be adding to better from here on)
                better += type.Value;
            }

            Console.WriteLine("Opponents have a %{0:0.000} of starting with a BETTER hand than what you have", (better / (tied + weaker)) * 100);

            ///Alter this to find the highest held card various masks and display that
            foreach (var mask in bestMasks)
            {
                foreach (var elem in mask)
                {
                    Console.Write(elem);
                }
                Console.WriteLine();
            }


            btn_Card1Holding.Content = bestMasks[0][0] == 1 ? "Hold" : "Draw";
            btn_Card2Holding.Content = bestMasks[0][1] == 1 ? "Hold" : "Draw";
            btn_Card3Holding.Content = bestMasks[0][2] == 1 ? "Hold" : "Draw";
            btn_Card4Holding.Content = bestMasks[0][3] == 1 ? "Hold" : "Draw";
            btn_Card5Holding.Content = bestMasks[0][4] == 1 ? "Hold" : "Draw";

            Console.WriteLine("Optimal return rate- " + highestExpected);
            Console.WriteLine("ties identical masks" + tiedMasks);

            Console.WriteLine(DateTime.Now.Subtract(start).ToString());

            int betterHands = 0;
            int tiedHands   = -1;
            int worseHands  = 0;

            foreach (var pair in (Dictionary <string, int>)hashedResults[bestMasks[0]])
            {
                if (pair.Key == currentHandType)
                {
                    tiedHands = pair.Value;
                    handTypeCountLabels[pair.Key].Foreground = new SolidColorBrush(Colors.Blue);
                    handTypeLabels[pair.Key].Foreground      = new SolidColorBrush(Colors.Blue);
                }
                else
                if (tiedHands == -1)
                {
                    worseHands += pair.Value;
                    handTypeCountLabels[pair.Key].Foreground = new SolidColorBrush(Colors.Red);
                    handTypeLabels[pair.Key].Foreground      = new SolidColorBrush(Colors.Red);
                }
                else
                {
                    betterHands += pair.Value;
                    handTypeCountLabels[pair.Key].Foreground = new SolidColorBrush(Colors.Green);
                    handTypeLabels[pair.Key].Foreground      = new SolidColorBrush(Colors.Green);
                }
            }

            double totalHands = betterHands + tiedHands + worseHands;

            foreach (var pair in (Dictionary <string, int>)hashedResults[bestMasks[0]])
            {
                //The flow direction property of labels causes weird positioning of special charachters: special symols seem to go to the opposite side you place them O_o when using "RightToLeft"
                if (totalHands == 0)
                {
                    if (pair.Key != currentHandType)
                    {
                        handTypeCountLabels[pair.Key].Content = "%0.00";
                    }
                    else
                    {
                        handTypeCountLabels[pair.Key].Content = "%100.00";
                    }
                }
                else
                {
                    double chance = (pair.Value / (totalHands) * 100);
                    if (chance != 0 && chance < 0.01)
                    {
                        handTypeCountLabels[pair.Key].Content = "%0.01>";
                    }
                    else
                    {
                        handTypeCountLabels[pair.Key].Content = string.Format("%{0:0.00}", (pair.Value / (totalHands) * 100));
                    }
                }
            }

            lbl_decrease.Content    = string.Format("{0:0.0%} chance of value decreasing", worseHands / totalHands);
            lbl_increase.Content    = string.Format("{0:0.0%} chance of value increasing", betterHands / totalHands);
            lbl_returnRate.Content  = string.Format("{0:0.0%} estimated return rate", highestExpected);
            lbl_betterStart.Content = string.Format("{0:0.0%} chance of better starting hand", (better / (tied + weaker)));
        }