// [0] /add => Ask for AccountName => Ask for Link => Ask for Note => Ask for password => Ask for EncryptionKey
        // [1] /add AccountName => Ask for Link => Ask for Note => Ask for password => Ask for EncryptionKey
        // [2] /add AccountName \n Login => Ask for password => Ask for EncryptionKey
        // [3] /add AccountName \n Login \n Password => Ask for EncryptionKey
        // [4] /add AccountName \n Login \n Password \n EncryptionKey
        // [5] /add AccountName \n Link \n Login \n Password \n EncryptionKey
        // [6] /add AccountName \n Link \n Note \n Login \n Password \n EncryptionKey
        public AccountAssemblingStage Create(int userId, string[] args = null)
        {
            var accountAssemblingModel = new AccountAssemblingModel()
            {
                AccountAssemblingStage = AccountAssemblingStage.AddAccountName,
                UserId = userId,
            };

            if (args == null || args.Length == 0)
            {
                accountAssemblings[userId] = accountAssemblingModel;
                return(accountAssemblingModel.AccountAssemblingStage);
            }

            accountAssemblingModel.AccountName = args[0];
            switch (args.Length)
            {
            case 1:
                accountAssemblingModel.AccountAssemblingStage = AccountAssemblingStage.AddLink;
                break;

            case 2:
                accountAssemblingModel.Login = args[1];
                accountAssemblingModel.AccountAssemblingStage = AccountAssemblingStage.AddPassword;
                break;

            case 3:
                accountAssemblingModel.Login    = args[1];
                accountAssemblingModel.Password = args[2];
                accountAssemblingModel.AccountAssemblingStage = AccountAssemblingStage.AddEncryptionKey;
                break;

            case 4:
                accountAssemblingModel.Login     = args[1];
                accountAssemblingModel.Password  = args[2].Encrypt(args[3]);
                accountAssemblingModel.Encrypted = true;
                accountAssemblingModel.AccountAssemblingStage = AccountAssemblingStage.Release;
                break;

            case 5:
                accountAssemblingModel.Link      = args[1];
                accountAssemblingModel.Login     = args[2];
                accountAssemblingModel.Password  = args[3].Encrypt(args[4]);
                accountAssemblingModel.Encrypted = true;
                accountAssemblingModel.AccountAssemblingStage = AccountAssemblingStage.Release;
                break;

            default:
                accountAssemblingModel.Link      = args[1];
                accountAssemblingModel.Note      = args[2];
                accountAssemblingModel.Login     = args[3];
                accountAssemblingModel.Password  = args[4].Encrypt(args[5]);
                accountAssemblingModel.Encrypted = true;
                accountAssemblingModel.AccountAssemblingStage = AccountAssemblingStage.Release;
                break;
            }

            accountAssemblings[userId] = accountAssemblingModel;
            return(accountAssemblingModel.AccountAssemblingStage);
        }
        public AccountUpdatingStage GetNextUpdatingStage(int userId, string property,
                                                         AccountUpdatingStage expectedAccountUpdatingStage = AccountUpdatingStage.None, long?accountId = null)
        {
            if (updatingAccounts.TryGetValue(userId, out AccountUpdatingModel accountUpdatingModel))
            {
                if ((accountId == null) || (accountId.Value == accountUpdatingModel.Account.Id &&
                                            expectedAccountUpdatingStage != AccountUpdatingStage.None &&
                                            accountUpdatingModel.AccountUpdatingStage == expectedAccountUpdatingStage))
                {
                    if (accountUpdatingModel.AccountUpdatingStage != AccountUpdatingStage.Release)
                    {
                        AccountAssemblingModel accountAssemblingModel = new AccountAssemblingModel();
                        switch (accountUpdatingModel.AccountUpdatingStage)
                        {
                        case AccountUpdatingStage.OutdatedTime:
                            if (property == null)
                            {
                                accountUpdatingModel.Account.OutdatedTime = null;
                                return(accountUpdatingModel.AccountUpdatingStage = AccountUpdatingStage.Release);
                            }
                            else if (Int32.TryParse(property, out int outdatedTimeDays))
                            {
                                accountUpdatingModel.Account.OutdatedTime
                                    = new TimeSpan(outdatedTimeDays, 0, 0, 0);
                                return(accountUpdatingModel.AccountUpdatingStage = AccountUpdatingStage.Release);
                            }
                            else
                            {
                                throw new ValidationException("Invalid number");
                            }

                        case AccountUpdatingStage.AccountName:
                            accountAssemblingModel.AccountName       = property;
                            accountUpdatingModel.Account.AccountName = accountAssemblingModel.AccountName;
                            return(accountUpdatingModel.AccountUpdatingStage = AccountUpdatingStage.Release);

                        case AccountUpdatingStage.Link:
                            accountAssemblingModel.Link       = property.AutoDomain().BuildUrl();
                            accountUpdatingModel.Account.Link = accountAssemblingModel.Link;
                            return(accountUpdatingModel.AccountUpdatingStage = AccountUpdatingStage.Release);

                        case AccountUpdatingStage.Note:
                            accountAssemblingModel.Note       = property;
                            accountUpdatingModel.Account.Note = accountAssemblingModel.Note;
                            return(accountUpdatingModel.AccountUpdatingStage = AccountUpdatingStage.Release);

                        case AccountUpdatingStage.Login:
                            accountAssemblingModel.Login       = property;
                            accountUpdatingModel.Account.Login = accountAssemblingModel.Login;
                            return(accountUpdatingModel.AccountUpdatingStage = AccountUpdatingStage.Release);

                        case AccountUpdatingStage.Password:
                            accountAssemblingModel.Password                  = property;
                            accountUpdatingModel.Account.Password            = accountAssemblingModel.Password;
                            accountUpdatingModel.Account.PasswordUpdatedDate = DateTime.UtcNow;
                            return(accountUpdatingModel.AccountUpdatingStage = AccountUpdatingStage.EncryptPassword);

                        case AccountUpdatingStage.EncryptPassword:
                            accountAssemblingModel.Password        = accountUpdatingModel.Account.Password.Encrypt(property);
                            accountUpdatingModel.Account.Password  = accountAssemblingModel.Password;
                            accountUpdatingModel.Account.Encrypted = true;
                            return(accountUpdatingModel.AccountUpdatingStage = AccountUpdatingStage.Release);

                        case AccountUpdatingStage.RemovePasswordEncryption:
                            accountAssemblingModel.Password                  = property;
                            accountUpdatingModel.Account.Password            = accountAssemblingModel.Password;
                            accountUpdatingModel.Account.PasswordUpdatedDate = DateTime.UtcNow;
                            accountUpdatingModel.Account.Encrypted           = false;
                            return(accountUpdatingModel.AccountUpdatingStage = AccountUpdatingStage.Release);

                        default:
                            throw new InvalidOperationException("Unknown updating stage");
                        }
                    }
                    else
                    {
                        return(AccountUpdatingStage.Release);
                    }
                }
            }
            return(AccountUpdatingStage.None);
        }