using System;
using System.Linq;
using System.Web.Mvc;
using MileageTraker.Web.Attributes;
using MileageTraker.Web.DAL;
using MileageTraker.Web.Utility;
using MileageTraker.Web.ViewModels;
using MileageTraker.Web.ViewModels.Log;
using MileageTraker.Web.ViewModels.Vehicle;

namespace MileageTraker.Web.Controllers
{
	[Authorize(Roles = "Administrator, Developer")]
	public class LogController : ControllerBase
    {
        public ViewResult Index(LogQueryViewModel query)
        {
			var logs = DataService.GetLogs();

			var validLogYears = DataService.GetValidLogYears().ToList();
			if (!validLogYears.Any())
				return View("Empty");
        	if (!query.Year.HasValue)
				query.Year = validLogYears.FirstOrDefault();

			var validLogMonths = DataService.GetValidLogMonths(query.Year.Value).ToList();
			if (!query.Month.HasValue)
				query.Month = validLogMonths.FirstOrDefault();

        	var filteredLogs = 
				from log in DataService.GetLogIndexViewModels(DataService.FilterLogs(logs, query))
				orderby log.Created descending 
				select log;
			
        	var viewModel = 
				new LogResultsViewModel
					{
						Logs = filteredLogs, 
						Years = validLogYears,
						Months = validLogMonths,
						SelectedYear = query.Year.Value,
						SelectedMonth = query.Month.Value,
						SelectedLogType = query.LogType.ToString()
					};

			Session.Add("LogPage", Request.Url.PathAndQuery);

			return View(viewModel);
        }

		[ActionLog]
		public ActionResult Export(LogQueryViewModel query)
		{
			var logs = DataService.GetLogs();
			var filteredLogs =
				DataService.GetLogIndexViewModels(
					DataService.FilterLogs(logs, query)
				           ).ToList();

			var name = string.Format(
				"MileageLogs{0}-{1}{2}",
				query.Year,
				query.Month,
				query.LogType.HasValue ? "-" + query.LogType.Value.GetDisplayShortName() : "");

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

		public ViewResult MonthlyVehicleMileage(LogQueryViewModel query)
		{
			var items = DataService.GetMonthlyVehicleMileageItems(query);

			var report = new VehicleMileageViewModel (items, query);

			return View(report);
		}

		public ActionResult MonthlyDriverMileage(LogQueryViewModel query)
		{
			var items = DataService.GetMonthlyDriverMileageItems(query);
			items = items.OrderBy(i => i.DriverName);

			var report = new DriverMileageViewModel(items, query);

			return View(report);
		}

		public ViewResult Details(int id)
        {
			var log = DataService.GetLog(id);
			var viewModel = new LogViewModel(log)
				{
					Purpose = {Available = GetPurposeTypesSelectList()}
				};
			return View(viewModel);
        }
		
		public ActionResult PreviousDetails(int id)
        {
			var log = DataService.GetLog(id);
			int logId;
			if (log.VehiclePreviousLog != null)
			{
				logId = log.VehiclePreviousLog.LogId;
			}
			else
			{
				logId = id;
				TempData["StatusMessage"] = "This is the first log for this vehicle";
			}
			return RedirectToAction("Details", new {id = logId});
        }

		public ActionResult NextDetails(int id)
		{
			var nextLog = DataService.GetNextLog(id);
			int logId;
			if (nextLog != null)
			{
				logId = nextLog.LogId;
			}
			else
			{
				logId = id;
				TempData["StatusMessage"] = "This is the most recent log for this vehicle";
			}
			return RedirectToAction("Details", new { id = logId });
		}

		[HttpGet]
		public ActionResult Create(string vehicleId)
		{
			var viewModel = new LogViewModel
				{
					Date = DateTime.Today,
					VehicleId = vehicleId,
					Purpose = {Available = GetPurposeTypesSelectList()},
				};

			return View(viewModel);
		} 

        [HttpPost]
		[ActionLog]
		public ActionResult Create(LogViewModel viewModel)
        {
			if (ModelState.IsValid)
			{
				var log = viewModel.GetLog();
				log.User = DataService.FindUserByFullName(viewModel.UserFullName);
				log.Source = HttpContext.Request.Url.AbsolutePath;
				log.UserHostAddress = HttpContext.Request.UserHostAddress;
				log.UserAgent = HttpContext.Request.UserAgent;

				if (viewModel.Purpose != null)
					log.Purpose =
						DataService.GetPurposeTypes()
						.First(pt => pt.PurposeTypeId == viewModel.Purpose.Selected);

				DataService.AddLog(log);

				TempData["StatusMessage"] = "Log created";
                return RedirectToAction("Index");  
            }

	        viewModel.Purpose.Available = GetPurposeTypesSelectList();
            return View(viewModel);
        }

		public ActionResult Edit(int id)
        {
			var log = DataService.GetLog(id);
			var viewModel = new LogViewModel(log)
				{
					Purpose = {Available = GetPurposeTypesSelectList()}
				};
			return View(viewModel);
        }

		[HttpPost]
		[ActionLog]
		public ActionResult Edit(LogViewModel viewModel)
        {
        	if (ModelState.IsValid)
            {
	            var log = DataService.GetLog(viewModel.LogId);
				viewModel.SetProperties(log);
				log.User = DataService.FindUserByFullName(viewModel.UserFullName);

				if (viewModel.Purpose != null)
					log.Purpose =
						DataService.GetPurposeTypes()
						.First(pt => pt.PurposeTypeId == viewModel.Purpose.Selected);
				
				DataService.UpdateLog(log);

	            TempData["StatusMessage"] = "Log updated";
                return RedirectToAction("Details", new{id = log.LogId});
            }

			viewModel.Purpose.Available = GetPurposeTypesSelectList();
			return View(viewModel);
        }

		public ActionResult Delete(int id)
        {
        	var log = DataService.GetLog(id);
			var viewModel = new LogViewModel(log)
				{
					Purpose = {Available = GetPurposeTypesSelectList()}
				};
			return View(viewModel);
        }

		[HttpPost, ActionName("Delete")]
		[ActionLog]
		public ActionResult DeleteConfirmed(int id)
        {            
            DataService.DeleteLog(id);

			TempData["StatusMessage"] = "Log deleted";
			if (Session["LogPage"] != null)
				return Redirect((string) Session["LogPage"]);
            return RedirectToAction("Index");
        }

		public JsonResult GetValidLogMonths(int year)
		{
			var validLogMonths = DataService.GetValidLogMonths(year);
			return Json(validLogMonths, JsonRequestBehavior.AllowGet);
		}

		public PartialViewResult DetailsPartial(int id)
		{
			var log = DataService.GetLog(id);
			return PartialView(new LogPartialDetails(log));
		}
	}
}