/// <summary>

        /// Sends a notification to Growl that specifies callback information and allows for additional request data.

        /// </summary>

        /// <param name="notification">The <see cref="Notification"/> to send.</param>

        /// <param name="callbackContext">The <see cref="CallbackContext"/> containing the callback information.</param>

        /// <param name="requestData">The <see cref="RequestData"/> containing the additional information.</param>

        /// <param name="state">An optional state object that will be passed into the response events associated with this request</param>

        public virtual void Notify(Notification notification, CallbackContext callbackContext, RequestData requestData, object state)

        {
            bool waitForCallback = false;

            HeaderCollection notificationHeaders = notification.ToHeaders();

            MessageBuilder mb = new MessageBuilder(RequestType.NOTIFY, this.GetKey());

            foreach (Header header in notificationHeaders)

            {
                mb.AddHeader(header);
            }



            if (callbackContext != null)

            {
                string url = callbackContext.CallbackUrl;

                if (!String.IsNullOrEmpty(url))

                {
                    mb.AddHeader(new Header(Header.NOTIFICATION_CALLBACK_TARGET, url));
                }

                else

                {
                    mb.AddHeader(new Header(Header.NOTIFICATION_CALLBACK_CONTEXT, callbackContext.Data));

                    mb.AddHeader(new Header(Header.NOTIFICATION_CALLBACK_CONTEXT_TYPE, callbackContext.Type.ToString()));

                    waitForCallback = true;
                }
            }



            // handle any additional request data

            if (requestData != null)

            {
                HeaderCollection requestDataHeaders = requestData.ToHeaders();

                foreach (Header header in requestDataHeaders)

                {
                    mb.AddHeader(header);
                }
            }



            Send(mb, OnResponseReceived, waitForCallback, state);
        }
        /// <summary>
        /// Registers the specified application and notification types and allows for additional request data.
        /// </summary>
        /// <param name="application">The <see cref="Application"/> to register.</param>
        /// <param name="notificationTypes">The <see cref="NotificationType"/>s to register.</param>
        /// <param name="requestData">The <see cref="RequestData"/> containing the additional information.</param>
        /// <param name="state">An optional state object that will be passed into the response events associated with this request</param>
        public virtual void Register(Application application, NotificationType[] notificationTypes, RequestData requestData, object state)
        {
            HeaderCollection        appHeaders    = application.ToHeaders();
            List <HeaderCollection> notifications = new List <HeaderCollection>();

            foreach (NotificationType notificationType in notificationTypes)
            {
                HeaderCollection notificationHeaders = notificationType.ToHeaders();
                notifications.Add(notificationHeaders);
            }

            MessageBuilder mb = new MessageBuilder(RequestType.REGISTER, this.GetKey());

            foreach (Header header in appHeaders)
            {
                mb.AddHeader(header);
            }
            mb.AddHeader(new Header(Header.NOTIFICATIONS_COUNT, notificationTypes.Length.ToString()));

            // handle any additional request data
            if (requestData != null)
            {
                HeaderCollection requestDataHeaders = requestData.ToHeaders();
                foreach (Header header in requestDataHeaders)
                {
                    mb.AddHeader(header);
                }
            }

            foreach (HeaderCollection headers in notifications)
            {
                MessageSection ms = new MessageSection();
                foreach (Header header in headers)
                {
                    ms.AddHeader(header);
                }
                mb.AddMessageSection(ms);
            }

            Send(mb, OnResponseReceived, false, state);
        }