/// <summary>
        /// Validates incoming SharedActivityChangeItem update item.
        /// <para>This function does not verify whether the activity exists.
        /// It also does not verify whether the new activity start time and expiration time are correct if they are not both changed.</para>
        /// </summary>
        /// <param name="ChangeItem">Change item to validate.</param>
        /// <param name="Index">Item index in the update message.</param>
        /// <param name="UsedFullActivityIdsInBatch">List of activity full IDs of already validated items of this batch.</param>
        /// <param name="MessageBuilder">Client's network message builder.</param>
        /// <param name="RequestMessage">Full request message received by the client.</param>
        /// <param name="ErrorResponse">If the validation fails, this is filled with response message to be sent to the neighbor.</param>
        /// <returns>true if the validation is successful, false otherwise.</returns>
        public static bool ValidateSharedActivityChangeItem(SharedActivityChangeItem ChangeItem, int Index, HashSet <string> UsedFullActivityIdsInBatch, ProxMessageBuilder MessageBuilder, ProxProtocolMessage RequestMessage, out ProxProtocolMessage ErrorResponse)
        {
            log.Trace("(Index:{0})", Index);

            bool res = false;

            ErrorResponse = null;

            if (ChangeItem == null)
            {
                ChangeItem = new SharedActivityChangeItem();
            }
            if (ChangeItem.SignedActivity == null)
            {
                ChangeItem.SignedActivity = new SignedActivityInformation();
            }
            if (ChangeItem.SignedActivity.Activity == null)
            {
                ChangeItem.SignedActivity.Activity = new ActivityInformation();
            }


            byte[] ownerIdentityPubKey = ChangeItem.SignedActivity.Activity.OwnerPublicKey.ToByteArray();
            if (ValidateSignedActivityInformation(ChangeItem.SignedActivity, ownerIdentityPubKey, MessageBuilder, RequestMessage, Index.ToString() + ".change.signedActivity.", true, out ErrorResponse))
            {
                string details = null;

                byte[] identityId = Crypto.Sha256(ownerIdentityPubKey);

                NeighborActivity na = new NeighborActivity()
                {
                    ActivityId      = ChangeItem.SignedActivity.Activity.Id,
                    OwnerIdentityId = identityId
                };

                string activityFullId = na.GetFullId();
                if (!UsedFullActivityIdsInBatch.Contains(activityFullId))
                {
                    UsedFullActivityIdsInBatch.Add(activityFullId);
                }
                else
                {
                    log.Debug("Activity full ID '{0}' already processed in this request.", activityFullId);
                    details = "change.signedActivity.activity.id";
                }

                if (details == null)
                {
                    res = true;
                }
                else
                {
                    ErrorResponse = MessageBuilder.CreateErrorInvalidValueResponse(RequestMessage, Index.ToString() + "." + details);
                }
            }


            log.Trace("(-):{0}", res);
            return(res);
        }
        /// <summary>
        /// Validates incoming update item during the neighborhood initialization process with in-memory database of activities from the neighbor.
        /// </summary>
        /// <param name="AddItem">Update item to validate.</param>
        /// <param name="Index">Index of the update item in the message.</param>
        /// <param name="ActivityDatabase">In-memory temporary database of activities from the neighbor server that were already received and processed.</param>
        /// <param name="MessageBuilder">Client's network message builder.</param>
        /// <param name="RequestMessage">Full request message received by the client.</param>
        /// <param name="ErrorResponse">If the validation fails, this is filled with response message to be sent to the neighbor.</param>
        /// <returns>true if the validation is successful, false otherwise.</returns>
        public static bool ValidateInMemorySharedActivityActivityInformation(SharedActivityAddItem AddItem, int Index, Dictionary <string, NeighborActivity> ActivityDatabase, ProxMessageBuilder MessageBuilder, ProxProtocolMessage RequestMessage, out ProxProtocolMessage ErrorResponse)
        {
            log.Trace("(Index:{0})", Index);

            bool res = false;

            ErrorResponse = null;

            if (AddItem == null)
            {
                AddItem = new SharedActivityAddItem();
            }
            if (AddItem.SignedActivity == null)
            {
                AddItem.SignedActivity = new SignedActivityInformation();
            }
            if (AddItem.SignedActivity.Activity == null)
            {
                AddItem.SignedActivity.Activity = new ActivityInformation();
            }

            byte[] ownerIdentityPubKey = AddItem.SignedActivity.Activity.OwnerPublicKey.ToByteArray();
            if (ValidateSignedActivityInformation(AddItem.SignedActivity, ownerIdentityPubKey, MessageBuilder, RequestMessage, Index.ToString() + ".add.signedActivity.", true, out ErrorResponse))
            {
                string details = null;
                if (ActivityDatabase.Count >= ActivityBase.MaxPrimaryActivities)
                {
                    log.Debug("Target server already sent too many activities.");
                    details = "add";
                }

                if (details == null)
                {
                    byte[]           identityId = Crypto.Sha256(ownerIdentityPubKey);
                    NeighborActivity na         = new NeighborActivity()
                    {
                        ActivityId      = AddItem.SignedActivity.Activity.Id,
                        OwnerIdentityId = identityId
                    };

                    string activityFullId = na.GetFullId();
                    if (ActivityDatabase.ContainsKey(activityFullId))
                    {
                        log.Debug("Activity full ID '{0}' (public key '{1}') already exists.", activityFullId, ownerIdentityPubKey.ToHex());
                        details = "add.signedActivity.activity.id";
                    }
                }

                if (details == null)
                {
                    res = true;
                }
                else
                {
                    ErrorResponse = MessageBuilder.CreateErrorInvalidValueResponse(RequestMessage, Index.ToString() + "." + details);
                }
            }

            log.Trace("(-):{0}", res);
            return(res);
        }
        /// <summary>
        /// Validates incoming SharedActivityDeleteItem update item.
        /// </summary>
        /// <para>This function does not verify whether the activity exists.</para>
        /// <param name="DeleteItem">Delete item to validate.</param>
        /// <param name="Index">Item index in the update message.</param>
        /// <param name="UsedFullActivityIdsInBatch">List of activity full IDs of already validated items of this batch.</param>
        /// <param name="MessageBuilder">Client's network message builder.</param>
        /// <param name="RequestMessage">Full request message received by the client.</param>
        /// <param name="ErrorResponse">If the validation fails, this is filled with response message to be sent to the neighbor.</param>
        /// <returns>true if the validation is successful, false otherwise.</returns>
        public static bool ValidateSharedActivityDeleteItem(SharedActivityDeleteItem DeleteItem, int Index, HashSet <string> UsedFullActivityIdsInBatch, ProxMessageBuilder MessageBuilder, ProxProtocolMessage RequestMessage, out ProxProtocolMessage ErrorResponse)
        {
            log.Trace("(Index:{0})", Index);

            bool res = false;

            ErrorResponse = null;

            if (DeleteItem == null)
            {
                DeleteItem = new SharedActivityDeleteItem();
            }

            string details = null;

            uint activityId = DeleteItem.Id;

            // 0 is not a valid activity identifier.
            if (activityId == 0)
            {
                log.Debug("Invalid activity ID '{0}'.", activityId);
                details = "delete.id";
            }

            if (details == null)
            {
                byte[] identityId      = DeleteItem.OwnerNetworkId.ToByteArray();
                bool   identityIdValid = identityId.Length == ProtocolHelper.NetworkIdentifierLength;
                if (identityIdValid)
                {
                    NeighborActivity na = new NeighborActivity()
                    {
                        ActivityId      = DeleteItem.Id,
                        OwnerIdentityId = identityId
                    };

                    string activityFullId = na.GetFullId();
                    if (!UsedFullActivityIdsInBatch.Contains(activityFullId))
                    {
                        UsedFullActivityIdsInBatch.Add(activityFullId);
                    }
                    else
                    {
                        log.Debug("Activity full ID '{0}' already processed in this request.", activityFullId);
                        details = "delete.id";
                    }
                }
                else
                {
                    log.Debug("Invalid owner network ID length '{0}'.", identityId.Length);
                    details = "delete.ownerNetworkId";
                }
            }


            if (details == null)
            {
                res = true;
            }
            else
            {
                ErrorResponse = MessageBuilder.CreateErrorInvalidValueResponse(RequestMessage, Index.ToString() + "." + details);
            }

            log.Trace("(-):{0}", res);
            return(res);
        }