/// <summary>
        /// Removes the engagements of the given conversation owners.
        /// </summary>
        /// <param name="conversationOwnerParties">The conversation owners whose engagements to remove.</param>
        /// <returns>The number of engagements removed.</returns>
        protected virtual IList <MessageRouterResult> RemoveEngagements(IList <Party> conversationOwnerParties)
        {
            IList <MessageRouterResult> messageRouterResults = new List <MessageRouterResult>();

            foreach (Party conversationOwnerParty in conversationOwnerParties)
            {
                EngagedParties.TryGetValue(conversationOwnerParty, out Party conversationClientParty);

                if (EngagedParties.Remove(conversationOwnerParty))
                {
                    if (conversationOwnerParty is EngageableParty)
                    {
                        (conversationOwnerParty as EngageableParty).ResetEngagementStartedTime();
                    }

                    if (conversationClientParty is EngageableParty)
                    {
                        (conversationClientParty as EngageableParty).ResetEngagementStartedTime();
                    }

                    messageRouterResults.Add(new MessageRouterResult()
                    {
                        Type = MessageRouterResultType.EngagementRemoved,
                        ConversationOwnerParty  = conversationOwnerParty,
                        ConversationClientParty = conversationClientParty
                    });
                }
            }

            return(messageRouterResults);
        }
        public virtual MessageRouterResult AddEngagementAndClearPendingRequest(Party conversationOwnerParty, Party conversationClientParty)
        {
            MessageRouterResult result = new MessageRouterResult()
            {
                ConversationOwnerParty  = conversationOwnerParty,
                ConversationClientParty = conversationClientParty
            };

            if (conversationOwnerParty != null && conversationClientParty != null)
            {
                try
                {
                    EngagedParties.Add(conversationOwnerParty, conversationClientParty);
                    PendingRequests.Remove(conversationClientParty);
                    result.Type = MessageRouterResultType.EngagementAdded;
                }
                catch (ArgumentException e)
                {
                    result.Type         = MessageRouterResultType.Error;
                    result.ErrorMessage = e.Message;
                    System.Diagnostics.Debug.WriteLine($"Failed to add engagement between parties {conversationOwnerParty} and {conversationClientParty}: {e.Message}");
                }
            }
            else
            {
                result.Type         = MessageRouterResultType.Error;
                result.ErrorMessage = "Either the owner or the client is missing";
            }

            return(result);
        }
        public virtual void DeleteAll()
        {
            AggregationParties.Clear();
            UserParties.Clear();
            BotParties.Clear();
            PendingRequests.Clear();
            EngagedParties.Clear();
#if DEBUG
            LastMessageRouterResults.Clear();
#endif
        }
        public virtual Party GetEngagedCounterpart(Party partyWhoseCounterpartToFind)
        {
            Party counterparty = null;

            if (IsEngaged(partyWhoseCounterpartToFind, EngagementProfile.Client))
            {
                for (int i = 0; i < EngagedParties.Count; ++i)
                {
                    if (EngagedParties.Values.ElementAt(i).Equals(partyWhoseCounterpartToFind))
                    {
                        counterparty = EngagedParties.Keys.ElementAt(i);
                        break;
                    }
                }
            }
            else if (IsEngaged(partyWhoseCounterpartToFind, EngagementProfile.Owner))
            {
                EngagedParties.TryGetValue(partyWhoseCounterpartToFind, out counterparty);
            }

            return(counterparty);
        }
        /// <summary>
        /// Removes the engagements of the given conversation owners.
        /// </summary>
        /// <param name="conversationOwnerParties">The conversation owners whose engagements to remove.</param>
        /// <returns>The number of engagements removed.</returns>
        protected virtual IList <MessageRouterResult> RemoveEngagements(IList <Party> conversationOwnerParties)
        {
            IList <MessageRouterResult> messageRouterResults = new List <MessageRouterResult>();

            foreach (Party conversationOwnerParty in conversationOwnerParties)
            {
                Party conversationClientParty = null;
                EngagedParties.TryGetValue(conversationOwnerParty, out conversationClientParty);

                if (EngagedParties.Remove(conversationOwnerParty))
                {
                    messageRouterResults.Add(new MessageRouterResult()
                    {
                        Type = MessageRouterResultType.EngagementRemoved,
                        ConversationOwnerParty  = conversationOwnerParty,
                        ConversationClientParty = conversationClientParty
                    });
                }
            }

            return(messageRouterResults);
        }