// GET: Report
        public ActionResult Index()
        {
            ReportDAL dal = new ReportDAL(_db);

            string userId = User.Identity.GetUserId();
            if (dal.UserHasIncompleteReport(userId))
                return RedirectToAction("Complete", new { uncompletedExists = true, redirected=true });

            return RedirectToAction("Startup", "Report");
        }
        public ActionResult Startup(bool reportCompleted = false, int? associatedProjectId = null)
        {
            Project associatedProject = null;

            if (reportCompleted)
                ViewBag.AppMessage = new AppMessage() { Type = AppMessage.Success, Message = AppString.ReportCompleted };
            if (associatedProjectId != null)
            {
                associatedProject = _db.Projects.Single(p => p.Id == associatedProjectId);
                ViewBag.AppMessage = new AppMessage() { Type = AppMessage.Success, Message = String.Format(AppString.ProjectAssociated, associatedProject.Name) };
            }
                

            string userId = User.Identity.GetUserId();

            ErrorLogger.LogString(User.IsInRole("Admin").ToString());

            // Makes sure that users finish previous reports first.
            ReportDAL rDb = new ReportDAL(_db);
            if (rDb.UserHasIncompleteReport(userId))
                return RedirectToAction("Index");

            ReportStartupViewModel model = new ReportStartupViewModel();

            try {
                PrepareProjectsForViewModel(model, associatedProject);
            } catch (Exception e) {
                // User is not logged in properly. Maybe a threading issue? (This code is a workaround)
                ErrorLogger.LogString("Could not log in. userId = " + User.Identity.GetUserId() );
                return RedirectToAction("Index", "Report"); 
            }
            
            // A user must have atleast one associated project to be able to report. Values are set in the PrepareProjectForStartup method call.
            if (model.AvailableProjects == null && model.SelectedProjectName == null)
                return RedirectToAction("Associate", "Project");

            
            PrepareCarsForViewModel(model);

            return View(model);
        }
        public ActionResult Startup(ReportStartupViewModel model)
        {
            if (ModelState.IsValid)
            {
                ReportDAL dal = new ReportDAL(_db);


                string currUserId = User.Identity.GetUserId(); // Calling GetUserId() within a Lambda-expression causes errors

                int? lastOdometerStatus = dal.GetLatestOdometerStatus(model.SelectedCarId);
                if ( lastOdometerStatus != null && model.OdometerStart < lastOdometerStatus ) {
                    ViewBag.OdometerError = String.Format(AppString.ErrorOdometerStart, lastOdometerStatus-1);
                    PrepareCarsForViewModel(model);
                    PrepareProjectsForViewModel(model, null);
                    return View(model);
                }

                Report report = new Report()
                {
                    Date = DateTime.Now,
                    OdometerStart = model.OdometerStart,
                    AssociatedCar = _db.Cars.Single(c => c.Id == model.SelectedCarId),
                    AssociatedProject = _db.Projects.Single(p => p.Id == model.SelectedProjectId),
                    AssociatedUser = _db.Users.Single(u => u.Id == currUserId),
                    FromLocation = model.FromLocation
                };

                // TODO: Perform checks on the received data to make sure that there isn't any user shenanigans going on. For example if a project id was passed that the user isn't associated with.

                _db.Reports.Add(report);
                _db.SaveChanges();

                return RedirectToAction("Complete", "Report", new { reportStarted = true });
            }

            return View(model);
        }
        /* Helper Methods below: */


        private void PrepareCarsForViewModel(ReportStartupViewModel model)
        {
            ICollection<Car> cars = _db.Cars.Where(c => c.Active).ToList();
            ReportDAL rDB = new ReportDAL(_db);
            // User doesn't need to select cars if there is only one available
            int? latestOdometerStatus = null;
            if (cars.Count == 1)
            {
                Car selectedCar = cars.FirstOrDefault();
                model.SelectedCarRegistrationNumber = selectedCar.RegistrationNumber;
                model.SelectedCarId = selectedCar.Id;

                latestOdometerStatus = rDB.GetLatestOdometerStatus(selectedCar.Id); ;
            }
            else
            {
                latestOdometerStatus = rDB.GetLatestOdometerStatus(cars.ToArray()[0].Id);
                model.AvailableCars = new SelectList(cars, "Id", "RegistrationNumber");
            }

            if (latestOdometerStatus != null)
                model.OdometerStart = (int)latestOdometerStatus;
        }
        public JsonResult LastRegisteredOdometerStatus(int carId)
        {
            ReportDAL dal = new ReportDAL(_db);

            int? oStatus = dal.GetLatestOdometerStatus(carId);

            if (oStatus != null)
                return Json(oStatus.ToString(), JsonRequestBehavior.AllowGet);
            else
                return Json("", JsonRequestBehavior.AllowGet);
        }
        public ActionResult Complete(ReportCompletionViewModel model)
        {
            if (ModelState.IsValid)
            {
                ReportDAL dal = new ReportDAL(_db);

                string userId = User.Identity.GetUserId();
                Report report = dal.GetLatestUncompletedReport(userId);

                if (report.OdometerStart >= model.OdometerEnd)
                {
                    ViewBag.OdometerError = AppString.ErrorOdometerEnd;
                    return View(model);
                }
                    

                report.OdometerEnd = model.OdometerEnd;
                report.ToLocation = model.ToLocation;
                report.Passengers = model.Passengers;
                report.Debitable = model.Debitable;
                report.Purpose = model.Purpose;

                _db.Reports.Attach(report);
                _db.Entry(report).State = EntityState.Modified;
                _db.SaveChanges();
                return RedirectToAction("Startup", "Report", new { reportCompleted = true });
            }

            return View(model);
        }
        public ActionResult Complete(bool uncompletedExists = false, bool reportStarted = false)
        {
            if (reportStarted)
                ViewBag.AppMessage = new AppMessage() { Type = AppMessage.Success, Message = AppString.ReportStarted };
            if (uncompletedExists)
                ViewBag.AppMessage = new AppMessage() { Type = AppMessage.Warning, Message = AppString.ReportUncompletedExists };

            ReportDAL dal = new ReportDAL(_db);
            string userId = User.Identity.GetUserId();
            Report report = dal.GetLatestUncompletedReport(userId);
            string projectInfo = null;
            if (report.AssociatedProject.Name == "DefaultProject")
                projectInfo = "[ " + AppString.ProjectNotBound + " ]";
            else
                projectInfo = report.AssociatedProject.Name + " - " + report.AssociatedProject.ProjectNumber;

            ReportCompletionViewModel model = new ReportCompletionViewModel()
            {
                Date = report.Date.ToString("yyyy-MM-dd HH:mm"),
                CarRegistrationNumber = report.AssociatedCar.RegistrationNumber,
                ProjectInfo = projectInfo,
                OdometerStart = report.OdometerStart
            };


            return View(model);
        }