/// <summary>
        /// Handles the SaveClick event of the mdWorkflowDetails control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected void mdWorkflowDetails_SaveClick(object sender, EventArgs e)
        {
            var rockContext       = new RockContext();
            var triggerType       = ddlTriggerType.SelectedValueAsEnum <BenevolenceWorkflowTriggerType>();
            var workflowQualifier = $"|{ddlPrimaryQualifier.SelectedValue}|{ddlSecondaryQualifier.SelectedValue}|";

            int workflowTypeId = wpWorkflowType.SelectedValueAsId().Value;
            var workflowType   = new WorkflowTypeService(rockContext).Get(workflowTypeId);

            var findWorkFlow = rockContext.BenevolenceWorkflows?.FirstOrDefault(w => w.BenevolenceTypeId == benevolenceTypeIdPageParameter
                                                                                & w.TriggerType == triggerType
                                                                                & w.WorkflowTypeId == workflowTypeId);

            var existingWorkflow = findWorkFlow != null && findWorkFlow.QualifierValue.Md5Hash() == workflowQualifier.Md5Hash();

            if (existingWorkflow)
            {
                DisplayError("That workflow record already exist for this benevolence type.");
                HideDialog();
                return;
            }

            var guid          = hfWorkflowGuid.Value.AsGuid();
            var workflowState = WorkflowStateModel.Where(w => w.Guid.Equals(guid) && !guid.Equals(Guid.Empty)).FirstOrDefault();

            if (workflowState == null)
            {
                workflowState = new BenevolenceWorkflow
                {
                    Guid = guid
                };

                WorkflowStateModel.Add(workflowState);
            }

            if (workflowType != null)
            {
                workflowState.WorkflowTypeId = workflowType.Id;
                workflowState.WorkflowType   = workflowType;
            }

            workflowState.TriggerType    = triggerType;
            workflowState.QualifierValue = workflowQualifier;
            BindWorkflowGrid();
            HideDialog();
        }
        private void LaunchWorkflow(RockContext rockContext, BenevolenceWorkflow benevolenceWorkflow, string name)
        {
            var workflowType = WorkflowTypeCache.Get(benevolenceWorkflow.WorkflowTypeId);

            if (workflowType != null && (workflowType.IsActive ?? true))
            {
                BenevolenceRequest benevolenceRequest = null;
                if (BenevolenceRequestGuid.HasValue)
                {
                    benevolenceRequest = new BenevolenceRequestService(rockContext).Get(BenevolenceRequestGuid.Value);

                    var workflow = Rock.Model.Workflow.Activate(workflowType, name);

                    List <string> workflowErrors;
                    new WorkflowService(rockContext).Process(workflow, benevolenceRequest, out workflowErrors);
                }
            }
        }
        private bool QualifiersMatch(BenevolenceWorkflow workflow, int prevStatusId, int statusId)
        {
            if (prevStatusId == statusId)
            {
                return(false);
            }

            var qualifierParts = (workflow.QualifierValue ?? "").Split(new char[] { '|' });

            bool matches = true;

            if (matches && qualifierParts.Length > 1 && !string.IsNullOrWhiteSpace(qualifierParts[1]))
            {
                var qualifierStatusId = qualifierParts[1].AsIntegerOrNull();
                if (qualifierStatusId.HasValue)
                {
                    matches = qualifierStatusId != 0 && qualifierStatusId == prevStatusId;
                }
                else
                {
                    matches = false;
                }
            }

            if (matches && qualifierParts.Length > 2 && !string.IsNullOrWhiteSpace(qualifierParts[2]))
            {
                var qualifierStatusId = qualifierParts[2].AsIntegerOrNull();
                if (qualifierStatusId.HasValue)
                {
                    matches = qualifierStatusId != 0 && qualifierStatusId == statusId;
                }
                else
                {
                    matches = false;
                }
            }

            return(matches);
        }
        /// <summary>
        /// Initializes the workflow grid.
        /// </summary>
        /// <param name="benevolenceTypeId">The benevolence type identifier.</param>
        private void InitializeWorkflowGrid(int benevolenceTypeId)
        {
            BenevolenceType benevolenceType = null;
            var             rockContext     = new RockContext();

            if (!benevolenceTypeId.Equals(0))
            {
                benevolenceType = new BenevolenceTypeService(rockContext).Get(benevolenceTypeId);
            }

            if (benevolenceType == null)
            {
                benevolenceType = new BenevolenceType {
                    Id = 0
                };
            }

            WorkflowStateModel = new List <BenevolenceWorkflow>();
            foreach (var benevolenceWorkflow in benevolenceType.BenevolenceWorkflows)
            {
                var modelState = new BenevolenceWorkflow
                {
                    Id   = benevolenceWorkflow.Id,
                    Guid = benevolenceWorkflow.Guid,
                    BenevolenceTypeId = benevolenceTypeId,
                    QualifierValue    = benevolenceWorkflow.QualifierValue,
                    TriggerType       = benevolenceWorkflow.TriggerType,
                    WorkflowTypeId    = benevolenceWorkflow.WorkflowTypeId,
                    WorkflowType      = benevolenceWorkflow.WorkflowType
                };

                WorkflowStateModel.Add(modelState);
            }

            gBenevolenceTypeWorkflows.DataKeyNames      = new string[] { "Guid" };
            gBenevolenceTypeWorkflows.Actions.ShowAdd   = true;
            gBenevolenceTypeWorkflows.Actions.AddClick += gBenevolenceTypeWorkflows_Add;
            gBenevolenceTypeWorkflows.GridRebind       += gBenevolenceTypeWorkflows_GridRebind;
        }
        private bool QualifiersMatch(BenevolenceWorkflow workflow, ConnectionState prevState, ConnectionState state)
        {
            if (prevState == state)
            {
                return(false);
            }

            var qualifierParts = (workflow.QualifierValue ?? "").Split(new char[] { '|' });

            bool matches = true;

            if (matches && qualifierParts.Length > 1 && !string.IsNullOrWhiteSpace(qualifierParts[1]))
            {
                matches = qualifierParts[1].AsInteger() == prevState.ConvertToInt();
            }

            if (matches && qualifierParts.Length > 2 && !string.IsNullOrWhiteSpace(qualifierParts[2]))
            {
                matches = qualifierParts[2].AsInteger() == state.ConvertToInt();
            }

            return(matches);
        }
        /// <summary>
        /// Handles the Click event of the btnSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected void btnSave_Click(object sender, EventArgs e)
        {
            Page.Validate();
            BenevolenceType benevolenceType = null;

            using (var rockContext = new RockContext())
            {
                var benevolenceService         = new BenevolenceTypeService(rockContext);
                var benevolenceWorkflowService = new BenevolenceWorkflowService(rockContext);

                var benevolenceTypeId = benevolenceTypeIdPageParameter;

                if (benevolenceTypeId != 0)
                {
                    benevolenceType = benevolenceService.Get(benevolenceTypeId);
                }

                if (benevolenceType == null)
                {
                    // Check for existing
                    var existingBenevolence = benevolenceService.Queryable()
                                              .Where(d => d.Name == tbName.Text)
                                              .FirstOrDefault();

                    if (existingBenevolence != null)
                    {
                        nbDuplicateDevice.Text    = $"A benevolence type already exists with the name '{existingBenevolence.Name}'. Please use a different benevolence type name.";
                        nbDuplicateDevice.Visible = true;
                    }
                    else
                    {
                        benevolenceType = new BenevolenceType();
                        benevolenceService.Add(benevolenceType);
                    }
                }

                if (benevolenceType != null)
                {
                    benevolenceType.Name                 = tbName.Text;
                    benevolenceType.Description          = tbDescription.Text;
                    benevolenceType.RequestLavaTemplate  = ceLavaTemplate.Text;
                    benevolenceType.ShowFinancialResults = cbShowFinancialResults.Checked;
                    benevolenceType.IsActive             = cbIsActive.Checked;

                    // remove any workflows that were removed in the UI
                    var uiWorkflows = WorkflowStateModel.Select(l => l.Guid);

                    foreach (var benevolenceWorkflow in benevolenceType.BenevolenceWorkflows.Where(l => !uiWorkflows.Contains(l.Guid)).ToList())
                    {
                        benevolenceType.BenevolenceWorkflows.Remove(benevolenceWorkflow);
                        benevolenceWorkflowService.Delete(benevolenceWorkflow);
                    }

                    // Add or Update workflows from the UI
                    foreach (var workflowStateModel in WorkflowStateModel)
                    {
                        BenevolenceWorkflow benevolenceWorkflow = benevolenceType.BenevolenceWorkflows
                                                                  .Where(b => !workflowStateModel.Guid.Equals(Guid.Empty) && b.Guid == workflowStateModel.Guid).FirstOrDefault();

                        if (benevolenceWorkflow == null)
                        {
                            benevolenceWorkflow = new BenevolenceWorkflow
                            {
                                BenevolenceTypeId = benevolenceTypeId
                            };
                            benevolenceType.BenevolenceWorkflows.Add(benevolenceWorkflow);
                        }

                        // Set the properties on the state model
                        benevolenceWorkflow.CopyPropertiesFrom(workflowStateModel);
                    }

                    if (!benevolenceType.IsValid)
                    {
                        // Controls will render the error messages
                        return;
                    }

                    rockContext.WrapTransaction(() =>
                    {
                        rockContext.SaveChanges();
                    });

                    BenevolenceWorkflowService.RemoveCachedTriggers();
                    NavigateToParentPage();
                }
            }
        }