// neil - create logged exercise with a routine
    public LoggedExercise createLoggedExercise(Int32 userID, Int32 exerciseID, Int32 routineID)
    {
        using (var context = new Layer2Container())
        {
            Exercise exercise = context.Exercises.Where(e => e.id == exerciseID).FirstOrDefault();
            LimitBreaker limitBreaker = context.LimitBreakers.Where(l => l.id == userID).FirstOrDefault();
            Routine routine = context.Routines.Where(r => r.id == routineID).FirstOrDefault();

            if (exercise != null && limitBreaker != null && routine != null)
            {
                LoggedExercise log;
                log = new LoggedExercise();
                log.timeLogged = DateTime.Now;
                log.Exercise = exercise;
                log.LimitBreaker = limitBreaker;
                log.Routine = routine;
                context.LoggedExercises.AddObject(log);
                context.SaveChanges();
                return log;
            }
            else
            {
                return null;
            }
        }
    }
    public Routine changeRoutineName(int routineID, string name)
    {
        using (var context = new Layer2Container())
        {
            Routine rc = new Routine();
            try
            {
                Routine rtn = context.Routines.Where(x => x.id == routineID).FirstOrDefault();
                if (rtn != null && rtn.name != name.Trim())
                {
                    rtn.name = name.Trim();
                    context.Routines.ApplyCurrentValues(rtn);
                    context.SaveChanges();
                }
                rc = rtn;
            }
            catch (NullReferenceException e)
            {
                Console.WriteLine(e.Message + Environment.NewLine + e.StackTrace);
                // write off the execeptions to my error.log file
                StreamWriter wrtr = new StreamWriter(System.Web.HttpContext.Current.ApplicationInstance.Server.MapPath("~/assets/documents/" + @"\" + "error.log"), true);

                wrtr.WriteLine(DateTime.Now.ToString() + " | Error: " + e);

                wrtr.Close();
            }

            return rc;
        }
    }
    public bool deleteExerciseById(int id)
    {
        bool result = true;
        using (var context = new Layer2Container())
        {
            try
            {
                var exercise = context.Exercises.Where(s => s.id == id).FirstOrDefault();

                //var exp = context.ExerciseExps.Where(s => s.Exercise.id == id).FirstOrDefault(); // Make it so it only works when there is a related ExerciseExp
                //context.ExerciseExps.DeleteObject(exp);

                exercise.LoggedExercise.Clear();
                exercise.ScheduledExercises.Clear();
                //ExerciseGoal doesn't have a navigation property

                context.Exercises.DeleteObject(exercise);
                context.SaveChanges();
            }

            catch (Exception e)
            {
                result = false;
            }
        }

        return result;
    }
    public bool addNewExerciseGoal(int weight, double distance, int time, int reps, string userName, string exerciseName)
    {
        bool rc = false;

        using (var context = new Layer2Container())
        {
            try
            {
                ExerciseGoal newExerciseGoal = new ExerciseGoal();
                Exercise exercise = context.Exercises.Where(s => s.name == exerciseName).FirstOrDefault();
                LimitBreaker user = context.LimitBreakers.Where(s => s.username == userName).FirstOrDefault();

                newExerciseGoal.LimitBreaker = user;
                newExerciseGoal.Exercise = exercise;
                newExerciseGoal.weight = weight;
                newExerciseGoal.distance = distance;
                newExerciseGoal.time = time;
                newExerciseGoal.reps = reps;

                context.ExerciseGoals.AddObject(newExerciseGoal);
                context.SaveChanges();

                rc = true;
            }

            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace);
            }
        }

        return rc;
    }
    public bool createNewExercise(string exerciseName, string muscleGroups, string equipment, string videoLink, bool rep, bool weight, bool distance, bool time, bool enabled)
    {
        bool rc = false;

        using (var context = new Layer2Container())
        {
            Exercise newExercise = new Exercise();
            try
            {
                if ((context.Exercises.FirstOrDefault(exercise => exercise.name == exerciseName).name == exerciseName))
                    rc = false;
            }
            catch (NullReferenceException e)
            {
                newExercise.name = exerciseName;
                newExercise.muscleGroups = muscleGroups;
                newExercise.equipment = equipment;
                newExercise.videoLink = videoLink;
                newExercise.rep = rep;
                newExercise.weight = weight;
                newExercise.distance = distance;
                newExercise.time = time;
                newExercise.enabled = enabled;

                context.Exercises.AddObject(newExercise);
                context.SaveChanges();
                rc = true;
            }
            return rc;
        }
    }
    public bool createNewExerciseExp(string exerciseName, double baseExp, double weightMod, double repMod, double distanceMod, double timeMod)
    {
        bool rc = false;

        using (var context = new Layer2Container())
        {
            try
            {
                ExerciseExp newExerciseExp = new ExerciseExp();
                Exercise exercise = context.Exercises.Where(s => s.name == exerciseName).FirstOrDefault();

                newExerciseExp.Exercise = exercise;
                newExerciseExp.baseExperience = baseExp;
                newExerciseExp.weightModifier = weightMod;
                newExerciseExp.repModifier = repMod;
                newExerciseExp.distanceModifier = distanceMod;
                newExerciseExp.timeModifier = timeMod;

                context.ExerciseExps.AddObject(newExerciseExp);
                context.SaveChanges();
                rc = true;
            }

            catch (Exception e)
            {
                Console.WriteLine(e.Message + Environment.NewLine + e.StackTrace);
            }
        }

        return rc;
    }
    //BIG F*****G ISSUE WITH THIS FUNCTION ON LINE 68!! This is a note for future reference.
    //The logic fault is that if you clear a LoggedExercise's refernece to an exercise and the exercise still exists, then wtf?! Solution: deleting an exercise is NOT allowed, only disabling
    public bool deleteExerciseByName(string name)
    {
        bool result = true;
        using (var context = new Layer2Container())
        {
            try
            {
                var exercise = context.Exercises.Where(s => s.name == name).FirstOrDefault();

                exercise.LoggedExercise.Clear();
                exercise.ScheduledExercises.Clear();
                exercise.Routines.Clear();
                exercise.ExerciseGoals.Clear();

                var exp = context.ExerciseExps.Where(s => s.Exercise.name == name).FirstOrDefault();
                if (exp != null)
                {
                    context.ExerciseExps.DeleteObject(exp);
                }

                context.Exercises.DeleteObject(exercise);
                context.SaveChanges();
            }

            catch (Exception e)
            {
                result = false;
            }
        }

        return result;
    }
    public bool achieveGoal(ExerciseGoal eg, int reps, int time, int weight, double distance)
    {
        bool achieved = false;

        if (reps >= eg.reps && time >= eg.time && weight >= eg.weight && distance >= eg.distance)
        {
            using (var context = new Layer2Container())
            {
                ExerciseGoal saveGoal = context.ExerciseGoals.Where(s => s.id == eg.id).FirstOrDefault();
                saveGoal.achieved = true;
                context.SaveChanges();
                achieved = true;
            }
        }

        return achieved;
    }
    public bool disableExerciseByName(string name)
    {
        bool result = true;

        using (var context = new Layer2Container())
        {
            try
            {
                Exercise exercise = context.Exercises.Where(s => s.name == name).FirstOrDefault();
                exercise.enabled = false;
                context.SaveChanges();
            }

            catch (Exception e)
            {
                result = false;
            }

            return result;
        }
    }
    public bool enableExerciseById(int id)
    {
        bool result = true;

        using (var context = new Layer2Container())
        {
            try
            {
                Exercise exercise = context.Exercises.Where(s => s.id == id).FirstOrDefault();
                exercise.enabled = true;
                context.SaveChanges();
            }

            catch (Exception e)
            {
                result = false;
            }

            return result;
        }
    }
    public bool deleteExerciseGoalByExerciseNameAndUserName(string userName, string exerciseName)
    {
        bool rc = false;

        try
        {
            using (var context = new Layer2Container())
            {
                ExerciseGoal eg = context.ExerciseGoals.Where(s => s.Exercise.name == exerciseName && s.LimitBreaker.username == userName).FirstOrDefault();

                context.ExerciseGoals.DeleteObject(eg);
                context.SaveChanges();
                rc = true;
            }
        }

        catch (Exception ex)
        {
            Console.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace);
        }

        return rc;
    }
    public bool deleteGoalByGoalID(int goalID)
    {
        bool rc = false;

        try
        {
            using (var context = new Layer2Container())
            {
                ExerciseGoal eg = context.ExerciseGoals.Where(s => s.id == goalID).FirstOrDefault();

                context.ExerciseGoals.DeleteObject(eg);
                context.SaveChanges();
                rc = true;
            }
        }

        catch (Exception ex)
        {
            Console.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace);
        }

        return rc;
    }
    public bool modifyExerciseGoalByExerciseNameAndUserName(string userName, string exerciseName, int time, double distance, int weight, int reps)
    {
        bool rc = false;

        try
        {
            using (var context = new Layer2Container())
            {
                ExerciseGoal eg = context.ExerciseGoals.Where(s => s.Exercise.name == exerciseName && s.LimitBreaker.username == userName).FirstOrDefault();

                eg.time = time;
                eg.distance = distance;
                eg.weight = weight;
                eg.reps = reps;

                context.SaveChanges();
                rc = true;
            }
        }

        catch (Exception ex)
        {
            Console.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace);
        }

        return rc;
    }
    public bool createNewStats(Double weight, Double height, LimitBreaker user)
    {
        bool rc = false;
        using (var context = new Layer2Container())
        {
            Statistics stats = new Statistics();

            stats.level = 1;
            stats.experience = 0;
            stats.weight = weight;
            stats.height = height;
            stats.rmr = 0;
            stats.bmi = 0;
            stats.vo2MAX = 0;

            stats.LimitBreaker = user;

            context.Statistics.AddObject(stats);
            context.SaveChanges();
            rc = true;
        }
        return rc;
    }
    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 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 modifyExperienceAtrophy(int days, int loss)
    {
        bool rc = false;

        using (var context = new Layer2Container())
        {
            try
            {
                ExperienceAtrophy expAtrophy = context.ExperienceAtrophies.FirstOrDefault();

                expAtrophy.graceDays = days;
                expAtrophy.baseLoss = loss;

                context.SaveChanges();
                rc = true;
            }

            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace);
            }
        }

        return rc;
    }
    public bool modifyGoalByGoalID(int goalID, int time, double distance, int weight, int reps)
    {
        bool rc = false;

        try
        {
            using (var context = new Layer2Container())
            {
                ExerciseGoal eg = context.ExerciseGoals.Where(s => s.id == goalID).FirstOrDefault();

                eg.time = time;
                eg.distance = distance;
                eg.weight = weight;
                eg.reps = reps;

                context.SaveChanges();
                rc = true;
            }
        }

        catch (Exception ex)
        {
            Console.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace);
        }

        return rc;
    }
    public bool deleteRoutine(int routineID)
    {
        using (var context = new Layer2Container())
        {
            bool rc = false;
            try
            {
                Routine rtn = context.Routines.Where(x => x.id == routineID).FirstOrDefault();
                ICollection<ScheduledRoutine> srList = rtn.ScheduledRoutines;
                if (rtn != null)
                {
                    // clear dependencies
                    rtn.Exercises.Clear();

                    foreach (ScheduledRoutine sr in srList.ToList())
                        context.ScheduledRoutines.DeleteObject(sr);
                    rtn.ScheduledRoutines.Clear();

                    context.Routines.DeleteObject(rtn);
                    context.SaveChanges();
                    rc = true;
                }
            }
            catch (NullReferenceException e)
            {
                Console.WriteLine(e.Message + Environment.NewLine + e.StackTrace);
                // write off the execeptions to my error.log file
                StreamWriter wrtr = new StreamWriter(System.Web.HttpContext.Current.ApplicationInstance.Server.MapPath("~/assets/documents/" + @"\" + "error.log"), true);

                wrtr.WriteLine(DateTime.Now.ToString() + " | Error: " + e);

                wrtr.Close();
            }

            return rc;
        }
    }
    public bool deleteLoggedExercises(int userID, int routineID)
    {
        using (var context = new Layer2Container())
        {
            bool rc = false;
            try
            {
                LimitBreaker lb = context.LimitBreakers.Where(x => x.id == userID).FirstOrDefault();
                List<LoggedExercise> lelist = context.LoggedExercises.Where(x => x.LimitBreaker.id == lb.id).Where(x => x.Routine.id == routineID).ToList();

                if (lb != null)
                {
                    foreach (LoggedExercise le in lelist)
                    {
                        foreach (SetAttributes sa in le.SetAttributes.ToList())
                        {
                            context.SetAttributes.DeleteObject(sa);
                        }
                        le.SetAttributes.Clear();
                        context.LoggedExercises.DeleteObject(le);
                    }
                    context.SaveChanges();
                }
                rc = true;
            }
            catch (NullReferenceException e)
            {
                Console.WriteLine(e.Message + Environment.NewLine + e.StackTrace);
                // write off the execeptions to my error.log file
                StreamWriter wrtr = new StreamWriter(System.Web.HttpContext.Current.ApplicationInstance.Server.MapPath("~/assets/documents/" + @"\" + "error.log"), true);

                wrtr.WriteLine(DateTime.Now.ToString() + " | Error: " + e);

                wrtr.Close();
            }

            return rc;
        }
    }
    public SetAttributes createSetAttributes(int loggedExerciseID, int weight, float distance, int time, int rep)
    {
        using (var context = new Layer2Container())
        {
            SetAttributes rc = new SetAttributes();
            try
            {
                LoggedExercise le = context.LoggedExercises.Where(x => x.id == loggedExerciseID).FirstOrDefault();

                if (le != null)
                {
                    rc.LoggedExercise = le;
                    rc.weight = weight;
                    rc.distance = distance;
                    rc.time = time;
                    rc.reps = rep;

                    context.SetAttributes.AddObject(rc);
                    context.SaveChanges();
                }
            }
            catch (NullReferenceException e)
            {
                Console.WriteLine(e.Message + Environment.NewLine + e.StackTrace);
                // write off the execeptions to my error.log file
                StreamWriter wrtr = new StreamWriter(System.Web.HttpContext.Current.ApplicationInstance.Server.MapPath("~/assets/documents/" + @"\" + "error.log"), true);

                wrtr.WriteLine(DateTime.Now.ToString() + " | Error: " + e);

                wrtr.Close();
            }

            return rc;
        }
    }
    public LoggedExercise createLoggedExerciseRoutine(int userID, int exerciseID, int routineID, int sets, DateTime logTime, string note)
    {
        using (var context = new Layer2Container())
        {
            LoggedExercise rc = new LoggedExercise();
            try
            {
                LimitBreaker lb = context.LimitBreakers.Where(x => x.id == userID).FirstOrDefault();
                Exercise ex = context.Exercises.Where(x => x.id == exerciseID).FirstOrDefault();
                Routine rtn = context.Routines.Where(x => x.id == routineID).FirstOrDefault();

                if (lb != null && ex != null)
                {

                    rc.LimitBreaker = lb;
                    rc.Exercise = ex;
                    rc.Routine = rtn;
                    rc.timeLogged = logTime;

                    context.LoggedExercises.AddObject(rc);
                    context.SaveChanges();
                }
            }
            catch (NullReferenceException e)
            {
                Console.WriteLine(e.Message + Environment.NewLine + e.StackTrace);
                // write off the execeptions to my error.log file
                StreamWriter wrtr = new StreamWriter(System.Web.HttpContext.Current.ApplicationInstance.Server.MapPath("~/assets/documents/" + @"\" + "error.log"), true);

                wrtr.WriteLine(DateTime.Now.ToString() + " | Error: " + e);

                wrtr.Close();
            }

            return rc;
        }
    }
    public bool modifyExerciseExpByName(string exerciseName, double baseExp, double weightMod, double repMod, double distanceMod, double timeMod)
    {
        bool rc = false;

        using (var context = new Layer2Container())
        {
            try
            {
                ExerciseExp exerciseExp = context.ExerciseExps.Where(s => s.Exercise.name == exerciseName).FirstOrDefault();

                exerciseExp.baseExperience = baseExp;
                exerciseExp.weightModifier = weightMod;
                exerciseExp.repModifier = repMod;
                exerciseExp.distanceModifier = distanceMod;
                exerciseExp.timeModifier = timeMod;

                context.SaveChanges();
                rc = true;
            }

            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace);
            }
        }

        return rc;
    }
    public void updateEmail(string username, string email)
    {
        using (var context = new Layer2Container())
        {
            LimitBreaker user = context.LimitBreakers.FirstOrDefault(limitbreaker => limitbreaker.username == username);

            user.email = email;

            context.SaveChanges();
        }
        MembershipUser aspUser = Membership.GetUser(username);
        aspUser.Email = email;
        Membership.UpdateUser(aspUser);
    }
    public Boolean modifyExercise(Int32 id, string exerciseName, string muscleGroups, string equipment, string videoLink, bool rep, bool weight, bool distance, bool time)
    {
        Boolean rc = false;
        Exercise exercise = null;

        using (var context = new Layer2Container())
        {
            exercise = context.Exercises.Where(x => x.id == id).FirstOrDefault();

            try
            {
                if ((context.Exercises.FirstOrDefault(e => e.name == exerciseName).name == exerciseName && exerciseName != exercise.name))
                {
                    rc = false;
                }
                else
                {
                    exercise.name = exerciseName.Trim();
                    exercise.equipment = equipment.Trim();
                    exercise.videoLink = videoLink.Trim();
                    exercise.rep = rep;
                    exercise.weight = weight;
                    exercise.distance = distance;
                    exercise.time = time;
                    exercise.muscleGroups = muscleGroups;
                    context.Exercises.ApplyCurrentValues(exercise);
                    context.SaveChanges();
                    rc = true;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        return rc;
    }
    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();
        }
    }
    // return the routine created
    public Routine createNewRoutine(String routineName, int userID, ICollection<Exercise> exerciseList)
    {
        using (var context = new Layer2Container())
        {
            Routine rc = new Routine();
            try
            {
                LimitBreaker lb = context.LimitBreakers.Where(x => x.id == userID).FirstOrDefault();
                Exercise exc = new Exercise();
                if (lb != null)
                {
                    rc.name = routineName.Trim();
                    rc.LimitBreaker = lb;
                    rc.lastModified = DateTime.Now;
                    foreach (Exercise ex in exerciseList)
                    {
        #if DEBUG
                        response.Write("Exercise: " + ex.name + "<br/> ID: " + ex.id + "<br/>");
        #endif
                        // to prevent object out of context error
                        exc = context.Exercises.Where(x => x.id == ex.id).FirstOrDefault();
                        rc.Exercises.Add(exc);
                        exc = new Exercise();
                    }

                    context.Routines.AddObject(rc);
                    context.SaveChanges();
                }
            }
            catch (NullReferenceException e)
            {
                Console.WriteLine(e.Message + Environment.NewLine + e.StackTrace);
                // write off the execeptions to my error.log file
                StreamWriter wrtr = new StreamWriter(System.Web.HttpContext.Current.ApplicationInstance.Server.MapPath("~/assets/documents/" + @"\" + "error.log"), true);

                wrtr.WriteLine(DateTime.Now.ToString() + " | Error: " + e);

                wrtr.Close();
            }

            return rc;
        }
    }
    public bool modifyLevelFormula(int maxLvl, double expMod, int baseReq)
    {
        bool rc = false;

        using (var context = new Layer2Container())
        {
            try
            {
                LevelFormula lvlForm = context.LevelFormulas.FirstOrDefault();

                lvlForm.maxLevel = maxLvl;
                lvlForm.expModifier = expMod;
                lvlForm.baseRequired = baseReq;

                context.SaveChanges();
                rc = true;
            }

            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace);
            }
        }

        return rc;
    }
    public void recordOldWeight(LimitBreaker user, Double weight, Layer2Container context)
    {
        OldWeight oldWeight = new OldWeight();
        oldWeight.LimitBreaker = user;
        oldWeight.date = DateTime.Now;
        oldWeight.weight = weight;

        context.OldWeights.AddObject(oldWeight);

        context.SaveChanges();
    }
    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();
        }
    }