/// <summary author="Austin Delaney" created="2019/04/25">
        /// Replies to a thread by passing the message manager a new message with that thread's ID.
        /// </summary>
        /// <param name="thread">The thread to add the message to.</param>
        /// <param name="reply">The message to add to the thread.</param>
        /// <returns>Whether the operation was a success or not.</returns>
        public bool ReplyToThread(IMessageThread thread, Message reply)
        {
            if (null == thread)
            {
                throw new ArgumentNullException("Thread to add participants to cannot be null.");
            }
            if (null == reply)
            {
                throw new ArgumentNullException("Message to use as reply cannot be null.");
            }

            bool            result         = false;
            IMessageManager messageManager = new RealMessageManager(daoType);

            try
            {
                result = messageManager.CreateNewReply(thread, reply);
            }
            catch (Exception ex)
            {
                ExceptionLogManager.getInstance().LogException(ex);
                throw ex;
            }

            return(result);
        }
        /// <summary author="Austin Delaney" created="2019/04/20">
        /// Creates a new thread with a supplied message and then a supplied set of recipients, who will become the thread participants.
        /// Note that if a recipient is included by role/dept as well as by their specific username, the message will ignore their role/dept.
        /// </summary>
        /// <param name="message">The message used to initialize the thread.</param>
        /// <param name="recipients">The set of recipients to be included in the new thread.</param>
        /// <returns>The user specific thread view of the thread.</returns>
        public UserThread CreateNewThread(Message message, List <IMessagable> recipients)
        {
            if (null == message)
            {
                throw new ArgumentNullException("Message cannot be null");
            }

            if (null == recipients)
            {
                recipients = new List <IMessagable>();
            }

            if (!message.IsValid())
            {
                throw new ArgumentException("Message is invalid, thread cannot be created.");
            }

            recipients.Add(message.Sender);

            int newThreadID;

            try
            {
                RealMessageManager messageManager = new RealMessageManager(daoType);
                newThreadID = messageManager.CreateNewMessage(message);
            }
            catch (Exception ex)
            {
                Exception exception =
                    new Exception("Error while creating a new thread using supplied message", ex);
                ExceptionLogManager.getInstance().LogException(exception);
                throw exception;
            }

            UserThread newThread = new UserThread {
                ThreadID = newThreadID
            };

            try
            {
                AddThreadParticipants(newThread, recipients);
            }
            catch (Exception ex)
            {
                Exception exception =
                    new Exception("Error while adding recipients to new thread", ex);
                ExceptionLogManager.getInstance().LogException(exception);
            }

            return(GetUserThread(newThread, message.Sender));
        }
        /// <summary author="Austin Delaney" created="2019/04/25">
        /// Gets a list of all user threads that a user is a participant in.
        /// </summary>
        /// <param name="user">The user/participant to find threads for.</param>
        /// <param name="showArchived">Include archived threads in the retrieval from the data store.</param>
        /// <returns>A list of compact thread objects</returns>
        public List <UserThreadView> GetUserThreadViewList(ISender user, bool showArchived)
        {
            if (null == user)
            {
                throw new ArgumentNullException("A user must be provided that is viewing the threads, cannot be null.");
            }

            List <UserThreadView> result = null;

            try
            {
                result = dao.GetUserThreadViews(user.Email, showArchived);
            }
            catch (Exception ex)
            {
                Exception exc = new Exception("Error while retrieving UserThreadView list for user: "******"Error while retrieving newest message for user: "******" in thread " + result[i].ThreadID, ex);
                    ExceptionLogManager.getInstance().LogException(exc);
                }
            }

            return(result);
        }
        /// <summary author="Austin Delaney" created="2019/04/25">
        /// Gets a fully populated user specific view of a particular thread from the data store
        /// by searching for its ID.
        /// </summary>
        /// <param name="threadID">The ID of the thread to get data on.</param>
        /// <param name="user">The user who is viewing the thread.</param>
        /// <returns>The fully populated thread object representing the requested thread.</returns>
        public UserThread GetUserThread(int threadID, ISender user)
        {
            if (null == user)
            {
                throw new ArgumentNullException("A user must be provided that is viewing the thread, cannot be null.");
            }

            UserThread result;

            try
            {
                result = dao.GetUserThreadData(threadID, user.Email);
            }
            catch (Exception ex)
            {
                Exception exc = new Exception("Error occurred retrieving thread " + threadID + " data for user " + user.Email, ex);
                ExceptionLogManager.getInstance().LogException(exc);
                throw exc;
            }

            //Set the participants of the thread.
            Dictionary <IMessagable, string> participantsWithAlias = new Dictionary <IMessagable, string>();

            //TRY and guess what this does
            try
            {
                //Get all the emails and aliases of the participants first
                Dictionary <string, string> emailsWithAlias = dao.GetThreadParticipantEmailAndAlias(threadID);

                //Setup the managers to get the properly formed data objects that those emails represent
                EmployeeManager    employeeManager = new EmployeeManager();
                GuestManager       guestManager    = new GuestManager();
                MemberManagerMSSQL memberManager   = new MemberManagerMSSQL();

                //Heres the tricky part
                //Using the list of all your emails, get an IEnumerable of all the objects that are found to match those emails
                //Why is this so ugly? It's not. Your eyes simply can't appreciate it's beauty.
                IEnumerable <ISender> foundParticipants = new List <ISender>().Concat(
                    employeeManager.SelectAllEmployees().Where(e => emailsWithAlias.Select(kp => kp.Key).Contains(e.Email))).Concat(
                    guestManager.ReadAllGuests().Where(g => emailsWithAlias.Select(kp => kp.Key).Contains(g.Email))).Concat(
                    memberManager.RetrieveAllMembers().Where(m => emailsWithAlias.Select(kp => kp.Key).Contains(m.Email)));

                //Using the list of objects you obtained, cast those objects to an imessagable and assign them the value that is found for their email
                foreach (var participantObject in foundParticipants)
                {
                    participantsWithAlias[participantObject as IMessagable] = emailsWithAlias[participantObject.Email];
                }
            }
            catch (Exception ex)
            {
                Exception exc = new Exception("Error while populating participants for thread " + threadID, ex);
                ExceptionLogManager.getInstance().LogException(exc);
            }

            result.ParticipantsWithAlias = participantsWithAlias;

            //Set the messages of the thread.
            IEnumerable <Message> messages = new List <Message>();

            //Try to properly retrieve them from data store. If unsuccessful, log exception and set
            //thread messages to an empty list
            try
            {
                RealMessageManager manager = new RealMessageManager(daoType);

                messages = manager.RetrieveThreadMessages(new UserThread {
                    ThreadID = threadID
                });
            }
            catch (Exception ex)
            {
                Exception exc = new Exception("Unable to retrieve messages for thread " + threadID, ex);
                ExceptionLogManager.getInstance().LogException(exc);
            }

            result.Messages = messages.ToList();

            //Return the (hopeuflly) fully formed UserThread object
            return(result);
        }