public ActionResult Edit(UserViewModel formModel)
        {
            var isEditingOrCreating = formModel.Id != null ? 'E' : 'C';

            this.ViewBag.IsEditingOrCreating = isEditingOrCreating;

            var utcNow = this.GetUtcNow();

            User user;

            // Normalizing the name of the person.
            if (!string.IsNullOrEmpty(formModel.FullName))
            {
                formModel.FullName = Regex.Replace(formModel.FullName, @"\s+", " ").Trim();
            }

            if (isEditingOrCreating == 'E')
            {
                // Note: User name cannot be edited, and should not be validated.
                this.ModelState.ClearPropertyErrors(() => formModel.UserName);

                user = this.db.Users.First(p => p.Id == formModel.Id);

                // TODO: suggest that r# use the attribute EdmScalarPropertyAttribute(IsNullable=false)
                // as a way to determine if a property can ever receive a null value or not
                // there was a bug in the line inside the following if, that could be detected by r# if it did consider that attribute.
                if (!string.IsNullOrWhiteSpace(formModel.FullName))
                {
                    user.Person.FullName = formModel.FullName;
                }

                user.Person.Gender = (short)formModel.Gender;

                // If there are model errors, we must return original user name to the view.
                formModel.UserName = user.UserName;
            }
            else
            {
                // UserName must not be null nor empty.
                if (string.IsNullOrWhiteSpace(formModel.UserName))
                {
                    this.ModelState.AddModelError(() => formModel.UserName, "Nome de usuário inválido.");
                }

                var loggedUser = this.DbUser;

                // Checking doctors limit of this account.
                if (formModel.IsDoctor)
                {
                    var doctorsCount = this.DbPractice.Users.Count(u => u.DoctorId != null);
                    if (doctorsCount >= this.DbPractice.AccountContract.DoctorsLimit)
                    {
                        this.ModelState.AddModelError(
                            "DoctorsLimit",
                            "Essa conta está configurada para suportar até {0} médicos.",
                            this.DbPractice.AccountContract.DoctorsLimit);
                    }
                }

                // Looking for another user with the same UserName or Email.
                var conflictingData = this.db.Users
                                      .Where(u => u.PracticeId == loggedUser.PracticeId)
                                      .Where(u => u.UserName == formModel.UserName || u.Person.Email == formModel.Email)
                                      .Select(u => new { u.UserName, u.Person.Email })
                                      .ToList();

                // Verifying wich fields are conflicting: Email.
#warning [Validate] Must validate all emails.
                bool emailConflict = conflictingData.Any(c => c.Email == formModel.Email);

                // For every new user we must create a login, with a common
                // password used the first time the person logs in.
                // The only action allowed with this password,
                // is to change the password.
                var userData = new CreateAccountViewModel
                {
                    UserName        = formModel.UserName,
                    Password        = Constants.DEFAULT_PASSWORD,
                    ConfirmPassword = Constants.DEFAULT_PASSWORD,
                    EMail           = formModel.Email,
                    FullName        = formModel.FullName,
                    Gender          = (short)formModel.Gender,
                };

                // Creating the new user.
                // The user belongs to the same practice as the logged user.
                var result = SecurityManager.CreateUser(out user, userData, this.db.Users, utcNow, loggedUser.PracticeId);

                if (result == CreateUserResult.UserNameAlreadyInUse)
                {
                    this.ModelState.AddModelError(
                        () => formModel.UserName,
                        // Todo: this message is also used in the AuthenticationController.
                        "O nome de usuário não pode ser registrado pois já está em uso. "
                        + "Note que nomes de usuário diferenciados por acentos, "
                        + "maiúsculas/minúsculas ou por '.', '-' ou '_' não são permitidos."
                        + "(Não é possível cadastrar 'MiguelAngelo' e 'miguel.angelo' no mesmo consultório.");
                }
            }

#warning Must validade all emails, cannot repeat emails in the same practice.

            if (!formModel.IsDoctor && !formModel.IsAdministrador && !formModel.IsSecretary)
            {
                this.ModelState.AddModelError("", "Usuário tem que ter pelo menos uma função: médico, administrador ou secretária.");
            }

            // If the user being edited is a doctor, then we must check the fields that are required for medics.
            if (!formModel.IsDoctor)
            {
                // Removing validation error of medic properties, because this user is not a medic.
                this.ModelState.ClearPropertyErrors(() => formModel.MedicCRM);
                this.ModelState.ClearPropertyErrors(() => formModel.MedicalEntityId);
                this.ModelState.ClearPropertyErrors(() => formModel.MedicalSpecialtyId);
                this.ModelState.ClearPropertyErrors(() => formModel.MedicalSpecialtyName);
                this.ModelState.ClearPropertyErrors(() => formModel.MedicalEntityJurisdiction);
            }

            if (user != null)
            {
                if (formModel.DateOfBirth.HasValue)
                {
                    user.Person.DateOfBirth = ConvertToUtcDateTime(this.DbPractice, formModel.DateOfBirth.Value);
                }
                user.Person.BirthPlace        = formModel.BirthPlace;
                user.Person.CPF               = formModel.Cpf;
                user.Person.CreatedOn         = this.GetUtcNow();
                user.Person.MaritalStatus     = formModel.MaritalStatus;
                user.Person.Profession        = formModel.Profissao;
                user.Person.Email             = formModel.Email;
                user.Person.EmailGravatarHash = GravatarHelper.GetGravatarHash(formModel.Email);

                // handle address
                if (!user.Person.Addresses.Any())
                {
                    user.Person.Addresses.Add(
                        new Address
                    {
                        PracticeId    = this.DbUser.PracticeId,
                        CEP           = formModel.Address.CEP,
                        City          = formModel.Address.City,
                        Complement    = formModel.Address.Complement,
                        Neighborhood  = formModel.Address.Neighborhood,
                        StateProvince = formModel.Address.StateProvince,
                        Street        = formModel.Address.Street,
                    });
                }

                // when the user is a doctor, we need to fill the properties of the doctor
                if (formModel.IsDoctor)
                {
                    // Only administrators can change the role of an user.
                    if (this.DbUser.AdministratorId != null)
                    {
                        // if user is already a doctor, we just edit the properties
                        // otherwise we create a new doctor instance
                        if (user.Doctor == null)
                        {
                            user.Doctor = new Doctor {
                                PracticeId = this.DbUser.PracticeId,
                            };
                            BusHelper.FillNewDoctorUtilityBelt(user.Doctor);
                        }
                    }

                    // Changing the doctor's informations.
                    if (!string.IsNullOrWhiteSpace(formModel.MedicCRM))
                    {
                        user.Doctor.CRM = formModel.MedicCRM;
                    }

                    if (formModel.MedicalEntityId != null)
                    {
                        var me = this.db.SYS_MedicalEntity.First(me1 => me1.Id == formModel.MedicalEntityId);
                        user.Doctor.MedicalEntityCode = me.Code;
                        user.Doctor.MedicalEntityName = me.Name;
                    }

                    if (formModel.MedicalSpecialtyId != null)
                    {
                        var ms = this.db.SYS_MedicalSpecialty.First(ms1 => ms1.Id == formModel.MedicalSpecialtyId);
                        user.Doctor.MedicalSpecialtyCode = ms.Code;
                        user.Doctor.MedicalSpecialtyName = ms.Name;
                    }

                    if (formModel.MedicalEntityJurisdiction != null)
                    {
                        user.Doctor.MedicalEntityJurisdiction =
                            ((TypeEstadoBrasileiro)formModel.MedicalEntityJurisdiction.Value).ToString();
                    }

                    // Creating an unique UrlIdentifier for this doctor.
                    // This does not consider UrlIdentifier's used by other kinds of objects.
                    string urlId = GetUniqueDoctorUrlId(this.db.Doctors, formModel.FullName, this.DbPractice.Id);
                    if (urlId == null && !string.IsNullOrWhiteSpace(formModel.FullName))
                    {
                        this.ModelState.AddModelError(
                            () => formModel.FullName,
                            // Todo: this message is also used in the AuthenticationController.
                            string.Format("Quantidade máxima de homônimos excedida para esta conta: {0}.", this.DbPractice.UrlIdentifier));
                    }

                    if (!string.IsNullOrWhiteSpace(urlId))
                    {
                        user.Doctor.UrlIdentifier = urlId;
                    }
                }
                else
                {
                    // Only administrators can change the role of an user.
                    if (this.DbUser.AdministratorId != null)
                    {
                        if (user.Doctor != null)
                        {
                            this.db.Doctors.DeleteObject(user.Doctor);
                        }

                        // if the user is not a doctor, then we make sure
                        // by assigning the doctor property to null
                        user.Doctor = null;
                    }
                }

                // when the user is an administrator
                if (formModel.IsAdministrador)
                {
                    // Only administrators can change the role of an user.
                    if (this.DbUser.AdministratorId != null)
                    {
                        if (user.Administrator == null)
                        {
                            user.Administrator = new Administrator {
                                PracticeId = this.DbUser.PracticeId,
                            }
                        }
                    }
                    ;
                }
                else
                {
                    // Only administrators can change the role of an user.
                    if (this.DbUser.AdministratorId != null)
                    {
                        if (user.Administrator != null)
                        {
                            this.db.Administrators.DeleteObject(user.Administrator);
                        }
                        user.Administrator = null;
                    }
                }

                if (user.IsOwner)
                {
                    if (!formModel.IsAdministrador)
                    {
                        this.ModelState.AddModelError(
                            () => formModel.IsAdministrador,
                            "Não é possível remover o papel de administrador do proprietário da conta.");
                    }
                }

                // when the user is a secretary
                if (formModel.IsSecretary)
                {
                    // Only administrators can change the role of an user.
                    if (this.DbUser.AdministratorId != null)
                    {
                        if (user.Secretary == null)
                        {
                            user.Secretary = new Secretary {
                                PracticeId = this.DbUser.PracticeId,
                            }
                        }
                    }
                    ;
                }
                else
                {
                    // Only administrators can change the role of an user.
                    if (this.DbUser.AdministratorId != null)
                    {
                        if (user.Secretary != null)
                        {
                            this.db.Secretaries.DeleteObject(user.Secretary);
                        }
                        user.Secretary = null;
                    }
                }
            }

            // If ModelState is still valid, save the objects to the database.
            if (this.ModelState.IsValid)
            {
                if (formModel.Id == null)
                {
                    var notificationData = new NewUserCreatedNotificationData()
                    {
                        UserName = user.UserName
                    };
                    var dbNotification = new Notification()
                    {
                        CreatedOn  = this.GetUtcNow(),
                        PracticeId = this.DbPractice.Id,
                        UserToId   = this.DbUser.Id,
                        Type       = NotificationConstants.NEW_USER_NOTIFICATION_TYPE,
                        Data       = new JavaScriptSerializer().Serialize(notificationData)
                    };
                    this.db.Notifications.AddObject(dbNotification);
                    this.db.SaveChanges();
                    NotificationsHub.BroadcastDbNotification(dbNotification, notificationData);
                }

                // Saving all the changes.
                this.db.SaveChanges();

                return(this.RedirectToAction("Details", new { id = user.Id }));
            }

            this.ViewBag.MedicalSpecialtyOptions =
                this.db.SYS_MedicalSpecialty
                .ToList()
                .Select(ms => new SelectListItem {
                Value = ms.Id.ToString(), Text = ms.Name
            })
                .ToList();

            this.ViewBag.MedicalEntityOptions =
                this.db.SYS_MedicalEntity
                .ToList()
                .Select(me => new SelectListItem {
                Value = me.Id.ToString(), Text = me.Name
            })
                .ToList();

            if (this.DbUser.AdministratorId != null || this.DbUser.IsOwner)
            {
                this.ViewBag.CanEditRole = true;
            }

            // Removes all duplicated messages.
            this.ModelState.RemoveDuplicates();

            return(this.View("Edit", formModel));
        }