package jp.ehobby.io;

import java.io.IOException;
import java.io.Writer;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;


/**
 * Syslog を書き出す Writer クラス.
 *
 * @author kei-n
 * @since 2002-2012
 */
public class SyslogWriter extends Writer {

	/** syslog サーバのポート番号(514).					*/
	public static final int SYSLOG_SERVER_PORT = 514;


	/** syslog サーバに送信する最大メッセージサイズ.	*/
	private static final int MAX_SYSLOG_MESSAGE_SIZE = 1024;


	/** syslog サーバのアドレス.						*/
	private final InetAddress    serverAddress;


	/** syslog サーバのポート番号.						*/
	private final int            serverPort;


	/** syslog サーバへデータ送信のためのソケット.		*/
	private final DatagramSocket dgramSocket;


	/**
	 * 指定されたホストに対して syslog を書き出す SyslogWriter を構築します.
	 *
	 * @param host ホストまたはIPアドレス
	 * @throws SocketException      Datagramソケット生成失敗
	 * @throws UnknownHostException 不明なホスト名
	 */
	public SyslogWriter(final String host)
			throws SocketException, UnknownHostException {
		this(host, SYSLOG_SERVER_PORT);
	}


	/**
	 * 指定されたホスト、ポートに対して syslog を書き出す SyslogWriter を構築します.
	 *
	 * @param host ホストまたはIPアドレス
	 * @param port ポート番号
	 * @throws SocketException      Datagramソケット生成失敗
	 * @throws UnknownHostException 不明なホスト名
	 */
	public SyslogWriter(final String host, final int port)
			throws SocketException, UnknownHostException {
		this.serverAddress = InetAddress.getByName(host);
		this.serverPort    = port;
		this.dgramSocket   = new DatagramSocket();
	}


	/**
	 * syslog サーバに指定された message を送信します.
	 *
	 * @param message メッセージ
	 * @throws IOException メッセージ送信エラー
	 */
	@Override
	public void write(final String message) throws IOException {
		byte[] sendData = message.getBytes();
		int    sendSize = sendData.length;

		// syslog は最大 1024 byte までメッセージ送信可能
		if (sendSize >= MAX_SYSLOG_MESSAGE_SIZE) {
			sendSize = MAX_SYSLOG_MESSAGE_SIZE;
		}

		DatagramPacket packet = new DatagramPacket(sendData, sendSize, this.serverAddress, this.serverPort);
		this.dgramSocket.send(packet);
	}


	@Override
	public void write(char[] cbuf, int off, int len) throws IOException {
		String message = new String(cbuf, off, len);
		this.write(message);
	}


	@Override
	public void flush() throws IOException {
		// Nothign to do.
	}


	@Override
	public void close() throws IOException {
		this.dgramSocket.close();
	}

}
