public List<ExerciseGoal> getUnachievedExerciseGoalsFromUser(string userName, int orderBy)
    {
        using (var context = new Layer2Container())
        {
            List<ExerciseGoal> goalSet;

            switch (orderBy)
            {
                case 0:
                    goalSet = context.ExerciseGoals.Where(s => s.LimitBreaker.username == userName && s.achieved == false).OrderBy(o => o.Exercise.name).ToList();
                    break;
                case 1:
                    goalSet = context.ExerciseGoals.Where(s => s.LimitBreaker.username == userName && s.achieved == false).OrderBy(o => o.id).ToList();
                    break;
                default:
                    goalSet = context.ExerciseGoals.Where(s => s.LimitBreaker.username == userName && s.achieved == false).ToList();
                    break;
            }

            foreach (ExerciseGoal eg in goalSet)
            {
                context.LoadProperty(eg, "Exercise");
            }

            return goalSet;
        }
    }
    public void updateRMR(String username)
    {
        using (var context = new Layer2Container())
        {
            LimitBreaker user = context.LimitBreakers.FirstOrDefault(limitbreaker => limitbreaker.username == username);
            context.LoadProperty(user, "Statistics"); ;

            if (user.gender == "Male")
            {
                user.Statistics.rmr = user.Statistics.weight * 10 +
                      user.Statistics.height * 6.25 -
                      (DateTime.Now.Year - user.dateOfBirth.Year) * 6.76 +
                      66;
            }
            else
            {
                user.Statistics.rmr = user.Statistics.weight * 9.56 +
                      user.Statistics.height * 1.85 -
                      (DateTime.Now.Year - user.dateOfBirth.Year) * 4.68 +
                      655;
            }
            context.SaveChanges();
        }
    }
    public bool updateWeight(String username, Double newWeight)
    {
        using (var context = new Layer2Container())
        {
            LimitBreaker user = context.LimitBreakers.FirstOrDefault(limitbreaker => limitbreaker.username == username);
            context.LoadProperty(user, "Statistics");
            context.LoadProperty(user, "OldWeights");

            //To avoid accessing null
            if (user.OldWeights.Count > 0)
            {
                //Return false (do not update weight) if old weight exists and the update day was less than 24 hours
                if (DateTime.Now.Subtract(user.OldWeights.LastOrDefault().date).Days < 1)
                {
                    return false;
                }
                recordOldWeight(user, user.Statistics.weight, context);
            }
            else
            {
                recordOldWeight(user, user.Statistics.weight, context);
            }
            user.Statistics.weight = newWeight;
            context.SaveChanges();
            return true;
        }
    }
    public void updateBMI(String username)
    {
        using (var context = new Layer2Container())
        {
            LimitBreaker user = context.LimitBreakers.FirstOrDefault(limitbreaker => limitbreaker.username == username);
            context.LoadProperty(user, "Statistics");

            user.Statistics.bmi = (user.Statistics.weight) / Math.Pow(user.Statistics.height / 100, 2);

            context.SaveChanges();
        }
    }
    public void updateHeight(String username, Double newHeight)
    {
        using (var context = new Layer2Container())
        {
            LimitBreaker user = context.LimitBreakers.FirstOrDefault(limitbreaker => limitbreaker.username == username);
            context.LoadProperty(user, "Statistics");

            user.Statistics.height = newHeight;

            context.SaveChanges();
        }
    }
    public Routine getRoutineByScheduledItem(Int32 id)
    {
        using (var context = new Layer2Container())
        {
            ScheduledRoutine schRoutine = context.ScheduledRoutines.Where(e => e.id == id).FirstOrDefault();
            context.LoadProperty(schRoutine, "Routine");
            return context.Routines.Where(e => e.id == schRoutine.Routine.id).FirstOrDefault();

        }
    }
    public List<ExerciseGoal> getAchievedExerciseGoalsFromUser(string userName, int orderBy, string muscleGroup)
    {
        using (var context = new Layer2Container())
        {
            List<ExerciseGoal> goalSet;

            if (muscleGroup != "All Groups")
            {
                switch (orderBy)
                {
                    case 0:
                        goalSet = context.ExerciseGoals.Where(s => s.LimitBreaker.username == userName && s.achieved == true && s.Exercise.muscleGroups.Contains(muscleGroup)).OrderBy(o => o.Exercise.name).ToList();
                        break;
                    case 1:
                        goalSet = context.ExerciseGoals.Where(s => s.LimitBreaker.username == userName && s.achieved == true && s.Exercise.muscleGroups.Contains(muscleGroup)).OrderBy(o => o.id).ToList();
                        break;
                    default:
                        goalSet = context.ExerciseGoals.Where(s => s.LimitBreaker.username == userName && s.achieved == true && s.Exercise.muscleGroups.Contains(muscleGroup)).ToList();
                        break;
                }
            }

            else
            {
                switch (orderBy)
                {
                    case 0:
                        goalSet = context.ExerciseGoals.Where(s => s.LimitBreaker.username == userName && s.achieved == true).OrderBy(o => o.Exercise.name).ToList();
                        break;
                    case 1:
                        goalSet = context.ExerciseGoals.Where(s => s.LimitBreaker.username == userName && s.achieved == true).OrderBy(o => o.id).ToList();
                        break;
                    default:
                        goalSet = context.ExerciseGoals.Where(s => s.LimitBreaker.username == userName && s.achieved == true).ToList();
                        break;
                }
            }

            foreach (ExerciseGoal eg in goalSet)
            {
                context.LoadProperty(eg, "Exercise");
            }

            return goalSet;
        }
    }
    //if top3 is true it only returns the top 3 users
    public List<LeaderBoardItem> getLeaderBoardValues(int orderBy, bool top3)
    {
        using (var context = new Layer2Container())
        {
            List<LimitBreaker> lbSet;
            List<LeaderBoardItem> leaderBoardItemSet = new List<LeaderBoardItem>();

            switch (orderBy)
            {
                //order by level then experience
                case 1:
                    lbSet = context.LimitBreakers.OrderByDescending(l => l.Statistics.level).ThenByDescending(l => l.Statistics.experience).ThenBy(l => l.username).ToList();
                    break;
                //order by number of achieved goals
                case 2:
                    lbSet = context.LimitBreakers.OrderByDescending(l => l.ExerciseGoals.Where(g => g.achieved == true).Count()).ThenBy(l => l.username).ToList();
                    break;
                //order by number of logged exercises
                case 3:
                    lbSet = context.LimitBreakers.OrderByDescending(l => l.LoggedExercises.Count()).ThenBy(l => l.username).ToList();
                    break;
                default:
                    lbSet = context.LimitBreakers.OrderByDescending(l => l.Statistics.level).ThenByDescending(l => l.Statistics.experience).ThenBy(l => l.username).ToList();
                    break;
            }

            int i = 1;

            if (!top3)
            {
                foreach (LimitBreaker lb in lbSet)
                {
                    context.LoadProperty(lb, "ExerciseGoals");
                    context.LoadProperty(lb, "Statistics");
                    context.LoadProperty(lb, "LoggedExercises");
                    leaderBoardItemSet.Add(new LeaderBoardItem(i, lb.username, lb.Statistics.level, Convert.ToInt32(lb.Statistics.experience), lb.ExerciseGoals.Where(g => g.achieved == true).Count(), lb.LoggedExercises.Count()));
                    i++;
                }
            }

            else
            {
                foreach (LimitBreaker lb in lbSet)
                {
                    context.LoadProperty(lb, "ExerciseGoals");
                    context.LoadProperty(lb, "Statistics");
                    context.LoadProperty(lb, "LoggedExercises");
                    leaderBoardItemSet.Add(new LeaderBoardItem(i, lb.username, lb.Statistics.level, Convert.ToInt32(lb.Statistics.experience), lb.ExerciseGoals.Where(g => g.achieved == true).Count(), lb.LoggedExercises.Count()));
                    i++;
                }
            }

            return leaderBoardItemSet;
        }
    }
    public LeaderBoardItem getUserValues(string userName)
    {
        using (var context = new Layer2Container())
        {
            LimitBreaker lb = context.LimitBreakers.Where(l => l.username == userName).FirstOrDefault();

            context.LoadProperty(lb, "ExerciseGoals");
            context.LoadProperty(lb, "Statistics");
            context.LoadProperty(lb, "LoggedExercises");

            return new LeaderBoardItem(0, userName, lb.Statistics.level, Convert.ToInt32(lb.Statistics.experience), lb.ExerciseGoals.Where(g => g.achieved == true).Count(), lb.LoggedExercises.Count());
        }
    }
    public Exercise getExerciseByScheduledItem(Int32 id)
    {
        using (var context = new Layer2Container())
        {
            ScheduledExercise schExercise = context.ScheduledExercises.Where(e => e.id == id).FirstOrDefault();
            context.LoadProperty(schExercise, "Exercise");
            return context.Exercises.Where(e => e.id == schExercise.Exercise.id).FirstOrDefault();

        }
    }