private async Task AddCardio(Difficulty difficulty, Goal goal, TrainingDay trainingDay)
        {
            int exerciseCount = goal == Goal.Lose
                ? 2
                : 1;
            var exercises = new List <Exercise>();

            for (int i = 0; i < exerciseCount; i++)
            {
                var currentExercises = await this.exercisesRepository
                                       .All()
                                       .Where(x => (x.Type == ExerciseType.Cardio) &&
                                              exercises.Contains(x) == false)
                                       .ToListAsync();

                var rand            = new Random();
                var currentExercise = currentExercises[rand.Next(0, currentExercises.Count)];
                while (goal != Goal.Lose && currentExercise.Difficulty == Difficulty.Hard)
                {
                    currentExercise = currentExercises[rand.Next(0, currentExercises.Count)];
                }

                exercises.Add(currentExercise);
                var workoutTrainingDay = new WorkoutTrainingDay()
                {
                    ExerciseId    = currentExercise.Id,
                    Exercise      = currentExercise,
                    TrainingDay   = trainingDay,
                    TrainingDayId = trainingDay.Id,
                    MinRepsCount  = currentExercise.Difficulty == Difficulty.Hard
                    ? 10
                    : currentExercise.Difficulty == Difficulty.Medium
                    ? 15
                    : 20,
                    MaxRepsCount = currentExercise.Difficulty == Difficulty.Hard
                    ? 20
                    : currentExercise.Difficulty == Difficulty.Medium
                    ? 25
                    : 30,
                };

                if (goal != Goal.Lose && currentExercise.Difficulty != Difficulty.Hard)
                {
                    workoutTrainingDay.MinRepsCount -= 5;
                    workoutTrainingDay.MaxRepsCount -= 5;
                }

                await this.workoutTrainingDayRepository.AddAsync(workoutTrainingDay);

                trainingDay.Exercises.Add(workoutTrainingDay);
                currentExercise.WorkoutPlans.Add(workoutTrainingDay);
            }
        }
        private async Task <TrainingDay> GenerateSeparateMusclesDay(
            Goal goal, Difficulty difficulty, WorkoutPlan workoutPlan, Day day, List <ExerciseType> exercises)
        {
            var trainingDay = new TrainingDay()
            {
                Day           = day,
                WorkoutPlan   = workoutPlan,
                WorkoutPlanId = workoutPlan.Id,
            };

            var pickedExercises = new List <Exercise>();
            int exercisesCount;
            int firstSet;

            switch (difficulty)
            {
            case Difficulty.Easy:
                exercisesCount = 5;
                firstSet       = 3;
                break;

            case Difficulty.Medium:
                exercisesCount = 6;
                firstSet       = 3;
                break;

            case Difficulty.Hard:
                exercisesCount = 7;
                firstSet       = 4;
                break;

            default:
                exercisesCount = 12;
                firstSet       = 12;
                break;
            }

            if (exercises.Count == 1)
            {
                firstSet = exercisesCount;
            }

            for (int i = 0; i < firstSet; i++)
            {
                var currentExercises = await this.exercisesRepository
                                       .All()
                                       .Where(x => x.Type == exercises[0] && pickedExercises.Contains(x) == false)
                                       .ToListAsync();

                if (currentExercises.Any() == false)
                {
                    break;
                }

                var rand            = new Random();
                var currentExercise = currentExercises[rand.Next(0, currentExercises.Count)];
                pickedExercises.Add(currentExercise);

                var workoutTrainingDay = new WorkoutTrainingDay()
                {
                    ExerciseId    = currentExercise.Id,
                    Exercise      = currentExercise,
                    TrainingDay   = trainingDay,
                    TrainingDayId = trainingDay.Id,
                    MinRepsCount  = currentExercise.Difficulty == Difficulty.Hard
                    ? 6
                    : currentExercise.Difficulty == Difficulty.Medium
                    ? 8
                    : 10,
                    MaxRepsCount = currentExercise.Difficulty == Difficulty.Hard
                    ? 10
                    : currentExercise.Difficulty == Difficulty.Medium
                    ? 12
                    : 14,
                };

                await this.workoutTrainingDayRepository.AddAsync(workoutTrainingDay);

                trainingDay.Exercises.Add(workoutTrainingDay);
                currentExercise.WorkoutPlans.Add(workoutTrainingDay);
            }

            if (exercises.Count == 2)
            {
                int secondSet = exercisesCount - firstSet;
                for (int i = 0; i < secondSet; i++)
                {
                    var currentExercises = await this.exercisesRepository
                                           .All()
                                           .Where(x => x.Type == exercises[1] && pickedExercises.Contains(x) == false)
                                           .ToListAsync();

                    var rand            = new Random();
                    var currentExercise = currentExercises[rand.Next(0, currentExercises.Count)];
                    pickedExercises.Add(currentExercise);

                    var workoutTrainingDay = new WorkoutTrainingDay()
                    {
                        ExerciseId    = currentExercise.Id,
                        Exercise      = currentExercise,
                        TrainingDay   = trainingDay,
                        TrainingDayId = trainingDay.Id,
                        MinRepsCount  = currentExercise.Difficulty == Difficulty.Hard
                        ? 6
                        : currentExercise.Difficulty == Difficulty.Medium
                        ? 8
                        : 10,
                        MaxRepsCount = currentExercise.Difficulty == Difficulty.Hard
                        ? 10
                        : currentExercise.Difficulty == Difficulty.Medium
                        ? 12
                        : 14,
                    };

                    await this.workoutTrainingDayRepository.AddAsync(workoutTrainingDay);

                    trainingDay.Exercises.Add(workoutTrainingDay);
                    currentExercise.WorkoutPlans.Add(workoutTrainingDay);
                }
            }

            await this.trainingDaysRepository.AddAsync(trainingDay);

            return(trainingDay);
        }
        private async Task <TrainingDay> GenerateFullBodyDay(Goal goal, Difficulty difficulty, WorkoutPlan workoutPlan)
        {
            var trainingDay = new TrainingDay()
            {
                Day           = Day.Undefined,
                WorkoutPlanId = workoutPlan.Id,
                WorkoutPlan   = workoutPlan,
            };

            int             exercisesCount;
            List <Exercise> currentDayExercises = new List <Exercise>();
            List <Exercise> exercises           = new List <Exercise>();

            exercises.AddRange(workoutPlan.TrainingDays.SelectMany(x => x.Exercises.Select(x => x.Exercise)));
            switch (difficulty)
            {
            case Difficulty.Easy:
                exercisesCount = 6;
                break;

            case Difficulty.Medium:
                exercisesCount = 7;
                break;

            case Difficulty.Hard:
                exercisesCount = 8;
                break;

            default:
                exercisesCount = 5;
                break;
            }

            if (goal == Goal.Lose)
            {
                exercisesCount -= 2;
            }

            for (int i = 0; i < exercisesCount; i++)
            {
                var currentExercises = await this.exercisesRepository
                                       .All()
                                       .Where(x => (x.Type != ExerciseType.Abs &&
                                                    x.Type != ExerciseType.Cardio) &&
                                              exercises.Contains(x) == false)
                                       .ToListAsync();

                var rand            = new Random();
                var currentExercise = currentExercises[rand.Next(0, currentExercises.Count)];
                while (currentDayExercises.Any(x => x.Type == currentExercise.Type))
                {
                    if (i == 6 || i == 7)
                    {
                        currentExercises =
                            currentExercises
                            .Where(x => x.Type == ExerciseType.Chest ||
                                   x.Type == ExerciseType.Back ||
                                   x.Type == ExerciseType.Legs)
                            .ToList();
                        currentExercise = currentExercises[rand.Next(0, currentExercises.Count)];
                        break;
                    }

                    currentExercise = currentExercises[rand.Next(0, currentExercises.Count)];
                }

                exercises.Add(currentExercise);
                currentDayExercises.Add(currentExercise);

                var workoutTrainingDay = new WorkoutTrainingDay()
                {
                    ExerciseId    = currentExercise.Id,
                    Exercise      = currentExercise,
                    TrainingDay   = trainingDay,
                    TrainingDayId = trainingDay.Id,
                    MinRepsCount  = currentExercise.Difficulty == Difficulty.Hard
                    ? 6
                    : currentExercise.Difficulty == Difficulty.Medium
                    ? 8
                    : 10,
                    MaxRepsCount = currentExercise.Difficulty == Difficulty.Hard
                    ? 10
                    : currentExercise.Difficulty == Difficulty.Medium
                    ? 12
                    : 14,
                };

                await this.workoutTrainingDayRepository.AddAsync(workoutTrainingDay);

                trainingDay.Exercises.Add(workoutTrainingDay);
                currentExercise.WorkoutPlans.Add(workoutTrainingDay);
            }

            await this.AddCardio(difficulty, goal, trainingDay);

            await this.trainingDaysRepository.AddAsync(trainingDay);

            return(trainingDay);
        }