/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2006 Bull S.A.
 * Contact: jonas-team@ow2.org
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation; either version 2.1 of the License, or any later
 * version.
 *
 * This library 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 Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.discovery.multicast.utils;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

import org.ow2.jonas.discovery.base.DiscHelper;
import org.ow2.jonas.discovery.base.comm.DiscMessage;

/**
 * This class helps creating a byte[] to be sent in a datagram when sending a DiscMessage, and helps
 * reading the sent DiscMessage on receiving an object when this object is actually a DiscMessage.
 * @author Adriana Danes
 */
public class DiscoveryHelper extends DiscHelper{
    @SuppressWarnings("unused")
    private static int DISC_GREETING = 2;
    /**
     *
     */
    private static int RECEIVE_BUFFER_SIZE = 1024;

    /**
     * Send a discovery message to a destination via a datagram socket (UDP).
     * The message is instance of DiscMessage class or one of its subclasses
     * (DiscEvent, DiscGreeting).
     * The socket may be simple or multicast.
     * @param msg object to be sent
     * @param socket sending point
     * @param destAddress destination address (maybe a multicast address)
     * @param destPort destination port number
     * @throws IOException if an I/O error occurs during sending,
     * or if can't create an ObjectOutputStream to write into it the message to send
     */
    @SuppressWarnings("unused")
    private void sendDiscoveryMessage(DiscMessage msg, DatagramSocket socket
            , InetAddress destAddress, int destPort) throws IOException {

        byte[] messageBytes = objectToBytes(msg);
        // Create datagram packet for sending
        DatagramPacket packet = new DatagramPacket(messageBytes, messageBytes.length
                , destAddress, destPort);
        sendPacket(socket, packet);
    }

    /**
     * Receive a discovery message via a datagram socket (UDP).
     * The message is instance of DiscMessage class or one of its subclasses
     * (DiscEvent, DiscGreeting).
     * The socket may be simple or multicast which were joind by the caller.
     * @param socket receiving point
     * @return received object
     * @throws IOException if an I/O error occurs during receiving,
     * or if can't create an ObjectInputStream to read the object into it.
     * @throws ClassNotFoundException Class of a serialized object cannot be found
     */
    @SuppressWarnings("unused")
    private DiscMessage receiveDiscoveryMessage(DatagramSocket socket) throws IOException, ClassNotFoundException, RuntimeException {
        // Create datagram for receiving
        DatagramPacket packet = new DatagramPacket(new byte[RECEIVE_BUFFER_SIZE], RECEIVE_BUFFER_SIZE);
        receivePacket(socket, packet);
        Object ret = null;
        try {
             ret = bytesToObject(packet.getData());
        }catch (RuntimeException e) {
        	throw new RuntimeException("The host has received other packet than DatagramSocket packet. That caused following exception: "+e);
        }catch (IOException e) {
        	throw new IOException(" The host has received other packet than DatagramSocket packet. That caused following exception: "+e);
		}
        return (DiscMessage) ret;
    }
    /**
     *
     * @param socket May be a unicast DatagramSocket or a MulticastSocket
     * @param packet datagram packet to send
     * @throws IOException if an I/O error occurs during sending
     */
    private void sendPacket(DatagramSocket socket, DatagramPacket packet) throws IOException {
        socket.send(packet);
    }
    /**
     *
     * @param socket May be a unicast DatagramSocket or a MulticastSocket which the caller joind
     * @param packet datagram packet to send
     * @throws IOException if an I/O error occurs during receiving
     */
    private void receivePacket(DatagramSocket socket, DatagramPacket packet) throws IOException {
        socket.receive(packet);
    }
}