/*
 * Copyright (C) 2010 Teleal GmbH, Switzerland
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.teleal.cling.protocol.sync;

import java.util.logging.Logger;
import org.teleal.cling.UpnpService;
import org.teleal.cling.model.gena.LocalGENASubscription;
import org.teleal.cling.model.message.StreamResponseMessage;
import org.teleal.cling.model.message.gena.OutgoingEventRequestMessage;
import org.teleal.cling.protocol.SendingSync;

import java.net.URL;


public class SendingEvent extends SendingSync<OutgoingEventRequestMessage, StreamResponseMessage> {

    protected static Logger log = Logger.getLogger(SendingEvent.class.getName());

    final protected LocalGENASubscription subscription;

    public SendingEvent(UpnpService upnpService, LocalGENASubscription subscription) {
        super(upnpService, null); // Special case, we actually need to send several messages to each callback URL
        this.subscription = subscription;
    }

    protected StreamResponseMessage executeSync() {

        log.fine("Sending event for subscription: " + subscription);

        StreamResponseMessage lastResponse = null;

        // If a particular action execution (or simple method call) on a LocalService fires several property change
        // events (maybe because several state variable values changed), then this protocol will be executed
        // concurrently on the same subscription instance. To prevent races on sequence increments, we synchronize.
        synchronized (subscription) {

            for (URL url : subscription.getCallbackURLs()) {

                if (subscription.getCurrentSequence().getValue() == 0) {
                    log.fine("Sending initial event message to callback URL: " + url);
                } else {
                    log.fine("Sending event message '"+subscription.getCurrentSequence()+"' to callback URL: " + url);
                }

                OutgoingEventRequestMessage requestMessage = new OutgoingEventRequestMessage(subscription, url);

                // Write the body
                getUpnpService().getConfiguration().getGenaEventProcessor().writeBody(requestMessage);

                // Always increment sequence now, as (its value) has already been set on the headers and the
                // next event will use the incremented value
                subscription.incrementSequence();

                // Send request
                lastResponse = getUpnpService().getRouter().send(requestMessage);
                log.fine("Received event callback response: " + lastResponse);

            }
        }

        // It's not really used, so just return the last one - we have only one callback URL most of the
        // time anyway
        return lastResponse;

    }
}