/// <summary>
        /// Create a new Inspection report item
        /// </summary>
        /// <param name="parameters">Parameters to save the information</param>
        public static Guid AddInspectionReport(ParameterSaveInspectionReport parameters)
        {
            Guid inspectionReportId = GetInspectionReportByName(parameters.InspectionReportName, parameters.ServiceOrderId).InspectionReportId;
            Fields fieldBusinessApplication = CacheHandler.Get(String.Format("Field{0}", parameters.BusinessApplicationId),
                                            () => DynamicFormEngine.GetFields(parameters.BusinessApplicationId));

            string fieldName = string.Empty;
            string valData = string.Empty;
            Guid inspectionReportItemId = Guid.NewGuid();
            InspectionReportItem inspectionReportItem = null;
            using (VestalisEntities context = new VestalisEntities())
            {
                inspectionReportItem = new InspectionReportItem
                {
                    InspectionReportId = inspectionReportId,
                    StatusCode = ConstantApplication.InspectionReportPendingPublish,
                    CreationBy = parameters.UserName,
                    CreationDate = DateTime.UtcNow,
                    InspectionReportItemId = inspectionReportItemId
                };
                context.InspectionReportItems.AddObject(inspectionReportItem);

                AddApprovalItem(parameters, inspectionReportItemId, context, inspectionReportItem);

                foreach (var formCollectionValue in parameters.FormCollection.Keys)
                {
                    fieldName = formCollectionValue.ToString();
                    ValueProviderResult val = parameters.FormCollection.GetValue(fieldName);
                    if (val != null)
                    {
                        //Get the form value for the specific field
                        valData = val.AttemptedValue.ToString();
                        if (!String.IsNullOrEmpty(valData))
                        {
                            //Set the form value
                            FormValue formValue = SetFormValueToInspectionReport(parameters, inspectionReportItemId, fieldName, valData,
                                                                          fieldBusinessApplication);
                            //Add the form value to the context
                            context.FormValues.AddObject(formValue);
                        }
                    }
                }
                context.SaveChanges();
            }
            return inspectionReportItem.InspectionReportItemId;
        }
        public ActionResult SaveInspectionReport(FormCollection collection)
        {
            if (collection.AllKeys.Contains("serviceOrderId")) collection.Remove("serviceOrderId");
            InspectionReportModel model = Session["frmNewInspection"] as InspectionReportModel;
            Guid serviceOrderReportId = new Guid(Session["serviceOrderReportId"].ToString());
            Guid businessApplicationId = new Guid(Convert.ToString(Session["BusinessAplicationId"]));
            Guid inspectionReportItemId = Guid.Empty;
            string publishValidate = string.Empty;
            string myuploader = string.Empty;
            //validate form and business rules
            if (model.ScreenOpenMode != ScreenOpenMode.View)
            {
                ValidateForm(model.FormDefinition, collection);
                ValidateBusinessRules(model.FormDefinition, collection);
            }
            if (ModelState.IsValid)
            {
                //if publish or validate button is clicked, take the value and remove the key from the collection
                if (collection.AllKeys.Contains("PublishValidateOption") && !string.IsNullOrEmpty(collection["PublishValidateOption"]))
                    publishValidate = collection["PublishValidateOption"];
                collection.Remove("PublishValidateOption");

                if(collection.AllKeys.Contains("UploadLib_Uploader_js"))
                    collection.Remove("UploadLib_Uploader_js");

                if (collection.AllKeys.Contains("__RequestVerificationToken"))
                    collection.Remove("__RequestVerificationToken");

                if (collection.AllKeys.Contains("myuploader"))
                {
                    myuploader = collection["myuploader"].ToString();
                    collection.Remove("myuploader");
                }

                //Set parameters for the method
                ParameterSaveInspectionReport parameters = new ParameterSaveInspectionReport
                {
                    BusinessApplicationId = businessApplicationId,
                    FormCollection = collection,
                    InspectionReportName = model.GridColumns.FormName,
                    ServiceOrderId = serviceOrderReportId,
                    UserName = UserName,
                    RolesForUser = Roles.GetRolesForUser(UserName).ToList(),
                    IsClient = User.IsInRole("Client")
                };
                if (model.ScreenOpenMode == ScreenOpenMode.Add)
                   inspectionReportItemId =  InspectionReportBusiness.AddInspectionReport(parameters);
                else if (model.ScreenOpenMode == ScreenOpenMode.Edit)
                {
                    inspectionReportItemId = new Guid(Session["inspectionReportItemId"].ToString());
                    parameters.InspectionReportItemId = inspectionReportItemId;

                    //perform edit operation
                    InspectionReportBusiness.EditInspectionReport(parameters);
                    //publish or validate inspection report item
                    if (!string.IsNullOrEmpty(publishValidate))
                        InspectionReportBusiness.PublishValidateInspectionReport(inspectionReportItemId, UserName);

                }
                else if (model.ScreenOpenMode == ScreenOpenMode.View && !string.IsNullOrEmpty(publishValidate) && publishValidate == "UnPublish")
                {
                    //Get the id of inspection report item
                    inspectionReportItemId = new Guid(Session["inspectionReportItemId"].ToString());
                    //Perform unpublish operation
                    InspectionReportBusiness.UnPublishInspectionReport(inspectionReportItemId, UserName, Roles.GetRolesForUser(UserName).ToList());
                }
                else if (model.ScreenOpenMode == ScreenOpenMode.View && !string.IsNullOrEmpty(publishValidate) && (publishValidate == "Publish" || publishValidate == "Validate"))
                {
                    //Get the id of inspection report item
                    inspectionReportItemId = new Guid(Session["inspectionReportItemId"].ToString());
                    //Perform unpublish operation
                    InspectionReportBusiness.PublishValidateInspectionReport(inspectionReportItemId, UserName);
                }

                if (!string.IsNullOrEmpty(myuploader) && model.ScreenOpenMode == ScreenOpenMode.Add)
                {
                    using (CuteWebUI.MvcUploader uploader = new CuteWebUI.MvcUploader(System.Web.HttpContext.Current))
                    {
                        if (!string.IsNullOrEmpty(myuploader))
                        {
                            List<string> processedfiles = new List<string>();
                            //for multiple files , the value is string : guid/guid/guid
                            foreach (string strguid in myuploader.Split('/'))
                            {
                                //for single file , the value is guid string
                                Guid fileguid = new Guid(strguid);
                                CuteWebUI.MvcUploadFile file = uploader.GetUploadedFile(fileguid);
                                if (file != null)
                                {
                                    //Save the picture in the database
                                    PictureDocumentBusiness.UploadPicture(file, serviceOrderReportId, UserName, inspectionReportItemId);
                                    processedfiles.Add(file.FileName);
                                    file.Delete();
                                }
                            }
                            if (processedfiles.Count > 0)
                                ViewData["UploadedMessage"] = string.Join(",", processedfiles.ToArray()) + " have been processed.";
                        }
                    }
                }

                return RedirectToAction("ChangeReport", "InspectionReport");
            }
            else
            {
                return View("InspectionReport", model);
            }
        }
        private static void EditApprovalItem(ParameterSaveInspectionReport parameters)
        {
            using (VestalisEntities context = new VestalisEntities())
            {
                InspectionReportItem inspectionReportItem = context.InspectionReportItems.FirstOrDefault(data => data.InspectionReportItemId == parameters.InspectionReportItemId);
                List<ValidationRole> roles = null;
                ValidationRole userRole = null;
                List<ApprovalItem> approvalItems = null;
                ApprovalItem approvalItem = null;
                bool isRole1Completed = false;

                if (inspectionReportItem != null)
                {
                    int currentApprovalLevel = inspectionReportItem.CurrentCompletedLevel.GetValueOrDefault();

                    userRole = (from role in context.ValidationRoles
                                where role.BusinessApplicationId == parameters.BusinessApplicationId
                                && role.IsDeleted == false && parameters.RolesForUser.Contains(role.RoleName)
                                select role).FirstOrDefault();

                    if (userRole.RoleLevel == 1)
                    {

                        roles = (from role in context.ValidationRoles
                                 where role.BusinessApplicationId == parameters.BusinessApplicationId
                                 && role.IsDeleted == false
                                 orderby role.RoleLevel
                                 select role).ToList();

                        approvalItems = (from appItems in context.ApprovalItems
                                         where appItems.InspectionReportItemId == parameters.InspectionReportItemId
                                         && appItems.IsDeleted == false
                                         select appItems).ToList();

                    }
                    else
                    {
                        roles = (from role in context.ValidationRoles
                                 where role.BusinessApplicationId == parameters.BusinessApplicationId
                                 && role.IsDeleted == false && role.RoleLevel >= currentApprovalLevel
                                 orderby role.RoleLevel
                                 select role).ToList();

                        approvalItems = (from appItems in context.ApprovalItems
                                         where appItems.InspectionReportItemId == parameters.InspectionReportItemId
                                         && appItems.IsDeleted == false && appItems.ApprovalLevel >= currentApprovalLevel
                                         select appItems).ToList();

                    }

                    foreach (ApprovalItem appItem in approvalItems)
                    {
                        appItem.IsDeleted = true;
                        appItem.ModificationBy = parameters.UserName;
                        appItem.ModificationDate = DateTime.UtcNow;
                    }

                    foreach (ValidationRole role in roles)
                    {
                        approvalItem = new ApprovalItem
                        {
                            ApprovalLevel = role.RoleLevel,
                            CanPublish = role.CanPublish,
                            CreationBy = parameters.UserName,
                            CreationDate = DateTime.UtcNow,
                            InspectionReportItemId = parameters.InspectionReportItemId,
                            IsReadOnly = role.IsReadOnly,
                            RoleName = role.RoleName,
                            ApprovalStatus = (int)ApprovalStatus.Waiting
                        };
                        if (role.RoleLevel == 1)
                        {
                            if (!role.CanPublish.GetValueOrDefault())
                            {
                                approvalItem.ApprovalStatus = (int)ApprovalStatus.Completed;
                                inspectionReportItem.CurrentCompletedLevel = 1;
                                inspectionReportItem.ModificationBy = parameters.UserName;
                                inspectionReportItem.ModificationDate = DateTime.UtcNow;
                                isRole1Completed = true;
                            }
                            else
                            {
                                approvalItem.ApprovalStatus = (int)ApprovalStatus.Ready;
                                isRole1Completed = false;
                            }

                        }
                        else if (isRole1Completed && role.RoleLevel == 2)
                        {
                            approvalItem.ApprovalStatus = (int)ApprovalStatus.Ready;
                        }
                        else if (role.RoleLevel == currentApprovalLevel)
                        {
                            approvalItem.ApprovalStatus = (int)ApprovalStatus.Ready;
                            inspectionReportItem.CurrentCompletedLevel = (currentApprovalLevel - 1);
                            inspectionReportItem.ModificationBy = parameters.UserName;
                            inspectionReportItem.ModificationDate = DateTime.UtcNow;
                        }
                        context.ApprovalItems.AddObject(approvalItem);
                    }
                }
                context.SaveChanges();
            }
        }
        /// <summary>
        /// Add approval items
        /// </summary>
        /// <param name="parameterSaveInspectionReport">parameterSaveInspectionReport</param>
        /// <param name="inspectionReportItemId">inspectionReportItemId</param>
        /// <param name="context">Data base context</param>
        /// <param name="inspectionReportItem">inspectionReportItem</param>
        private static void AddApprovalItem(ParameterSaveInspectionReport parameterSaveInspectionReport, Guid inspectionReportItemId, VestalisEntities context, InspectionReportItem inspectionReportItem)
        {
            ApprovalItem approvalItem = null;

            List<ValidationRole> roles = (from role in context.ValidationRoles
                                          where role.BusinessApplicationId == parameterSaveInspectionReport.BusinessApplicationId
                                          && role.IsDeleted == false
                                          select role).ToList();

            foreach (ValidationRole role in roles)
            {
                approvalItem = new ApprovalItem
                {
                    ApprovalLevel = role.RoleLevel,
                    CanPublish = role.CanPublish,
                    CreationBy = parameterSaveInspectionReport.UserName,
                    CreationDate = DateTime.UtcNow,
                    InspectionReportItemId = inspectionReportItemId,
                    IsReadOnly = role.IsReadOnly,
                    RoleName = role.RoleName,
                    ApprovalStatus = (int)ApprovalStatus.Waiting
                };
                if (role.RoleLevel == 1)
                {
                    if (!role.CanPublish.GetValueOrDefault())
                    {
                        approvalItem.ApprovalStatus = (int)ApprovalStatus.Completed;
                        inspectionReportItem.CurrentCompletedLevel = 1;
                    }
                    else
                    {
                        approvalItem.ApprovalStatus = (int)ApprovalStatus.Ready;
                    }
                }
                if (role.RoleLevel == 2)
                {
                    approvalItem.ApprovalStatus = (int)ApprovalStatus.Ready;
                }
                context.ApprovalItems.AddObject(approvalItem);
            }
        }
        /// <summary>
        /// Create a FormValue according each value entered in the form by the user. It is convert to the appropiated data type according the field type
        /// </summary>
        /// <param name="parameterSaveInspectionReport">Class parameter</param>
        /// <param name="inspectionReportItemId">Id of inspection report item</param>
        /// <param name="fieldName">Field name</param>
        /// <param name="valData">Val data</param>
        /// <param name="fieldBusinessApplication">Fields obtained from the XML </param>
        /// <returns>Form value to be inserted in the database</returns>
        private static FormValue SetFormValueToInspectionReport(ParameterSaveInspectionReport parameterSaveInspectionReport, Guid inspectionReportItemId,
            string fieldName, string valData, Fields fieldBusinessApplication)
        {
            FormValue formValue = new FormValue();
            formValue.ServiceOrderId = parameterSaveInspectionReport.ServiceOrderId;
            formValue.InspectionReportItemId = inspectionReportItemId;
            formValue.FieldName = fieldName;

            Field field = fieldBusinessApplication.Items.Single(x => x.FieldName == fieldName);

            if (field is FieldsSingleTextLineField)
            {
                formValue.FieldType = (int)FieldType.SingleTextLine;
                formValue.TextValue = valData;
            }
            else if (field is FieldsDatepickerField)
            {
                formValue.FieldType = (int)FieldType.Datepicker;
                string[] dateValue = valData.Split(new[] { '-', '/' });
                if (dateValue.Length > 1)
                    formValue.DateValue = new DateTime(int.Parse(dateValue[2]), int.Parse(dateValue[1]), int.Parse(dateValue[0]));
            }
            else if (field is FieldsDecimalField)
            {
                formValue.FieldType = (int)FieldType.Decimal;
                formValue.DecimalValue = Convert.ToDecimal(valData);
            }
            else if (field is FieldsIntegerField)
            {
                formValue.FieldType = (int)FieldType.Integer;
                formValue.IntegerValue = Convert.ToInt32(valData);
            }
            else if (field is FieldsMultipleTextLineField)
            {
                formValue.FieldType = (int)FieldType.MultipleTextLine;
                formValue.TextValue = valData;
            }
            else if (field is FieldsRegularExpressionTextField)
            {
                formValue.FieldType = (int)FieldType.RegularExpressionText;
                formValue.TextValue = valData;
            }
            else if (field is FieldsTimeField)
            {
                formValue.FieldType = (int)FieldType.Time;
                formValue.TextValue = valData;
            }
            else if (field is FieldsUserField)
            {
                formValue.FieldType = (int)FieldType.User;
                formValue.UserName = valData;
            }
            else if (field is FieldsBooleanField)
            {
                formValue.FieldType = (int)FieldType.Boolean;
                if (valData == "on")
                {
                    formValue.CheckValue = true;
                }
            }
            else if (field is FieldsCatalogueField)
            {
                formValue.FieldType = (int)FieldType.Catalogue;
                formValue.CatalogueValueId = new Guid(valData);
            }
            else if (field is FieldsAutoCompleteTextField)
            {
                formValue.FieldType = (int)FieldType.AutoComplete;
                formValue.TextValue = valData;
            }
            formValue.CreationBy = parameterSaveInspectionReport.UserName;
            formValue.CreationDate = DateTime.UtcNow;
            formValue.ModificationBy = parameterSaveInspectionReport.UserName;
            formValue.ModificationDate = DateTime.UtcNow;
            return formValue;
        }
        /// <summary>
        /// Insert the edited values of the inspection report
        /// </summary>
        /// <param name="parameters">Inspection report parameters</param>
        /// <param name="context">EF Context</param>
        /// <param name="formCollectionValue"></param>
        /// <param name="fieldBusinessApplication"></param>
        private static void SetFieldValuesEditInspection(ParameterSaveInspectionReport parameters, VestalisEntities context, object formCollectionValue, Fields fieldBusinessApplication)
        {
            string fieldName;
            string valData;
            fieldName = formCollectionValue.ToString();
            ValueProviderResult val = parameters.FormCollection.GetValue(fieldName);
            //Get the form value of the service order according the field name
            FormValue formValueToEdit = (from formValues in context.FormValues
                                         where
                                             formValues.ServiceOrderId == parameters.ServiceOrderId &&
                                             formValues.InspectionReportItemId == parameters.InspectionReportItemId &&
                                             formValues.IsDeleted == false &&
                                             formValues.FieldName == fieldName
                                         select formValues).FirstOrDefault();

            if (val != null)
            {
                //Get the form value for the specific field
                valData = val.AttemptedValue.ToString();

                if (!String.IsNullOrEmpty(valData))
                {
                    if (formValueToEdit != null)
                    {
                        SetFormValueToEditInspectionReport(formValueToEdit, valData, parameters.UserName);
                    }
                    else
                    {
                        //Set the form value
                        FormValue formValue = SetFormValueToInspectionReport(parameters, parameters.InspectionReportItemId, fieldName,
                                                                             valData,
                                                                             fieldBusinessApplication);
                        //Add the form value to the context
                        context.FormValues.AddObject(formValue);
                    }
                }
                //Case this field had a value in the past, but the user has updated now without value
                else if (formValueToEdit != null)
                {
                    formValueToEdit.IsDeleted = true;
                    formValueToEdit.ModificationBy = parameters.UserName;
                    formValueToEdit.ModificationDate = DateTime.UtcNow;
                }
            }
        }
        /// <summary>
        /// Save the service order in the database
        /// </summary>
        /// <param name="parameters">Inspection report parameters</param>
        public static void EditInspectionReport(ParameterSaveInspectionReport parameters)
        {
            IList<string> keyNames = new List<string>();
            //Get the fields definition for the business application
            Fields fieldBusinessApplication = CacheHandler.Get(String.Format("Field{0}", parameters.BusinessApplicationId),
                                            () => DynamicFormEngine.GetFields(parameters.BusinessApplicationId));

            using (VestalisEntities context = new VestalisEntities())
            {
                //Get the form values inserted in the database but they aren't in formCollection.Keys
                foreach (var formCollectionValue in parameters.FormCollection.Keys)
                {
                    keyNames.Add(formCollectionValue.ToString());
                }

                var formsNotSent = (from formValues in context.FormValues
                                    where
                                        formValues.ServiceOrderId == parameters.ServiceOrderId &&
                                        formValues.InspectionReportItemId == parameters.InspectionReportItemId &&
                                        formValues.IsDeleted == false &&
                                        !keyNames.Contains(formValues.FieldName)
                                    select formValues);

                foreach (var formNotSent in formsNotSent)
                {
                    formNotSent.IsDeleted = true;
                    formNotSent.ModificationBy = parameters.UserName;
                    formNotSent.ModificationDate = DateTime.UtcNow;
                }

                //For each field form
                foreach (var formCollectionValue in parameters.FormCollection.Keys)
                {
                    SetFieldValuesEditInspection(parameters, context, formCollectionValue, fieldBusinessApplication);
                }
                context.SaveChanges();
            }

            EditApprovalItem(parameters);
        }