using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using MileageTraker.Web.Attributes;
using MileageTraker.Web.DAL;
using MileageTraker.Web.Email;
using MileageTraker.Web.Models;
using MileageTraker.Web.Utility;
using MileageTraker.Web.ViewModels;
using MileageTraker.Web.ViewModels.ServiceReminder;
using MileageTraker.Web.ViewModels.VehicleService;

namespace MileageTraker.Web.Controllers
{
	[Authorize(Roles = "Administrator, Developer, Driver")]
	public class VehicleServiceController : ControllerBase
    {
        [Authorize(Roles = "Administrator, Developer")]
        public ActionResult Index(VehicleServiceQueryViewModel query)
        {
			var validVehicleServiceYearMonths = DataService.GetValidVehicleServiceMonths();

			if (!validVehicleServiceYearMonths.Any()) // this means no logs in DB
				return View("Empty");

			// default parameter processing
			query.SetDefaultParameters(validVehicleServiceYearMonths);

			var vehicleServices = DataService.FilterVehicleServices(DataService.GetVehicleServices(), query).ToList();

	        var upcomingServiceReminders =
				DataService.GetUpcomingServiceReminders().ToList()
				.Select(sr => new ServiceReminderViewModel(sr)).ToList();
			upcomingServiceReminders.Sort();

	        var viewModel = new VehicleServiceResultsViewModel(
		        vehicleServices.Select(s => new VehicleServiceViewModel(s)),
				upcomingServiceReminders,
		        query,
		        CustomExtensions.YearMonthList(validVehicleServiceYearMonths));

			return View(viewModel);
        }

        [Authorize(Roles = "Administrator, Developer")]
		[ActionLog]
		public ActionResult Export(VehicleServiceQueryViewModel query)
		{
			var validVehicleServiceYearMonths = DataService.GetValidVehicleServiceMonths();

			if (!validVehicleServiceYearMonths.Any()) // this means no logs in DB
				return View("Empty");

			// default parameter processing
			query.SetDefaultParameters(validVehicleServiceYearMonths);

			var vehicleServices = DataService.FilterVehicleServices(DataService.GetVehicleServices(), query).ToList();
			var filteredServices = vehicleServices.Select(vs => new VehicleServiceViewModel(vs));

			var name = string.Format("VehicleServices_{0}", query);

			var export = ExcelWriter<VehicleServiceViewModel>.WriteXls(filteredServices, name, name);
			return File(export, "application/ms-excel", name + ".xls");
		}

        [Authorize(Roles = "Administrator, Developer")]
		public ViewResult Details(int id)
		{
			var vehicleService = DataService.GetVehicleService(id);
			var viewModel = new VehicleServiceViewModel(vehicleService);
			return View(viewModel);
		}

        [Authorize(Roles = "Administrator, Developer")]
		public ActionResult Create()
		{
			return View();
		}

        [Authorize(Roles = "Administrator, Developer")]
		[HttpGet]
		[RequireRequestValue("vehicleId")]
		public ActionResult Create(string vehicleId)
		{
			return View(new VehicleServiceViewModel{VehicleId = vehicleId});
		}

		[HttpPost]
		[RequireRequestValue("serviceVehicleId")]
		public ActionResult CreateDriver(string serviceVehicleId)
		{
			return View ("Create", new VehicleServiceViewModel{VehicleId = serviceVehicleId });
		}

		[HttpPost]
		[ActionLog]
		public ActionResult Create(VehicleServiceViewModel viewModel)
		{
			if (ModelState.IsValid)
			{
				var vehicleService = viewModel.GetVehicleService();

				vehicleService.Vehicle = DataService.GetVehicle(viewModel.VehicleId);
				DataService.AddVehicleService(vehicleService);

				SetStatusMessage(
					string.Format("Vehicle Service for vehicle {0} created", viewModel.VehicleId), StatusType.Success);
				return RedirectToAction("UpdateServiceReminders", new {vehicleId = viewModel.VehicleId});
			}

			return View(viewModel);
		}

		[HttpGet]
		public ActionResult UpdateServiceReminders(string vehicleId)
		{
			var vehicle = DataService.GetVehicle(vehicleId);

			var viewModel = new UpdateServiceRemindersViewModel { VehicleId = vehicleId };

			RefreshServiceReminderViewModel(viewModel, vehicle, true);

			if (vehicle.CurrentOdometer.HasValue)
				viewModel.TargetOdometer = vehicle.CurrentOdometer.Value + DataService.ServiceReminderDefaultMileageDelta;

			return View(viewModel);
		}

		[HttpPost]
		[ActionLog]
		public ActionResult UpdateServiceReminders(UpdateServiceRemindersViewModel viewModel)
		{
			var vehicle = DataService.GetVehicle(viewModel.VehicleId);

			RefreshServiceReminderViewModel(viewModel, vehicle); // this data doesn't get posted back

			if (ModelState.IsValid)
			{
				var serviceReminder = viewModel.GetServiceReminder();

				var status = new List<string>();

				// handle the new service reminder
				if (serviceReminder != null)
				{
					serviceReminder.Vehicle = vehicle;

					DataService.AddServiceReminder(serviceReminder);
					status.Add(string.Format("Service Reminder at {0} miles created", viewModel.TargetOdometer));
				}

				// handle any deletion
				if (viewModel.DeleteServiceReminders != null
					&& viewModel.DeleteServiceReminders.Selected != null
					&& viewModel.DeleteServiceReminders.Selected.Length > 0)
				{
					var serviceReminders =
						(from sr in vehicle.ServiceReminders
						 select new { format = UpdateServiceRemindersViewModel.FormatServiceReminder(sr), id = sr.ServiceReminderId })
							.ToDictionary(o => o.format);

					foreach (var selected in viewModel.DeleteServiceReminders.Selected)
					{
						DataService.DeleteServiceReminder(serviceReminders[selected].id);
					}
					status.Add(string.Format("Selected {0} service reminders deleted", viewModel.DeleteServiceReminders.Selected.Count()));
				}

				if (status.Count > 0)
				{
					SetStatusMessage(string.Join(", ", status), StatusType.Success);
				}

                if (User.IsInRole("Administrator") || User.IsInRole("Developer"))
                {
                    return RedirectToAction("Index");
                }

                return RedirectToAction("Index", "CreateLog"); // for the drivers
            }

			return View(viewModel);
		}

        [Authorize(Roles = "Administrator, Developer")]
		private void RefreshServiceReminderViewModel(
			UpdateServiceRemindersViewModel viewModel, Vehicle vehicle, bool setDefaultSelectedServiceReminders = false)
		{
			if (viewModel.DeleteServiceReminders == null)
				viewModel.DeleteServiceReminders = new CheckBoxViewModel();

			var existingServiceReminders =
				(from sr in vehicle.ServiceReminders
				 select UpdateServiceRemindersViewModel.FormatServiceReminder(sr)).ToArray();

			viewModel.DeleteServiceReminders.Available = existingServiceReminders;
			viewModel.CurrentOdometer = vehicle.CurrentOdometer;

			if (vehicle.CurrentOdometer.HasValue && setDefaultSelectedServiceReminders)
			{
				viewModel.DeleteServiceReminders.Selected =
					(from sr in vehicle.ServiceReminders
					 where sr.TargetOdometer <= vehicle.CurrentOdometer.Value
					 select UpdateServiceRemindersViewModel.FormatServiceReminder(sr)).ToArray();
			}
		}

        [Authorize(Roles = "Administrator, Developer")]
		public ActionResult Edit(int id)
		{
			var vehicleService = DataService.GetVehicleService(id);
			var viewModel = new VehicleServiceViewModel(vehicleService);
			return View(viewModel);
		}

        [Authorize(Roles = "Administrator, Developer")]
		public ActionResult Delete(int id)
		{
			var vehicleService = DataService.GetVehicleService(id);
			var viewModel = new VehicleServiceViewModel(vehicleService);
			return View(viewModel);
		}

        [Authorize(Roles = "Administrator, Developer")]
		[HttpPost, ActionName("Delete")]
		[ActionLog]
		public ActionResult DeleteConfirmed(int id)
		{
			DataService.DeleteVehicleService(id);

			SetStatusMessage("Vehicle Service deleted");
			return RedirectToAction("Index");
		}

        [Authorize(Roles = "Administrator, Developer")]
		[HttpPost]
		[ActionLog]
		public ActionResult Edit(VehicleServiceViewModel viewModel)
		{
			if (ModelState.IsValid)
			{
				var vehicleService = viewModel.GetVehicleService();
				vehicleService.Vehicle = DataService.GetVehicle(viewModel.VehicleId);

				DataService.UpdateVehicleService(vehicleService);
				SetStatusMessage("Changes saved for vehicle service " + vehicleService.Vehicle.VehicleId);
				return RedirectToAction("Details", new { id = vehicleService.VehicleServiceId });
			}
			return View(viewModel);
		}

		public JsonResult ServiceCenterNameAutocomplete(string term)
		{
			var names = DataService.GetServiceCenterNamesAutocomplete(term);
			return Json(names, JsonRequestBehavior.AllowGet);
		}
	
		[ActionLog]
		[Authorize(Roles = "Developer")]
		public ActionResult SendVehicleServiceReminderEmails()
		{
			var emailService = new ServiceReminderEmailService();
			emailService.SendAllNotificationEmails();
			SetStatusMessage("Vehicle Service Reminders Sent");
			return Redirect(Request.UrlReferrer.ToString());
		}
	}
}