/// <summary>
        /// Accepts a command string and handles the parsing and execution of the command and the included arguments.
        /// </summary>
        /// <param name="commandString">The command string. Usually a string passed in from a command line interface by the user.</param>
        /// <returns>A CommandResult option containing properties relevant to how data should be processed by the UI.</returns>
        public CommandResult ExecuteCommand(string commandString)
        {
            if (commandString == null) commandString = string.Empty;
            var hasSpace = commandString.Contains(' ');
            var spaceIndex = 0;
            if (hasSpace)
                spaceIndex = commandString.IndexOf(' ');

            // Parse command string to find the command name.
            string commandName = hasSpace ? commandString.Remove(spaceIndex) : commandString;

            if (_currentUser != null)
            {
                _currentUser.LastLogin = DateTime.UtcNow;
                _dataBucket.UserRepository.UpdateUser(_currentUser);
                _dataBucket.SaveChanges();
            }

            // Check for alias. Replace command name with alias.
            if ((_commandContext.Status & ContextStatus.Forced) == 0)
            {
                var alias = defaultAliases.SingleOrDefault(x => x.Shortcut.Is(commandName));
                if (_currentUser != null)
                    alias = _dataBucket.AliasRepository.GetAlias(_currentUser.Username, commandName);
                if (alias != null)
                {
                    commandString = hasSpace ? alias.Command + commandString.Remove(0, spaceIndex) : alias.Command;
                    hasSpace = commandString.Contains(' ');
                    spaceIndex = 0;
                    if (hasSpace)
                        spaceIndex = commandString.IndexOf(' ');
                    commandName = hasSpace ? commandString.Remove(spaceIndex) : commandString;
                }
            }

            // Parse command string and divide up arguments into a string array.
            var args = hasSpace ?
                commandString.Remove(0, spaceIndex)
                .Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries) : null;

            // Obtain all roles the current user is a part of.
            var availableRoles = _currentUser != null ? _currentUser.Roles.Select(x => x.Name).ToArray() : new string[] { "Visitor" };

            // Create command result.
            var commandResult = new CommandResult(TerminalEvents)
            {
                Command = commandName.ToUpper(),
                CurrentUser = _currentUser,
                CommandContext = _commandContext,
                IPAddress = _ipAddress,
            };

            // Obtain all commands for the roles the user is a part of.
            var commands = _commands
                .Where(x => x.Roles.Any(y => availableRoles.Any(z => z.Is(y))))
                .ToList();

            foreach (var cmd in commands)
            {
                cmd.CommandResult = commandResult;
                cmd.AvailableCommands = commands;
            }

            if (_currentUser != null && _currentUser.BanInfo != null)
                if (DateTime.UtcNow < _currentUser.BanInfo.EndDate)
                    return BanMessage(commandResult);
                else
                {
                    _dataBucket.UserRepository.UnbanUser(_currentUser.Username);
                    _dataBucket.UserRepository.UpdateUser(_currentUser);
                    _dataBucket.SaveChanges();
                }

            // Obtain the command the user intends to execute from the list of available commands.
            var command = commands.SingleOrDefault(x => x.Name.Is(commandName));

            if (commandName.Is("INITIALIZE"))
                commandResult.DeactivateContext();

            // Perform different behaviors based on the current command context.
            switch (_commandContext.Status)
            {
                // Perform normal command execution.
                case ContextStatus.Disabled:
                    if (command != null)
                    {
                        command.CommandResult.Command = command.Name;
                        command.Invoke(args);
                    }
                    break;

                // Perform normal command execution.
                // If command does not exist, attempt to use command context instead.
                case ContextStatus.Passive:
                    if (command != null)
                    {
                        command.CommandResult.Command = command.Name;
                        command.Invoke(args);
                    }
                    else if (!commandName.Is("HELP"))
                    {
                        command = commands.SingleOrDefault(x => x.Name.Is(_commandContext.Command));
                        if (command != null)
                        {
                            args = commandString.Contains(' ') ? commandString.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries) : new string[] { commandString };
                            var newArgs = new List<string>();
                            if (_commandContext.Args != null) newArgs.AddRange(_commandContext.Args);
                            newArgs.AddRange(args);
                            command.CommandResult.Command = command.Name;
                            command.Invoke(newArgs.ToArray());
                        }
                    }
                    break;

                // Perform command execution using command context.
                // Reset command context if "CANCEL" is supplied.
                case ContextStatus.Forced:
                    if (!commandName.Is("CANCEL"))
                    {
                        command = commands.SingleOrDefault(x => x.Name.Is(_commandContext.Command));
                        if (command != null)
                        {
                            command.CommandResult.Command = command.Name;
                            if (_commandContext.Prompt)
                            {
                                var newStrings = new List<string>();
                                if (_commandContext.PromptData != null)
                                    newStrings.AddRange(_commandContext.PromptData);
                                newStrings.Add(commandString);
                                _commandContext.PromptData = newStrings.ToArray();
                                command.Invoke(_commandContext.Args);
                            }
                            else
                            {
                                args = commandString.Contains(' ') ? commandString.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries) : new string[] { commandString };
                                var newArgs = new List<string>();
                                if (_commandContext.Args != null) newArgs.AddRange(_commandContext.Args);
                                newArgs.AddRange(args);
                                args = newArgs.ToArray();
                                command.Invoke(args);
                            }
                        }
                    }
                    else
                    {
                        commandResult.RestoreContext();
                        commandResult.WriteLine("Action canceled.");
                    }
                    break;
            }

            // If command does not exist, check if the command was "HELP".
            // If so, call the ShowHelp method to show help information for all available commands.
            if (command == null)
            {
                if (commandName.Is("HELP"))
                    commandResult = DisplayHelp(commands, args, commandResult);
                else if (!commandName.Is("CANCEL"))
                    if (commandName.IsNullOrWhiteSpace())
                        commandResult.WriteLine("You must supply a command.");
                    else
                        commandResult.WriteLine("'{0}' is not a recognized command or is not available in the current context.", commandName);
            }

            _currentUser = commandResult.CurrentUser;
            if (_currentUser != null && _currentUser.BanInfo != null)
                if (DateTime.UtcNow < _currentUser.BanInfo.EndDate)
                    return BanMessage(commandResult);
                else
                {
                    _dataBucket.UserRepository.UnbanUser(_currentUser.Username);
                    _dataBucket.UserRepository.UpdateUser(_currentUser);
                    _dataBucket.SaveChanges();
                }

            // Temporarily notify of messages on each command execution.
            if (_currentUser != null)
            {
                var unreadMessageCount = _dataBucket.MessageRepository.UnreadMessages(_currentUser.Username);
                if (unreadMessageCount > 0)
                {
                    commandResult.WriteLine();
                    commandResult.WriteLine("You have {0} unread message(s).", unreadMessageCount);
                }
            }

            commandResult.TerminalTitle = string.Format("Terminal - {0}", _currentUser != null ? _currentUser.Username : "******");

            FinalParsing(commandResult);

            return commandResult;
        }
        public void Invoke(string[] args)
        {
            var options = new OptionSet();
            options.Add(
                "?|help",
                "Show help information.",
                x => HelpUtility.WriteHelpInformation(this, options)
            );

            List<string> parsedArgs = null;
            if (args != null)
            {
                try
                {
                    parsedArgs = options.Parse(args);
                }
                catch (OptionException ex)
                {
                    CommandResult.WriteLine(ex.Message);
                }
            }

            var registrationStatus = _dataBucket.VariableRepository.GetVariable("Registration");
            if (registrationStatus.Equals("Open", StringComparison.InvariantCultureIgnoreCase) || CommandResult.CommandContext.PromptData != null)
            {
                CommandResult.CommandContext.Prompt = false;
                InviteCode inviteCode = null;
                if (CommandResult.CommandContext.PromptData != null)
                    inviteCode = _dataBucket.InviteCodeRepository.GetInviteCode(CommandResult.CommandContext.PromptData[0]);

                if (CommandResult.CommandContext.PromptData == null || inviteCode != null)
                {
                    if (inviteCode != null)
                    {
                        if (parsedArgs == null)
                            parsedArgs = new List<string> { inviteCode.Username };
                        else
                            parsedArgs.Insert(0, inviteCode.Username);
                    }
                    if ((parsedArgs == null || parsedArgs.Count == 0))
                    {
                        CommandResult.WriteLine("Enter your desired username. (no spaces. sorry.)");
                        CommandResult.SetContext(ContextStatus.Forced, Name, args, "Username");
                    }
                    else if (parsedArgs.Count == 1)
                    {
                        if (parsedArgs[0].Length >= 3 && parsedArgs[0].Length <= 30)
                        {
                            if (!_dataBucket.UserRepository.CheckUserExists(parsedArgs[0]))
                            {
                                CommandResult.WriteLine("Enter your desired password.");
                                CommandResult.PasswordField = true;
                                CommandResult.SetContext(ContextStatus.Forced, Name, args, "Password");
                            }
                            else
                            {
                                CommandResult.WriteLine("Username already exists.");
                                CommandResult.WriteLine("Enter a different username.");
                                CommandResult.SetContext(ContextStatus.Forced, Name, null, "Username");
                            }
                        }
                        else
                        {
                            CommandResult.WriteLine("Username must be between 3 and 15 characters.");
                            CommandResult.WriteLine("Enter a different username.");
                            CommandResult.SetContext(ContextStatus.Forced, Name, null, "Username");
                        }
                    }
                    else if (parsedArgs.Count == 2)
                    {
                        if (parsedArgs[0].Length >= 3 && parsedArgs[0].Length <= 15)
                        {
                            if (!_dataBucket.UserRepository.CheckUserExists(parsedArgs[0]))
                            {
                                CommandResult.WriteLine("Re-enter your desired password.");
                                CommandResult.PasswordField = true;
                                CommandResult.SetContext(ContextStatus.Forced, Name, args, "Confirm Password");
                            }
                            else
                            {
                                CommandResult.WriteLine("Username already exists.");
                                CommandResult.WriteLine("Enter your desired username.");
                                CommandResult.SetContext(ContextStatus.Forced, Name, null, "Username");
                            }
                        }
                        else
                        {
                            CommandResult.WriteLine("Username must be between 3 and 15 characters.");
                            CommandResult.WriteLine("Enter a different username.");
                            CommandResult.SetContext(ContextStatus.Forced, Name, null, "Username");
                        }
                    }
                    else if (parsedArgs.Count == 3)
                    {
                        if (parsedArgs[0].Length >= 3 && parsedArgs[0].Length <= 15)
                        {
                            var user = _dataBucket.UserRepository.GetUser(parsedArgs[0]);
                            if (user == null)
                            {
                                if (parsedArgs[1] == parsedArgs[2])
                                {
                                    user = new User
                                    {
                                        Username = parsedArgs[0],
                                        Password = parsedArgs[1],
                                        JoinDate = DateTime.UtcNow,
                                        LastLogin = DateTime.UtcNow,
                                        TimeZone = "UTC",
                                        Sound = true,
                                    };
                                    var role = _dataBucket.UserRepository.GetRole("User");
                                    user.Roles = new List<Role> { role };

                                    if (inviteCode != null)
                                        _dataBucket.InviteCodeRepository.DeleteInviteCode(inviteCode);

                                    _dataBucket.UserRepository.AddUser(user);
                                    _dataBucket.SaveChanges();

                                    var defaultAliases = new List<Alias>
                                        {
                                            new Alias
                                            {
                                                Username = user.Username,
                                                Shortcut = "lb",
                                                Command = "BOARDS"
                                            },
                                            new Alias
                                            {
                                                Username = user.Username,
                                                Shortcut = "b",
                                                Command = "BOARD"
                                            },
                                            new Alias
                                            {
                                                Username = user.Username,
                                                Shortcut = "t",
                                                Command = "TOPIC"
                                            },
                                            new Alias
                                            {
                                                Username = user.Username,
                                                Shortcut = "lm",
                                                Command = "MESSAGES"
                                            },
                                            new Alias
                                            {
                                                Username = user.Username,
                                                Shortcut = "m",
                                                Command = "MESSAGE"
                                            }
                                        };

                                    defaultAliases.ForEach(x => _dataBucket.AliasRepository.AddAlias(x));
                                    _dataBucket.SaveChanges();

                                    CommandResult.CurrentUser = user;
                                    CommandResult.WriteLine("Thank you for registering.");
                                    //CommandResult.WriteLine();
                                    //var STATS = AvailableCommands.SingleOrDefault(x => x.Name.Is("STATS"));
                                    //STATS.Invoke(new string[] { "-users" });
                                    CommandResult.WriteLine();
                                    CommandResult.WriteLine("You are now logged in as {0}.", CommandResult.CurrentUser.Username);
                                    CommandResult.DeactivateContext();
                                }
                                else
                                {
                                    CommandResult.WriteLine("Passwords did not match.");
                                    CommandResult.WriteLine("Enter your desired password.");
                                    CommandResult.PasswordField = true;
                                    CommandResult.SetContext(ContextStatus.Forced, Name, new string[] { parsedArgs[0] }, "Password");
                                }
                            }
                            else
                            {
                                CommandResult.WriteLine("Username already exists.");
                                CommandResult.WriteLine("Enter your desired username.");
                                CommandResult.SetContext(ContextStatus.Forced, Name, null, "Username");
                            }
                        }
                        else
                        {
                            CommandResult.WriteLine("Username must be between 3 and 15 characters.");
                            CommandResult.WriteLine("Enter a different username.");
                            CommandResult.SetContext(ContextStatus.Forced, Name, null, "Username");
                        }
                    }
                }
                else
                {
                    CommandResult.WriteLine("You did not supply a valid invite code.");
                    CommandResult.DeactivateContext();
                }
            }
            else if (registrationStatus.Equals("Invite-Only", StringComparison.InvariantCultureIgnoreCase))
            {
                CommandResult.WriteLine("Enter your invite code.");
                CommandResult.SetPrompt(Name, args, "Invite Code");
            }
            else if (registrationStatus.Equals("Closed", StringComparison.InvariantCultureIgnoreCase))
                CommandResult.WriteLine("Registration is currently closed.");
        }
 /// <summary>
 /// Deletes a user from the data context.
 /// </summary>
 /// <param name="user">The user to be deleted.</param>
 public void DeleteUser(User user)
 {
     _entityContainer.Users.Remove(user);
 }
 /// <summary>
 /// Updates an existing user in the data context.
 /// </summary>
 /// <param name="user">The user to be updated.</param>
 public void UpdateUser(User user)
 {
 }
 /// <summary>
 /// Adds a user to the data context.
 /// </summary>
 /// <param name="user">The user to be added.</param>
 public void AddUser(User user)
 {
     _entityContainer.Users.Add(user);
 }