/// <summary>
        /// Iterative breadth first algorithm
        /// </summary>
        /// <param name="row">Row to start at</param>
        /// <param name="column">Column to start at</param>
        /// <returns>True - if path is found, false - if path is not found.</returns>
        private BreadthFirstResult ExecuteInternal(int row, int column)
        {
            var result = new BreadthFirstResult();

            if (row == 0 || row == _labyrinthHeight - 1 || column == 0 || column == _labyrinthWidth - 1)
            {
                result.IsSuccess = true;
                GetTrace(row, column, result);
                return(result);
            }

            var newRow    = 0;
            var newColumn = 0;

            while (_close <= _new)
            {
                row    = _fRow[_close];
                column = _fColumn[_close];

                //Loop over production rules
                for (int i = 0; i < 4; i++)
                {
                    //Calculate new coordinates
                    newRow    = row + _cRow[i];
                    newColumn = column + _cColumn[i];

                    //if cell is free
                    if (_operationalLabyrinth[newRow, newColumn] == 0)
                    {
                        _operationalLabyrinth[newRow, newColumn] = _operationalLabyrinth[row, column] + 1;
                        if (newRow == 0 || newRow == _labyrinthHeight - 1 || newColumn == 0 || newColumn == _labyrinthWidth - 1)
                        {
                            GetTrace(newRow, newColumn, result);
                            result.IsSuccess = true;
                            return(result);
                        }

                        _new++;
                        _fRow[_new]    = newRow;
                        _fColumn[_new] = newColumn;
                    }
                }

                _close++;
            }

            return(result);
        }
        private void GetTrace(int endRow, int endColumn, BreadthFirstResult result)
        {
            var newRow    = 0;
            var newColumn = 0;

            var endRowCopy    = endRow;
            var endColumnCopy = endColumn;
            var labCopy       = (int[, ])_labyrinth.Clone();

            var endRowNotChanged    = endRow;
            var endColumnNotChanged = endColumn;

            _labyrinth[endRow, endColumn] = _operationalLabyrinth[endRow, endColumn];

            var path = new List <KeyValuePair <int, int> >();

            path.Add(new KeyValuePair <int, int>(endRow, endColumn));

            //Collect path
            do
            {
                for (int k = 3; k >= 0; k--)
                {
                    newRow    = endRow + _cRow[k];
                    newColumn = endColumn + _cColumn[k];

                    //if in labyrinth
                    if (newRow > 0 && newRow < _labyrinthHeight - 1 && newColumn > 0 && newColumn < _labyrinthWidth - 1)
                    {
                        //if previous number
                        if (_operationalLabyrinth[newRow, newColumn] == _operationalLabyrinth[endRow, endColumn] - 1)
                        {
                            //previous step found
                            _labyrinth[newRow, newColumn] = _operationalLabyrinth[newRow, newColumn];
                            endRow    = newRow;
                            endColumn = newColumn;
                            path.Add(new KeyValuePair <int, int>(endRow, endColumn));
                        }
                    }
                }
            } while (_labyrinth[endRow, endColumn] != 2);

            //Reverse path, first element = start element
            path.Reverse();

            result.Path = path;

            var newN  = 0;
            var close = 0;

            newColumn = 0;
            newRow    = 0;

            var processNextIteration     = new List <KeyValuePair <int, int> >();
            var processNextIterationCopy = new List <KeyValuePair <int, int> >();

            //Collect trace
            for (int i = 0; i < path.Count; i++)
            {
                processNextIteration = new List <KeyValuePair <int, int> >(processNextIterationCopy);
                processNextIterationCopy.Clear();
                _loggerService.Write($"Wave {i}, label L=\"{_operationalLabyrinth[path[i].Key, path[i].Value]}\"");

                if (i == 0)
                {
                    _loggerService.Write($". Initial position: X={path[i].Value + 1}, Y={path[i].Key + 1}, NEWN={newN + 1}");
                    processNextIterationCopy.Add(new KeyValuePair <int, int>(path[i].Key, path[i].Value));
                    _loggerService.WriteLine("");
                    continue;
                }

                _loggerService.WriteLine("");

                for (int j = 0; j < processNextIteration.Count; j++)
                {
                    _loggerService.WriteLine($"     Close CLOSE={close + 1}, X={processNextIteration[j].Value + 1}, Y={processNextIteration[j].Key + 1}.");
                    close++;

                    for (int k = 0; k < 4; k++)
                    {
                        newRow    = processNextIteration[j].Key + _cRow[k];
                        newColumn = processNextIteration[j].Value + _cColumn[k];

                        _loggerService.Write($"         R{k + 1}. X={newColumn + 1}, Y={newRow + 1}.");

                        //if in labyrinth
                        if ((newRow > 0 && newRow < _labyrinthHeight - 1 && newColumn > 0 && newColumn < _labyrinthWidth - 1) ||
                            (newRow == endRowNotChanged && newColumn == endColumnNotChanged))
                        {
                            //if terminal.
                            if (newRow == endRowNotChanged && newColumn == endColumnNotChanged)
                            {
                                endRowCopy    = newRow;
                                endColumnCopy = newColumn;
                                newN++;
                                _loggerService.Write($" Free. NEWN={newN + 1}. Terminal.");
                                processNextIterationCopy.Add(new KeyValuePair <int, int>(newRow, newColumn));
                                _loggerService.WriteLine("");
                                goto terminalCheckpoint;
                            }
                            //if next number
                            else if (_operationalLabyrinth[newRow, newColumn] + 1 == _operationalLabyrinth[endRowCopy, endColumnCopy])
                            {
                                endRowCopy    = newRow;
                                endColumnCopy = newColumn;
                                newN++;
                                _loggerService.Write($" Free. NEWN={newN + 1}");
                                processNextIterationCopy.Add(new KeyValuePair <int, int>(newRow, newColumn));
                            }
                            //if free
                            else if (labCopy[newRow, newColumn] == 0)
                            {
                                if (_fRow[newN + 1] == newRow && _fColumn[newN + 1] == newColumn)
                                {
                                    newN++;
                                    _loggerService.Write($" Free. NEWN={newN + 1}");
                                    processNextIterationCopy.Add(new KeyValuePair <int, int>(newRow, newColumn));
                                }
                                else
                                {
                                    _loggerService.Write($" CLOSED OR OPEN.");
                                }
                            }
                            //if wall
                            else if (labCopy[newRow, newColumn] == 1)
                            {
                                _loggerService.Write($" Wall.");
                            }
                        }
                        else
                        {
                            _loggerService.Write($" Wall.");
                        }

                        _loggerService.WriteLine("");
                    }
                }
            }

terminalCheckpoint:

            //Compute rules
            var rules = new List <string>();

            for (int i = 0; i < path.Count; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    if (i != path.Count - 1 && path[i + 1].Value == path[i].Value + _cColumn[j] && path[i + 1].Key == path[i].Key + _cRow[j])
                    {
                        rules.Add($"R{j + 1}");
                    }
                }
            }

            result.Rules = rules;
        }