Inheritance: IDisposable
        // GET: /Student/CourseRoster?term=201301&subject=ENL&courseNumber=262&key=1234
        public ActionResult CourseRoster(string term, string subject, string courseNumber)
        {
            if (string.IsNullOrWhiteSpace(term) || string.IsNullOrWhiteSpace(subject) || string.IsNullOrWhiteSpace(courseNumber))
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Term, Subject and CourseNumber need to be provided");
            }

            using (var db = new DbManager())
            {
                var rosterQuery = db.Connection.QueryMultiple(QueryResources.RosterSubjectQuery,
                    new { Term = term, Subject = subject, CourseNumb = courseNumber });

                var students = rosterQuery.Read().ToList();
                var instructors = rosterQuery.Read().ToList();

                var courses = from c in students
                              group c by c.Crn into uniqueCourses
                              orderby uniqueCourses.Key
                              select new CourseRoster
                              {
                                  Crn = uniqueCourses.Key,
                                  Students = students.Where(s => s.Crn == uniqueCourses.Key).Select(s => new Person(s)).ToArray(),
                                  Instructors = instructors.Where(i => i.Crn == uniqueCourses.Key).Select(i => new Person(i)).ToArray()
                              };

                return new JsonNetResult(courses);
            }
        }
        // GET: /Student/Course?term=201301&subject=ENL&courseNumber=262&key=1234
        public ActionResult Course(string term, string subject, string courseNumber)
        {
            if (string.IsNullOrWhiteSpace(term) || string.IsNullOrWhiteSpace(subject) || string.IsNullOrWhiteSpace(courseNumber))
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Term, Subject and CourseNumber need to be provided");
            }

            using (var db = new DbManager())
            {
                var courseQuery = db.Connection.Query(QueryResources.CourseSubjectQuery,
                    new { Term = term, Subject = subject, CourseNumb = courseNumber });

                var courses = from c in courseQuery
                              group c by new { c.Subject, c.CourseNumb }
                                  into x
                                  select new Course(x.First())
                                  {
                                      Sections =
                                          x.GroupBy(y => y.Sequence)
                                           .Select(y => new Section(y.First()) { Classtimes = y.Select(z => new Classtime(z)) })
                                  };

                return new JsonNetResult(courses.FirstOrDefault());
            }
        }
        // GET: /Monitor/
        public ActionResult Index(string key)
        {
            var monitorKey = WebConfigurationManager.AppSettings["monitor"];

            Check.Require(key == monitorKey, "Not a valid monitor key");

            using (var db = new DbManager())
            {
                var term = db.Connection.Query("select top 1 Id from terms").Single();
                return new JsonNetResult(term);
            }
        }
        public ActionResult Find(string subject)
        {
            if (string.IsNullOrWhiteSpace(subject))
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Subject cannot be empty");
            }

            using (var db = new DbManager())
            {
                var departments = db.Connection.Query(QueryResources.DeparmentFindQuery, new {subject});
                return new JsonNetResult(departments.FirstOrDefault());
            }
        }
        public ActionResult Crn(string crn)
        {
            if (string.IsNullOrWhiteSpace(crn))
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Crn cannot be empty");
            }

            using (var db = new DbManager())
            {
                var departments = db.Connection.Query(QueryResources.DepartmentCrnQuery, new {crn});
                return new JsonNetResult(departments.FirstOrDefault());
            }
        }
        // GET: /Course/GradesRemaining?term=201306&crns=60152&crns=60170&key=1234
        public ActionResult GradesRemaining(string term, string[] crns)
        {
            if (crns == null || !crns.Any() || string.IsNullOrWhiteSpace(term))
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Neither Course Nubmers nor Term can be empty");
            }

            using (var db = new DbManager())
            {
                var courses = db.Connection.Query("SELECT TermCode, Crn, GradesOutstandingCount, Gradable FROM Courses WHERE termCode = @term AND crn in @crns", new { term, crns });

                return new JsonNetResult(courses);
            }
        }
        // GET: /Course/Complete?term=201301&subject=MAT&courseNumbers=021A&courseNumbers=021B&key=1234
        public ActionResult Complete(string term, string subject, string[] courseNumbers)
        {
            if (string.IsNullOrWhiteSpace(subject) || courseNumbers == null || !courseNumbers.Any()|| string.IsNullOrWhiteSpace(term))
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Neither Subject, Course Nubmers nor Term can be empty");
            }

            using (var db = new DbManager())
            {
                var cm = string.Join(",", courseNumbers.Select(a => "'" + a + "'"));
                var cq = string.Format(QueryResources.CoursesSubjectQuery, cm);
                var rq = string.Format(QueryResources.RostersSubjectQuery, cm);

                var courseQuery = db.Connection.Query(cq,
                    new { Term = term, Subject = subject });

                var rosterQuery = db.Connection.QueryMultiple(rq,
                    new { Term = term, Subject = subject });

                var students = rosterQuery.Read().ToList();
                var instructors = rosterQuery.Read().ToList();

                var courses = from c in courseQuery
                              group c by new { c.Subject, c.CourseNumb }
                                  into x
                                  select new Course(x.First())
                                  {
                                      Sections = x.GroupBy(y => y.Sequence)
                                          .Select(y => new Section(y.First())
                                          {
                                              Classtimes = y.Select(z => new Classtime(z)),
                                              CourseRoster = new CourseRoster()
                                              {
                                                  Students = students.Where(a => a.Crn == y.First().Crn).Select(s => new Person(s)).ToArray(),
                                                  Instructors = instructors.Where(a => a.Crn == y.First().Crn).Select(i => new Person(i)).ToArray()
                                              }
                                          })
                                  };

                return new JsonNetResult(courses);
            }
        }
        // GET: /Student/Course?term=201303&subject
        // GET: /Student/Courses?department=wxyz&term=201301&key=1234
        public ActionResult Courses(string department, string term)
        {
            if (string.IsNullOrWhiteSpace(department) || string.IsNullOrWhiteSpace(term))
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Neither Department nor Term can be empty");
            }

            using (var db = new DbManager())
            {
                var courseQuery = db.Connection.Query(QueryResources.CourseSectionQuery, new { Term = term, Department = department });

                var courses = from c in courseQuery
                              group c by new {c.Subject, c.CourseNumb}
                              into x
                              select new Course(x.First())
                                  {
                                      Sections =
                                          x.GroupBy(y => y.Sequence)
                                           .Select(y => new Section(y.First()) {Classtimes = y.Select(z => new Classtime(z))})
                                  };

                return new JsonNetResult(courses);
            }
        }
        // GET: /Course/List?department=wxyz&term=201301&key=1234
        public ActionResult List(string term, string department)
        {
            if (string.IsNullOrWhiteSpace(department) || string.IsNullOrWhiteSpace(term))
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Neither Department nor Term can be empty");
            }

            using (var db = new DbManager())
            {
                var courseQuery = db.Connection.Query(QueryResources.CourseSectionQuery, new { Term = term, Department = department });
                var courses = courseQuery.Select(a => new {a.Subject, a.CourseNumb, a.Name}).Distinct();
                return new JsonNetResult(courses);
            }
        }
        // GET: /Student/TermCodes?key=1234
        public ActionResult TermCodes()
        {
            using (var db = new DbManager())
            {
                var terms = db.Connection.Query(QueryResources.TermCodeQuery);

                return new JsonNetResult(terms);
            }
        }
        // GET: /Student/Roster?term=201301&crn=52960&key=1234
        public ActionResult Roster(string term, string crn)
        {
            if (string.IsNullOrWhiteSpace(term) || string.IsNullOrWhiteSpace(crn))
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Neither Term nor Crn can be empty");
            }

            using (var db = new DbManager())
            {
                var rosterQuery = db.Connection.QueryMultiple(QueryResources.RosterQuery, new { @Term = term, @Crn = crn });

                var students = rosterQuery.Read().ToList();
                var instructors = rosterQuery.Read().ToList();

                return new JsonNetResult(new { students, instructors });
            }
        }