private void SolveCrossTopLayer()
        {
            // Step 1: Get edges with the color of the top face
            IEnumerable <Cube> topEdges = Rubik.Cubes.Where(c => c.IsEdge).Where(c => c.Position.HasFlag(CubeFlag.TopLayer));

            // Step 2: Check if the cube is insoluble
            if (topEdges.Count(tE => tE.Faces.First(f => f.Position == FacePosition.Top).Color == Rubik.TopColor) % 2 != 0)
            {
                return;
            }

            var correctEdges             = topEdges.Where(c => c.Faces.First(f => f.Position == FacePosition.Top).Color == Rubik.TopColor);
            var solveTopCrossAlgorithmI  = new Algorithm("F R U R' U' F'");
            var solveTopCrossAlgorithmII = new Algorithm("F S R U R' U' F' S'");

            // Step 3: Solve the cross on the top layer
            if (Rubik.CountEdgesWithCorrectOrientation() == 0)
            {
                SolverAlgorithm(solveTopCrossAlgorithmI);
                correctEdges = topEdges.Where(c => c.Faces.First(f => f.Position == FacePosition.Top).Color == Rubik.TopColor);
            }

            if (Rubik.CountEdgesWithCorrectOrientation() == 2)
            {
                var firstCorrect  = correctEdges.First();
                var secondCorrect = correctEdges.First(f => f != firstCorrect);

                bool opposite = false;

                foreach (CubeFlag flag in firstCorrect.Position.GetFlags())
                {
                    CubeFlag pos = CubeFlagService.GetOppositeFlag(flag);

                    if (secondCorrect.Position.HasFlag(pos) && pos != CubeFlag.None)
                    {
                        opposite = true;
                        break;
                    }
                }

                if (opposite)
                {
                    while (correctEdges.Count(c => c.Position.HasFlag(CubeFlag.RightSlice)) != 1)
                    {
                        SolverMove(CubeFlag.TopLayer, true);
                    }

                    SolverAlgorithm(solveTopCrossAlgorithmI);
                }
                else
                {
                    while (correctEdges.Count(c => c.Position.HasFlag(CubeFlag.RightSlice) || c.Position.HasFlag(CubeFlag.FrontSlice)) != 2)
                    {
                        SolverMove(CubeFlag.TopLayer, true);
                    }

                    SolverAlgorithm(solveTopCrossAlgorithmII);
                }
            }

            // Step 4: Move the edges of the cross to their target positions
            while (topEdges.Count(c => c.Position.Flags == GetTargetFlags(c)) < 4)
            {
                IEnumerable <Cube> correctEdges2 = topEdges.Where(c => c.Position.Flags == GetTargetFlags(c));
                while (correctEdges2.Count() < 2)
                {
                    SolverMove(CubeFlag.TopLayer, true);
                }

                CubeFlag rightSlice = CubeFlagService.FromFacePosition(correctEdges2.First().Faces
                                                                       .First(f => f.Position != FacePosition.Top && f.Color != Color.Black).Position);
                SolverMove(CubeFlag.TopLayer, false);

                if (correctEdges2.Count(c => c.Position.HasFlag(rightSlice)) == 0)
                {
                    SolverMove(CubeFlag.TopLayer, true);
                }
                else
                {
                    SolverMove(CubeFlag.TopLayer, true);

                    rightSlice =
                        CubeFlagService.FromFacePosition(
                            correctEdges2
                            .First(cE => !cE.Position.HasFlag(rightSlice))
                            .Faces
                            .First(f =>
                                   f.Position != FacePosition.Top &&
                                   f.Color != Color.Black
                                   )
                            .Position
                            );
                }

                // Algorithm: R U R' U R U U R'
                SolverAlgorithm(
                    "{0} U {0}' U {0} U U {0}'",
                    CubeFlagService.ToNotationString(rightSlice)
                    );

                while (correctEdges2.Count() < 2)
                {
                    SolverMove(CubeFlag.TopLayer, true);
                }
            }
        }