/// <summary>
        /// This method executes when the user clicks the verify button in
        /// the verify code section and it attempts to log the user in with
        /// the code they entered
        /// </summary>
        /// <param name="sender">The btnVerifyCode DevEx button</param>
        /// <param name="e">The Click event</param>
        protected void btnVerifyCode_Click(object sender, EventArgs e)
        {
            //Only continue if the validation is successful
            if (ASPxEdit.AreEditorsValid(this, btnVerifyCode.ValidationGroup))
            {
                //Try to sign the user in
                var result = signinManager.TwoFactorSignIn <PyramidUser, string>(hfSelectedProvider.Value, txtCode.Text, isPersistent: false, rememberBrowser: chkRememberBrowser.Checked);
                switch (result)
                {
                case SignInStatus.Success:
                    //Get the user ID
                    string userID = signinManager.GetVerifiedUserId <PyramidUser, string>();

                    //Get the user
                    var user = manager.FindById(userID);

                    //Get the user's program roles
                    List <UserProgramRole> userProgramRoles;
                    using (PyramidContext context = new PyramidContext())
                    {
                        userProgramRoles = context.UserProgramRole.Where(upr => upr.Username == user.UserName).ToList();
                    }

                    //Redirect the user based on the number of roles they have
                    if (userProgramRoles.Count > 1)
                    {
                        //Redirect the user to the select role page
                        Response.Redirect(String.Format("/Account/SelectRole.aspx?ReturnUrl={0}&message={1}",
                                                        (Request.QueryString["ReturnUrl"] != null ? Request.QueryString["ReturnUrl"].ToString() : "/Default.aspx"),
                                                        "TwoFactorVerified"));
                    }
                    else
                    {
                        //Get the UserProgramRole
                        UserProgramRole programRole = userProgramRoles.FirstOrDefault();

                        //Set the session variables
                        Session["CodeProgramRoleFK"] = programRole.CodeProgramRole.CodeProgramRolePK;
                        Session["ProgramRoleName"]   = programRole.CodeProgramRole.RoleName;
                        Session["ProgramFK"]         = programRole.ProgramFK;
                        Session["ProgramName"]       = programRole.Program.ProgramName;

                        //Redirect the user
                        Response.Redirect(Request.QueryString["ReturnUrl"] != null ? Request.QueryString["ReturnUrl"].ToString() : "/Default.aspx?message=TwoFactorVerified");
                    }
                    break;

                case SignInStatus.LockedOut:
                    Response.Redirect("/Account/Lockout");
                    break;

                case SignInStatus.Failure:
                default:
                    msgSys.ShowMessageToUser("danger", "Invalid Code", "The code you entered is invalid!", 25000);
                    break;
                }
            }
        }
        /// <summary>
        /// This method fires when the user clicks the save button and
        /// it attempts to add a new user to the system with the information
        /// provided on the page
        /// </summary>
        /// <param name="sender">The submitUser control</param>
        /// <param name="e">The Click event</param>
        protected void submitUser_Click(object sender, EventArgs e)
        {
            //Get the user manager
            var manager = Context.GetOwinContext().GetUserManager <ApplicationUserManager>();

            //Create and fill the user object
            PyramidUser newUser = new PyramidUser();

            newUser.FirstName            = txtFirstName.Value.ToString();
            newUser.LastName             = txtLastName.Value.ToString();
            newUser.UserName             = txtUsername.Value.ToString();
            newUser.Email                = txtEmail.Value.ToString();
            newUser.EmailConfirmed       = false;
            newUser.TwoFactorEnabled     = false;
            newUser.PhoneNumber          = (txtPhoneNumber.Value == null ? null : txtPhoneNumber.Value.ToString());
            newUser.PhoneNumberConfirmed = false;

            //Attempt to create the user
            IdentityResult result = manager.Create(newUser, txtPassword.Value.ToString());

            if (result.Succeeded)
            {
                //If the user creation succeeded, send the user an email to confirm their account
                string emailcode   = manager.GenerateEmailConfirmationToken(newUser.Id);
                string callbackUrl = IdentityHelper.GetAccountConfirmationRedirectUrl(emailcode, newUser.Id, Request);
                manager.SendEmail(newUser.Id, "Confirm your account", Utilities.GetEmailHTML(callbackUrl, "Confirm Account", true, "Welcome " + newUser.FirstName + " " + newUser.LastName + "!", "Your user account for the Pyramid Model Implementation Data System was created by an administrator.<br/>Your username for this system is:<br/><br/>" + newUser.UserName + "<br/><br/>Once you confirm your account and create your password, you will be able to start using the system.<br/>To get started, please click the link below.", Request));

                //Add the user to their identity role
                manager.AddToRole(newUser.Id, ddIdentityRole.SelectedItem.Text.ToString());

                //Add the user to their program role
                using (PyramidContext context = new PyramidContext())
                {
                    //Create the UserProgramRole object and fill it
                    UserProgramRole userPrgRole = new UserProgramRole();
                    userPrgRole.CreateDate        = DateTime.Now;
                    userPrgRole.Creator           = User.Identity.Name;
                    userPrgRole.ProgramFK         = Convert.ToInt32(ddProgram.Value);
                    userPrgRole.ProgramRoleCodeFK = Convert.ToInt32(ddProgramRole.Value);
                    userPrgRole.Username          = newUser.UserName;

                    //Add the UserProgramRole to the database and save
                    context.UserProgramRole.Add(userPrgRole);
                    context.SaveChanges();
                }

                //Redirect the user
                Response.Redirect("/Admin/UserManagement?message=CreateUserSuccess");
            }
            else
            {
                msgSys.ShowMessageToUser("danger", "Error", result.Errors.FirstOrDefault(), 120000);
            }
        }
        /// <summary>
        /// This method fires when the user clicks the Remove Role button and
        /// it removes the Program Role from the user
        /// </summary>
        /// <param name="sender">The lbDeleteRole LinkButton</param>
        /// <param name="e">The Click event</param>
        protected void lbDeleteRole_Click(object sender, EventArgs e)
        {
            //Get the calling button
            LinkButton deleteButton = (LinkButton)sender;

            //Get the specific repeater item
            RepeaterItem item = (RepeaterItem)deleteButton.Parent;

            //Get the hidden field with the PK for deletion
            HiddenField hfUserProgramRolePK = (HiddenField)item.FindControl("hfUserProgramRolePK");

            //Get the PK from the hidden field
            int?rowToRemovePK = (String.IsNullOrWhiteSpace(hfUserProgramRolePK.Value) ? (int?)null : Convert.ToInt32(hfUserProgramRolePK.Value));

            //Remove the role if the PK is not null
            if (rowToRemovePK != null)
            {
                using (PyramidContext context = new PyramidContext())
                {
                    //Only remove the role if the user has another role
                    if (context.UserProgramRole.Where(upr => upr.Username == currentUser.UserName).ToList().Count > 1)
                    {
                        //Get the role to remove
                        UserProgramRole roleToRemove = context.UserProgramRole.Where(upr => upr.UserProgramRolePK == rowToRemovePK).FirstOrDefault();
                        context.UserProgramRole.Remove(roleToRemove);
                        context.SaveChanges();

                        //Show the changes
                        BindUserProgramRoles(context, currentUser);

                        //Show a success message
                        msgSys.ShowMessageToUser("success", "Success", "Successfully removed user's program role!", 10000);
                    }
                    else
                    {
                        //Show an error message
                        msgSys.ShowMessageToUser("danger", "Error", "You cannot remove a user's only program role!", 120000);
                    }
                }
            }
            else
            {
                msgSys.ShowMessageToUser("danger", "Error", "An error occurred while attempting to remove the role!", 120000);
            }
        }
        /// <summary>
        /// This method fires when the user clicks the Add Role button and
        /// it adds the selected Program Role to the user
        /// </summary>
        /// <param name="sender">The btnAddRole DevExpress Bootstrap button</param>
        /// <param name="e">The Click event</param>
        protected void btnAddRole_Click(object sender, EventArgs e)
        {
            //Only continue if the page is valid
            if (ASPxEdit.AreEditorsValid(this, btnAddRole.ValidationGroup))
            {
                int programRoleFK, programFK;

                //Get the program role fk and program fk
                programRoleFK = Convert.ToInt32(ddProgramRole.Value);
                programFK     = Convert.ToInt32(ddProgram.Value);

                //Create the object and fill it
                UserProgramRole newUpr = new UserProgramRole();
                newUpr.Creator           = User.Identity.Name;
                newUpr.CreateDate        = DateTime.Now;
                newUpr.ProgramFK         = programFK;
                newUpr.Username          = currentUser.UserName;
                newUpr.ProgramRoleCodeFK = programRoleFK;

                //Add the object to the database
                using (PyramidContext context = new PyramidContext())
                {
                    //Add the role
                    context.UserProgramRole.Add(newUpr);
                    context.SaveChanges();

                    //Show the changes
                    BindUserProgramRoles(context, currentUser);
                }

                //Clear the inputs
                ddProgramRole.Value = "";
                ddProgram.Value     = "";

                //Show a success message
                msgSys.ShowMessageToUser("success", "Success", "Successfully added program role to user!", 10000);
            }
        }
        /// <summary>
        /// This method fires when the user clicks the Login button and it attempts to log
        /// the user in
        /// </summary>
        /// <param name="sender">The btnLogin DevExpress button</param>
        /// <param name="e">The Click event</param>
        protected void btnLogin_Click(object sender, EventArgs e)
        {
            if (ASPxEdit.AreEditorsValid(this, btnLogin.ValidationGroup))
            {
                // Validate the user password
                var manager       = Context.GetOwinContext().GetUserManager <ApplicationUserManager>();
                var signinManager = Context.GetOwinContext().GetUserManager <ApplicationSignInManager>();

                //Try to get the user
                PyramidUser user = manager.FindByName(txtUsername.Text);

                //Make sure that the user is confirmed
                if (user != null && manager.IsEmailConfirmed(user.Id))
                {
                    //Try to sign the user in
                    var result = signinManager.PasswordSignIn(txtUsername.Text, txtPassword.Text, false, user.LockoutEnabled);

                    switch (result)
                    {
                    case SignInStatus.Success:
                        //The user successfully logged in

                        List <UserProgramRole> userProgramRoles;
                        List <spGetUserCustomizationOptions_Result> userCustomizationOptions;
                        using (PyramidContext context = new PyramidContext())
                        {
                            //Get the user's program roles
                            userProgramRoles = context.UserProgramRole.AsNoTracking()
                                               .Include(upr => upr.CodeProgramRole)
                                               .Include(upr => upr.Program)
                                               .Where(upr => upr.Username == txtUsername.Text).ToList();

                            //Get the user's customization options
                            userCustomizationOptions = context.spGetUserCustomizationOptions(txtUsername.Text).ToList();

                            //Keep a record of successful logins
                            LoginHistory history = new LoginHistory();
                            history.Username  = txtUsername.Text;
                            history.LoginTime = DateTime.Now;

                            //If the user only has one program role, record it in the login history
                            if (userProgramRoles.Count == 1)
                            {
                                history.ProgramFK = userProgramRoles.First().ProgramFK;
                                history.Role      = userProgramRoles.First().CodeProgramRole.RoleName;
                            }

                            //Save the login history
                            context.LoginHistory.Add(history);
                            context.SaveChanges();

                            //Save the LoginHistory primary key to the session for later access
                            Session["LoginHistoryPK"] = history.LoginHistoryPK;
                        }

                        //Set the user customization options cookie
                        Utilities.SetCustomizationOptionCookie(userCustomizationOptions);

                        //Redirect the user based on the number of roles they have
                        if (userProgramRoles.Count > 1)
                        {
                            Response.Redirect(String.Format("/Account/SelectRole.aspx?ReturnUrl={0}",
                                                            (Request.QueryString["ReturnUrl"] != null ? Request.QueryString["ReturnUrl"].ToString() : "/Default.aspx")));
                        }
                        else
                        {
                            //To hold the role information
                            ProgramAndRoleFromSession roleInfo = new ProgramAndRoleFromSession();

                            //Get the UserProgramRole
                            UserProgramRole userRole = userProgramRoles.FirstOrDefault();

                            //Set the session variables for the program roles
                            roleInfo.RoleFK           = userRole.CodeProgramRole.CodeProgramRolePK;
                            roleInfo.RoleName         = userRole.CodeProgramRole.RoleName;
                            roleInfo.AllowedToEdit    = userRole.CodeProgramRole.AllowedToEdit;
                            roleInfo.CurrentProgramFK = userRole.ProgramFK;
                            roleInfo.ProgramName      = userRole.Program.ProgramName;

                            //Get the hub and state information
                            using (PyramidContext context = new PyramidContext())
                            {
                                Program currentProgram = context.Program.AsNoTracking()
                                                         .Include(p => p.Hub)
                                                         .Include(p => p.State)
                                                         .Include(p => p.ProgramType)
                                                         .Where(p => p.ProgramPK == userRole.ProgramFK).FirstOrDefault();

                                roleInfo.HubFK             = currentProgram.HubFK;
                                roleInfo.HubName           = currentProgram.Hub.Name;
                                roleInfo.StateFK           = currentProgram.StateFK;
                                roleInfo.StateName         = currentProgram.State.Name;
                                roleInfo.StateLogoFileName = currentProgram.State.LogoFilename;
                                roleInfo.StateCatchphrase  = currentProgram.State.Catchphrase;
                                roleInfo.StateDisclaimer   = currentProgram.State.Disclaimer;

                                //Set the allowed program fks
                                if (roleInfo.RoleFK == (int)Utilities.ProgramRoleFKs.HUB_DATA_VIEWER)
                                {
                                    //Hub viewer, allow them to see the programs in that hub
                                    var hubPrograms = context.Program.AsNoTracking()
                                                      .Where(p => p.HubFK == roleInfo.HubFK.Value)
                                                      .ToList();
                                    roleInfo.ProgramFKs = hubPrograms
                                                          .Select(hp => hp.ProgramPK)
                                                          .ToList();

                                    //Allow them to see all cohorts in their hub
                                    roleInfo.CohortFKs = hubPrograms
                                                         .Select(hp => hp.CohortFK)
                                                         .Distinct()
                                                         .ToList();

                                    //Don't restrict their view of the BOQs
                                    roleInfo.ShowBOQ    = true;
                                    roleInfo.ShowBOQFCC = true;
                                }
                                else if (roleInfo.RoleFK == (int)Utilities.ProgramRoleFKs.APPLICATION_ADMIN)
                                {
                                    //App admin, allow them to see all programs in a state
                                    roleInfo.ProgramFKs = context.Program.AsNoTracking()
                                                          .Where(p => p.StateFK == roleInfo.StateFK.Value)
                                                          .Select(p => p.ProgramPK).ToList();

                                    //Allow them to see all cohorts in a state
                                    roleInfo.CohortFKs = context.Cohort.AsNoTracking()
                                                         .Where(c => c.StateFK == roleInfo.StateFK.Value)
                                                         .Select(c => c.CohortPK).ToList();

                                    //Don't restrict their view of the BOQs
                                    roleInfo.ShowBOQ    = true;
                                    roleInfo.ShowBOQFCC = true;
                                }
                                else if (roleInfo.RoleFK == (int)Utilities.ProgramRoleFKs.SUPER_ADMIN)
                                {
                                    //Super admin, all programs in all states
                                    roleInfo.ProgramFKs = context.Program.AsNoTracking()
                                                          .Select(p => p.ProgramPK).ToList();

                                    //All cohorts
                                    roleInfo.CohortFKs = context.Cohort.AsNoTracking()
                                                         .Select(c => c.CohortPK).ToList();

                                    //Don't restrict their view of the BOQs
                                    roleInfo.ShowBOQ    = true;
                                    roleInfo.ShowBOQFCC = true;
                                }
                                else
                                {
                                    //Something else, limit to the current program fk
                                    List <int> programFKs = new List <int>();
                                    programFKs.Add(roleInfo.CurrentProgramFK.Value);
                                    roleInfo.ProgramFKs = programFKs;

                                    //Limit to current cohort fk
                                    List <int> cohortFKs = new List <int>();
                                    cohortFKs.Add(currentProgram.CohortFK);
                                    roleInfo.CohortFKs = cohortFKs;

                                    //Determine if this program is a FCC program
                                    var fccProgramTypes = currentProgram.ProgramType
                                                          .Where(pt => pt.TypeCodeFK == (int)Utilities.ProgramTypeFKs.FAMILY_CHILD_CARE ||
                                                                 pt.TypeCodeFK == (int)Utilities.ProgramTypeFKs.GROUP_FAMILY_CHILD_CARE)
                                                          .ToList();

                                    //Limit their view to the right BOQ type
                                    if (fccProgramTypes.Count > 0)
                                    {
                                        roleInfo.ShowBOQ    = false;
                                        roleInfo.ShowBOQFCC = true;
                                    }
                                    else
                                    {
                                        roleInfo.ShowBOQ    = true;
                                        roleInfo.ShowBOQFCC = false;
                                    }
                                }
                            }

                            //Add the role information to the session
                            Utilities.SetProgramRoleInSession(Session, roleInfo);

                            //Redirect the user
                            Response.Redirect(Request.QueryString["ReturnUrl"] != null ? Request.QueryString["ReturnUrl"].ToString() : "/Default.aspx");
                        }
                        break;

                    case SignInStatus.LockedOut:
                        Response.Redirect("/Account/Lockout");
                        break;

                    case SignInStatus.RequiresVerification:
                        Response.Redirect(String.Format("/Account/TwoFactorAuthenticationSignIn?ReturnUrl={0}",
                                                        Request.QueryString["ReturnUrl"]), true);
                        break;

                    case SignInStatus.Failure:
                    default:
                        //Show the user an error message
                        msgSys.ShowMessageToUser("danger", "Error", "Invalid login attempt", 120000);

                        //Focus the password text box
                        txtPassword.Focus();
                        break;
                    }
                }
                else
                {
                    msgSys.ShowMessageToUser("danger", "Error", "Invalid login attempt", 120000);
                }
            }
        }