//[OutputCache(Duration = 600, 
        //    VaryByParam = "TakeRateParameters.TakeRateId,TakeRateParameters.MarketId,TakeRateParameters.PageSize,TakeRateParameters.PageIndex")]
        //[SiteMapTitle("DocumentName")]
        public ActionResult TakeRateDataPage(TakeRateParameters parameters)
        {
            var filter = TakeRateFilter.FromTakeRateParameters(parameters);
            filter.Action = TakeRateDataItemAction.TakeRateDataPage;
            var model = TakeRateViewModel.GetModel(DataContext, filter).Result;

            var title = string.Format("{0} - {1} ({2}) - {3}", 
                model.Document.Vehicle.Code,
                model.Document.Vehicle.ModelYear, model.Document.UnderlyingOxoDocument.Gateway,
                model.Document.TakeRateSummary.First().Version);
            
            ViewBag.Title = title;

            string displayName;
            if (model.Document.Market is EmptyMarket)
            {
                displayName = string.Format("{0} - ALL MARKETS", title);
            }
            else
            {
                displayName = string.Format("{0} - {1}",
                    title,
                    model.Document.Market.Name.ToUpper());
            }

            ViewData["DocumentName"] = displayName;

            return View("TakeRateDataPage", model);
        }
        public async Task<JsonResult> TakeRateFeatureData(TakeRateParameters parameters)
        {
            Log.Debug(MethodBase.GetCurrentMethod().Name);

            var filter = TakeRateFilter.FromTakeRateParameters(parameters);
            filter.Action = TakeRateDataItemAction.TakeRateDataPage;
            var model = await TakeRateViewModel.GetModel(DataContext, filter);

            var rows = new List<Dictionary<string, object>>();
            foreach (DataRow dr in model.Document.TakeRateData.RawData.Rows)
            {
                var row = new Dictionary<string, object>();
                foreach (DataColumn col in model.Document.TakeRateData.RawData.Columns)
                {
                    row.Add(col.ColumnName, dr[col]);
                }
                rows.Add(row);
            }

            Response.AddHeader("Content-Encoding", "gzip");
            Response.Filter = new GZipStream(Response.Filter,
                                 CompressionMode.Compress);
            
            return Json(new
            {
                FeatureData = rows,
                model.Document.Market
            });
        }
        public async Task<ActionResult> Publish(TakeRateParameters parameters)
        {
            TakeRateParametersValidator
               .ValidateTakeRateParameters(DataContext, parameters, TakeRateParametersValidator.TakeRateIdentifierWithCommentAndMarket);

            var publish = await DataContext.TakeRate.SetPublish(
                TakeRateFilter.FromTakeRateParameters(parameters));

            return Json(publish);
        }
		public async Task<ActionResult> TakeRatePage(TakeRateParameters parameters)
		{
			TakeRateParametersValidator
				.ValidateTakeRateParameters(DataContext, parameters, TakeRateParametersValidator.NoValidation);

			var filter = TakeRateFilter.FromTakeRateParameters(parameters);
			filter.Action = TakeRateDataItemAction.TakeRates;
			var takeRateView = await TakeRateViewModel.GetModel(DataContext, filter);

			return View("TakeRatePage", takeRateView);
		}
 private async Task CheckModelAllowsEdit(TakeRateParameters parameters)
 {
     var filter = TakeRateFilter.FromTakeRateParameters(parameters);
     filter.Action = TakeRateDataItemAction.Publish;
     var takeRateView = await TakeRateViewModel.GetModel(
         DataContext,
         filter);
     if (!takeRateView.AllowEdit)
     {
         throw new InvalidOperationException(NoEdits);
     }
 }
        protected override bool IsValid(PropertyValidatorContext context)
        {
            Parameters = context.ParentContext.InstanceToValidate as TakeRateParameters;
            var changes = context.PropertyValue as IEnumerable<DataChange>;

            if (changes != null)
            {
                return !changes.Any(IsVolumeGreaterThanVolumeForMarket);
            }

            return true;
        }
        //[OutputCacheComplex(typeof(TakeRateParameters))]
        public async Task<ActionResult> PublishConfirm(TakeRateParameters parameters)
        {
            TakeRateParametersValidator
               .ValidateTakeRateParameters(DataContext, parameters, TakeRateParametersValidator.TakeRateIdentifier);

            var filter = TakeRateFilter.FromTakeRateParameters(parameters);
            filter.Action = TakeRateDataItemAction.Publish;
            var takeRateView = await TakeRateViewModel.GetModel(
                DataContext,
                filter);

            return PartialView("_PublishConfirm", takeRateView);
        }
        public async Task<ActionResult> MarketReview(TakeRateParameters parameters)
        {
            TakeRateParametersValidator
               .ValidateTakeRateParameters(DataContext, parameters, TakeRateParametersValidator.TakeRateIdentifierWithCommentAndMarketAndReviewStatus);

            await CheckModelAllowsEdit(parameters);

            var marketReview = await DataContext.TakeRate.SetMarketReview(
                TakeRateFilter.FromTakeRateParameters(parameters));

            if (parameters.MarketReviewStatus == MarketReviewStatus.Approved)
            {
                // Automatically save the changes from the market
                parameters.Comment = "Changes from market review";
                await DataContext.TakeRate.PersistChangeset(TakeRateFilter.FromTakeRateParameters(parameters));
            }

            return Json(marketReview);
        }
        //[OutputCacheComplex(typeof(TakeRateParameters))]
        public async Task<ActionResult> MarketReviewConfirm(TakeRateParameters parameters)
        {
            TakeRateParametersValidator
               .ValidateTakeRateParameters(DataContext, parameters, TakeRateParametersValidator.TakeRateIdentifier);

            var filter = TakeRateFilter.FromTakeRateParameters(parameters);
            filter.Action = TakeRateDataItemAction.MarketReview;
            var takeRateView = await TakeRateViewModel.GetModel(
                DataContext,
                filter);

            if (parameters.MarketReviewStatus == MarketReviewStatus.Recalled)
            {
                takeRateView.MarketReviewStatus = MarketReviewStatus.Recalled;
            }

            takeRateView.Changes = await DataContext.TakeRate.GetUnsavedChangesForUser(filter);

            return PartialView("_MarketReviewConfirm", takeRateView);
        }
		public async Task<ActionResult> ContextMenu(TakeRateParameters parameters)
		{
			try
			{
				TakeRateParametersValidator
					.ValidateTakeRateParameters(DataContext, parameters, TakeRateParametersValidator.TakeRateIdentifier);

				var filter = TakeRateFilter.FromTakeRateParameters(parameters);
				filter.Action = TakeRateDataItemAction.TakeRates;

				var takeRateView = await TakeRateViewModel.GetModel(
					DataContext,
					filter);

				return PartialView("_ContextMenu", takeRateView);
			}
			catch (Exception ex)
			{
				return PartialView("_ModalError");
			}
		}
        public async Task<ActionResult> ListPublish(TakeRateParameters parameters)
        {
            TakeRateParametersValidator
                .ValidateTakeRateParameters(DataContext, parameters, TakeRateParametersValidator.NoValidation);

            var filter = new TakeRateFilter()
            {
                FilterMessage = parameters.FilterMessage,
                Action = TakeRateDataItemAction.Publish
            };
            filter.InitialiseFromJson(parameters);

            var results = await PublishViewModel.GetModel(DataContext, filter);
            var jQueryResult = new JQueryDataTableResultModel(results);

            foreach (var result in results.AvailableFiles.CurrentPage)
            {
                jQueryResult.aaData.Add(result.ToJQueryDataTableResult());
            }

            return Json(jQueryResult);
        }
        private static async void RunAsync()
        {
            const int takeRateId = 2;
            const int marketId = 17;

            var kernel = GetKernel();
            var context = kernel.Get<IDataContext>(new ConstructorArgument("cdsId", "bweston2"));
            var p = new TakeRateParameters
            {
                TakeRateId = takeRateId,
                MarketId = marketId
            };
            var filter = TakeRateFilter.FromTakeRateParameters(p);
            var rawData = context.TakeRate.GetRawData(filter).Result;
            var results = Validator.Validate(rawData);
            
            foreach (var error in results.Errors)
            {
                Console.WriteLine(error.ErrorMessage);
            }

            var persistedResults = Validator.Persist(context, filter, results);
        }
		public async Task<ActionResult> ListTakeRates(TakeRateParameters parameters)
		{
			TakeRateParametersValidator
				.ValidateTakeRateParameters(DataContext, parameters, TakeRateParametersValidator.NoValidation);

			var js = new JavaScriptSerializer();
			var filter = new TakeRateFilter()
			{
				FilterMessage = parameters.FilterMessage,
				TakeRateStatusId = parameters.TakeRateStatusId,
				Action = TakeRateDataItemAction.TakeRates
			};
			filter.InitialiseFromJson(parameters);

			var results = await TakeRateViewModel.GetModel(DataContext, filter);
			var jQueryResult = new JQueryDataTableResultModel(results);

			foreach (var result in results.TakeRates.CurrentPage)
			{
				jQueryResult.aaData.Add(result.ToJQueryDataTableResult());
			}

			return Json(jQueryResult);
		}
        public async Task<ActionResult> ChangesetHistoryDetails(TakeRateParameters parameters)
        {
            TakeRateParametersValidator.ValidateTakeRateParameters(DataContext, parameters, TakeRateParametersValidator.TakeRateIdentifier);

            var filter = TakeRateFilter.FromTakeRateParameters(parameters);
            filter.Action = TakeRateDataItemAction.Changeset;
            var takeRateView = await TakeRateViewModel.GetModel(DataContext, filter);

            takeRateView.History = await DataContext.TakeRate.GetChangesetHistory(filter);
            takeRateView.HistoryDetails = await DataContext.TakeRate.GetChangesetHistoryDetails(filter);

            return PartialView("_ChangesetHistoryDetails", takeRateView);
        }
        //[HandleErrorWithJson]
        //[HttpPost]
        //public async Task<ActionResult> Validate(TakeRateParameters parameters)
        //{
        //    var validationResults = Enumerable.Empty<ValidationResult>();

        //    TakeRateParametersValidator.ValidateTakeRateParameters(DataContext, parameters, TakeRateParametersValidator.TakeRateIdentifier);

        //    var filter = TakeRateFilter.FromTakeRateParameters(parameters);
        //    filter.Action = TakeRateDataItemAction.Validate;
        //    var takeRateView = await TakeRateViewModel.GetModel(DataContext, filter);

        //    try
        //    {
        //        var interimResults = Validator.Validate(takeRateView.RawData);
        //        validationResults = await Validator.Persist(DataContext, filter, interimResults);
        //    }
        //    catch (ValidationException vex)
        //    {
        //        // Just in case someone has thrown an exception from the validation, which we don't actually want
        //        Log.Warning(vex);
        //    }
        //    catch (Exception ex)
        //    {
        //        Log.Error(ex);
        //    }

        //    return JsonGetSuccess(validationResults);
        //}

	    public ActionResult IgnoreValidationError(TakeRateParameters parameters)
	    {
            TakeRateParametersValidator.ValidateTakeRateParameters(DataContext, parameters, TakeRateParametersValidator.TakeRateIdentifier);
	        DataContext.TakeRate.IgnoreValidationError(TakeRateFilter.FromTakeRateParameters(parameters));

	        return RedirectToRoute("TakeRateDataByMarket", new { takeRateId = parameters.TakeRateId, marketId = parameters.MarketId });
	    }
		public async Task<ActionResult> Clone(TakeRateParameters parameters)
		{
			var filter = TakeRateFilter.FromTakeRateParameters(parameters);
			var clone = await DataContext.TakeRate.CloneTakeRateDocument(filter);

			// Revalidate the clone, as the new document may have different feature applicability
			filter = new TakeRateFilter()
			{
				TakeRateId = clone.TakeRateId
			};

			var markets = await DataContext.Market.ListMarkets(filter);
			foreach (var market in markets)
			{
			    try
			    {
			        filter.MarketId = market.Id;
			        var rawData = await DataContext.TakeRate.GetRawData(filter);

			        //var validationResults = Validator.Validate(rawData);
			        //Validator.Persist(DataContext, filter, validationResults);
			    }
			    catch (ValidationException vex)
			    {
			        // Sink the exception, as we don't want any validation errors propagating up
			    }
			    catch (Exception ex)
			    {
			        
			    }
			}
			
			return JsonGetSuccess(clone);
		}
		private async Task<TakeRateViewModel> GetModelFromParameters(TakeRateParameters parameters)
		{
			return await TakeRateViewModel.GetModel(DataContext, TakeRateFilter.FromTakeRateParameters(parameters));
		}
        public void ExportCpat(TakeRateParameters parameters)
        {
            var business = new TakeRateBusiness(DataContext, parameters, false);
            var exportData = business.ExportCpat();
            var fileName = string.Format("TakeRateCpatExport_{0:yyyyMMdd}_{1}.xlsx",
                DateTime.Now,
                parameters.TakeRateId);

            Response.ClearContent();
            Response.Buffer = true;
            Response.AddHeader("content-disposition", "attachment; filename=" + fileName);
            Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";

            using (var stream = new MemoryStream())
            {
                exportData.SaveAs(stream);
                stream.WriteTo(Response.OutputStream);
                Response.Flush();
                Response.End();
            }
        }
		public async Task<ActionResult> ModalAction(TakeRateParameters parameters)
		{
			TakeRateParametersValidator
				.ValidateTakeRateParameters(DataContext, parameters, TakeRateParametersValidator.TakeRateIdentifier);
			TakeRateParametersValidator
				.ValidateTakeRateParameters(DataContext, parameters, Enum.GetName(parameters.Action.GetType(), parameters.Action));

			return RedirectToRoute(Enum.GetName(parameters.Action.GetType(), parameters.Action), parameters.GetActionSpecificParameters());
		}
	    public async Task<ActionResult> PersistChangeset(TakeRateParameters parameters)
	    {
	        TakeRateParametersValidator.ValidateTakeRateParameters(DataContext, parameters,
	            TakeRateParametersValidator.TakeRateIdentifierWithChangesetAndComment);

	        CheckModelAllowsEdit(parameters);

	        var persistedChangeset =
	            await DataContext.TakeRate.PersistChangeset(TakeRateFilter.FromTakeRateParameters(parameters));

	        return Json(persistedChangeset);
	    }
        public void ExportChangeDetails(TakeRateParameters parameters)
        {
            TakeRateParametersValidator.ValidateTakeRateParameters(DataContext, parameters, TakeRateParametersValidator.TakeRateIdentifierWithChangeset);

            var business = new TakeRateBusiness(DataContext, parameters);
            var exportData = business.ExportChangeset();

            Response.ClearContent();
            Response.Buffer = true;
            Response.AddHeader("content-disposition", "attachment; filename=ChangeHistory.xlsx");
            Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";

            using (var stream = new MemoryStream())
            {
                exportData.SaveAs(stream);
                stream.WriteTo(Response.OutputStream);
                Response.Flush();
                Response.End();
            }        
        }
 public async Task<ActionResult> PublishPage(TakeRateParameters parameters)
 {
     var filter = TakeRateFilter.FromTakeRateParameters(parameters);
     return View(await PublishViewModel.GetModel(DataContext, filter));
 }
	    public async Task<ActionResult> PersistChangesetConfirm(TakeRateParameters parameters)
	    {
	        TakeRateParametersValidator.ValidateTakeRateParameters(DataContext, parameters, TakeRateParametersValidator.TakeRateIdentifierWithChangeset);

	        var filter = TakeRateFilter.FromTakeRateParameters(parameters);
	        filter.Action = TakeRateDataItemAction.TakeRateDataItemDetails;
	        var takeRateView = await TakeRateViewModel.GetModel(DataContext, filter);

	        takeRateView.Changes = await DataContext.TakeRate.GetUnsavedChangesForUser(filter);

	        return PartialView("_PersistChangesetConfirm", takeRateView);
	    }
        public async Task<ActionResult> UndoAllChangeset(TakeRateParameters parameters)
        {
            TakeRateParametersValidator.ValidateTakeRateParameters(DataContext, parameters, TakeRateParametersValidator.TakeRateIdentifierWithChangeset);

            var filter = TakeRateFilter.FromTakeRateParameters(parameters);
            filter.Action = TakeRateDataItemAction.Changeset;
            var takeRateView = await TakeRateViewModel.GetModel(DataContext, filter);
            if (!takeRateView.AllowEdit)
            {
                throw new InvalidOperationException(NO_EDITS);
            }
            var undoneChangeset = await DataContext.TakeRate.UndoAllChangeset(TakeRateFilter.FromTakeRateParameters(parameters));

            //// TODO break this out into a separate call, as we want it to return as fast as possible
            //var rawData = await DataContext.TakeRate.GetRawData(filter);
            //var validationResults = Validator.Validate(rawData);
            //var savedValidationResults = await Validator.Persist(DataContext, filter, validationResults);

            return JsonGetSuccess(undoneChangeset);
        }
	    private void CheckModelAllowsEdit(TakeRateParameters parameters)
	    {
	        var filter = TakeRateFilter.FromTakeRateParameters(parameters);
	        filter.Action = TakeRateDataItemAction.Changeset;
	        var takeRateView = TakeRateViewModel.GetModel(DataContext, filter).Result;
	        if (!takeRateView.AllowEdit)
	        {
	            throw new InvalidOperationException(NO_EDITS);
	        }
	    }
	    public async Task<ActionResult> AddNote(TakeRateParameters parameters)
	    {
	        TakeRateParametersValidator.ValidateTakeRateParameters(DataContext, parameters, TakeRateParametersValidator.ModelPlusFeatureAndComment);

	        var filter = TakeRateFilter.FromTakeRateParameters(parameters);
	        filter.Action = TakeRateDataItemAction.AddNote;
	        var takeRateView = TakeRateViewModel.GetModel(DataContext, filter).Result;
	        if (!takeRateView.AllowEdit)
	        {
	            throw new InvalidOperationException(NO_EDITS);
	        }
	        var note = await DataContext.TakeRate.AddDataItemNote(TakeRateFilter.FromTakeRateParameters(parameters));

	        return Json(note, JsonRequestBehavior.AllowGet);
	    }
	    public async Task<ActionResult> GetValidation(TakeRateParameters parameters)
	    {
	        TakeRateParametersValidator.ValidateTakeRateParameters(DataContext, parameters, TakeRateParametersValidator.TakeRateIdentifier);

            var validation = new FdpValidation();

	        if (parameters.MarketId.HasValue)
	        {
	            var business = new TakeRateBusiness(DataContext, parameters);
	            business.ValidateChangeset();

                validation = await DataContext.TakeRate.GetValidation(TakeRateFilter.FromTakeRateParameters(parameters));
	        }

	        return Json(validation);
	    }
	    public async Task<ActionResult> GetValidationSummary(TakeRateParameters parameters)
	    {
            TakeRateParametersValidator.ValidateTakeRateParameters(DataContext, parameters, TakeRateParametersValidator.TakeRateIdentifier);

            var filter = TakeRateFilter.FromTakeRateParameters(parameters);
	        filter.Action = TakeRateDataItemAction.ValidationSummary;
	        var takeRateView = await TakeRateViewModel.GetModel(DataContext, filter);
            var validation = await DataContext.TakeRate.GetValidation(TakeRateFilter.FromTakeRateParameters(parameters));

	        takeRateView.Validation = validation;

            return PartialView("_ValidationSummary", takeRateView);
	    }
		public async Task<ActionResult> ModalContent(TakeRateParameters parameters)
		{
			TakeRateParametersValidator
				.ValidateTakeRateParameters(DataContext, parameters, TakeRateParametersValidator.TakeRateIdentifier);

			var takeRateView = await GetModelFromParameters(parameters);

			return PartialView(GetContentPartialViewName(parameters.Action), takeRateView);
		}
        public async Task<JsonResult> Markets(TakeRateParameters parameters)
        {
            TakeRateParametersValidator.ValidateTakeRateParameters(DataContext, parameters, TakeRateParametersValidator.TakeRateIdentifier);
            var marketsGroups =
                await DataContext.TakeRate.ListAvailableMarketGroups(TakeRateFilter.FromTakeRateParameters(parameters));

            var markets = marketsGroups.SelectMany(mg => mg.Markets).Select(m => new
            {
                m.Name,
                m.GroupName,
                m.VariantCount,
                m.LastUpdated,
                m.UpdatedBy
            });

            return Json(markets, JsonRequestBehavior.AllowGet);
        }