private static async Task Main()
        {
            try
            {
                Traverse.Client = await Connection_Initialization("MohammadReza");
                await Traverse_Mazes();

                Console.ReadLine();
            }
            catch (Exception e)
            {
                ConsoleLogging.ExceptionHandler(e, $"Unknown Upper Level Case");
            }
        }
 private static async Task <PossibleActionsAndCurrentScore> BackTrack(Stack <Direction> stack)
 {
     try
     {
         Direction = stack.Pop();
         var possibleMovements = CurrentTile.PossibleMoveActions.Select(x => x.Direction).ToList();
         if (possibleMovements.Contains(Direction))
         {
             return(await Client.Move(Direction));
         }
         return(await Client.Move(possibleMovements[0]));
     }
     catch (Exception e)
     {
         ConsoleLogging.ExceptionHandler(e, $"Poping from backtracking {stack.GetType().Name} stacks");
         throw;
     }
 }
        private static async Task <bool> Try_Exit_Maze(PossibleActionsAndCurrentScore tile, MazeInfo maze)
        {
            try
            {
                if (tile.CurrentScoreInBag != maze.PotentialReward || !tile.CanExitMazeHere)
                {
                    return(false);
                }
                Console.WriteLine($"Maze Exit: {maze.Name} with {tile.CurrentScoreInBag} score in bag");
                await Client.ExitMaze();

                return(true);
            }
            catch (Exception e)
            {
                ConsoleLogging.ExceptionHandler(e, $"Trying to Exit Maze \"{maze.Name}\"");
                return(false);
            }
        }
        private static async Task <PossibleActionsAndCurrentScore> Try_Collect_Score()
        {
            try
            {
                if (!CurrentTile.CanCollectScoreHere || CurrentTile.CurrentScoreInHand <= 0)
                {
                    return(CurrentTile);
                }
                Console.WriteLine($"Score Collection: {CurrentTile.CurrentScoreInHand} has been moved to your bag");
                CurrentTile = await Client.CollectScore();

                return(CurrentTile);
            }
            catch (Exception e)
            {
                ConsoleLogging.ExceptionHandler(e, "Trying to Collect score");
                return(CurrentTile);
            }
        }
        public static async Task Traverse_Mazes()
        {
            var mazesList = (await _client.AllMazes()).OrderBy(x => x.TotalTiles).ToList();

            foreach (var maze in mazesList)
            {
                try
                {
                    ConsoleLogging.Mazes_Info(mazesList);
                    await Traverse.Start(maze);
                }
                catch (Exception e)
                {
                    ConsoleLogging.ExceptionHandler(e, $"Traversing Maze \"{maze.Name}\"");
                }
            }

            Console.WriteLine("You have finished all the Mazes:\n");
            ConsoleLogging.Client_Info(await ClientInfo());
        }
        public static async Task <AmazeingClient> Connection_Initialization(string playerName, string token = null)
        {
            try
            {
                var httpClient        = new HttpClient();
                var authorization_Key = token ?? "HTI Thanks You [e48a]";

                httpClient.DefaultRequestHeaders.Add("Authorization", authorization_Key);
                _client = new AmazeingClient("https://maze.hightechict.nl/", httpClient);

                await _client.ForgetPlayer();

                await _client.RegisterPlayer(name : playerName);

                Console.WriteLine("About to register client...");
                ConsoleLogging.Client_Info(await ClientInfo());
                return(_client);
            }
            catch (Exception e)
            {
                ConsoleLogging.ExceptionHandler(e, $"Connection Initialization Phase");
                return(null);
            }
        }
        public static async Task Start(MazeInfo maze)
        {
            Console.WriteLine($"Enter to maze: {maze.Name} with {maze.TotalTiles} tiles and {maze.PotentialReward} potential rewards.");
            _backtrackStacks = new Dictionary <string, Stack <Direction> >
            {
                { "Collection", new Stack <Direction>() },
                { "Exit", new Stack <Direction>() },
                { "Pass", new Stack <Direction>() }
            };

            CurrentTile = await Client.EnterMaze(maze.Name);

            do
            {
                try
                {
                    var  scoreInBag = CurrentTile.CurrentScoreInBag;
                    var  scoreInHand = CurrentTile.CurrentScoreInHand;
                    var  allPointsPicked = maze.PotentialReward == scoreInBag + scoreInHand;
                    bool collectionBackTrack = false, passedBackTrack = false, exitBackTrack = false;

                    CurrentTile = await Scan_For_Collection_And_Exit_Spots(CurrentTile);

                    if (await Try_Exit_Maze(CurrentTile, maze))
                    {
                        return;
                    }

                    if (!allPointsPicked)
                    {
                        var possibleReward = CurrentTile.PossibleMoveActions
                                             .Where(di => di.RewardOnDestination != 0 || !di.HasBeenVisited)
                                             .OrderBy(di => di.RewardOnDestination != 0)
                                             .Select(di => di.Direction).ToList();

                        if (possibleReward.Count != 0)
                        {
                            Direction   = possibleReward[0];
                            CurrentTile = await Client.Move(Direction);
                        }
                        else
                        {
                            CurrentTile = await BackTrack(_backtrackStacks["Pass"]);

                            passedBackTrack = true;
                        }
                    }
                    else
                    {
                        if (scoreInHand != 0)
                        {
                            // Go Collection Points: Scores needs to be transferred to Bag
                            if (_backtrackStacks["Collection"] != null && _backtrackStacks["Collection"].Count != 0)
                            {
                                collectionBackTrack = true;
                                CurrentTile         = await BackTrack(_backtrackStacks["Collection"]);
                            }
                        }
                        else
                        {
                            // Go Exit: All Scored already moved to Bag
                            if (_backtrackStacks["Exit"] != null && _backtrackStacks["Exit"].Count != 0)
                            {
                                exitBackTrack = true;
                                CurrentTile   = await BackTrack(_backtrackStacks["Exit"]);
                            }
                            else if (_backtrackStacks["Pass"] != null && _backtrackStacks["Pass"].Count != 0)
                            {
                                passedBackTrack = true;
                                CurrentTile     = await BackTrack(_backtrackStacks["Pass"]);
                            }
                        }
                    }
                    ConsoleLogging.CurrentTile_Info(CurrentTile, maze, Direction);

                    //Updating Stacks with taken movement
                    if (CurrentTile.CanExitMazeHere)
                    {
                        _backtrackStacks["Exit"].Clear();
                    }
                    if (CurrentTile.CanCollectScoreHere)
                    {
                        _backtrackStacks["Collection"].Clear();
                    }
                    if (collectionBackTrack == false)
                    {
                        _backtrackStacks["Collection"]?.Push(ReverseDirection(Direction));
                    }
                    if (exitBackTrack == false)
                    {
                        _backtrackStacks["Exit"]?.Push(ReverseDirection(Direction));
                    }
                    if (passedBackTrack == false)
                    {
                        _backtrackStacks["Pass"].Push(ReverseDirection(Direction));
                    }
                }
                catch (Exception e)
                {
                    ConsoleLogging.ExceptionHandler(e, "Trying to Make a move");
                    CurrentTile = await BackTrack(_backtrackStacks["Pass"]);
                }
            } while (true);
        }