/*
 * LOGICAL-PARADOX.ORG
 * Copyright (C)2005 satoshi akabane(akabane@logical-paradox.org)
 * $Id: SocketWriter.java,v 1.3 2005/09/17 17:36:00 rampil Exp $
 */
package org.logical_paradox.vsan.tools.console.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.Socket;

import org.logical_paradox.common.io.ExpandableBuffer;
import org.logical_paradox.common.util.ByteStreamConverter;
import org.logical_paradox.common.util.StringUtils;
import org.logical_paradox.vsan.dac.DacConfig;
import org.logical_paradox.vsan.dac.Response;

/**
 * ソケットライター
 * DACに対してデータを送信します
 * @author satoshi akabane@logical-paradox.org
 * @version $Revision: 1.3 $
 */
public class SocketWriter {
	/**
	 * データをDACに対して送信します
	 * 何らかの回答があれば、回答されたデータを返します<br>
	 * ignoreオプションにtrueを設定すると、通信時に発生したI/O例外を無視します
	 * @param dac 接続先
	 * @param data 送信するデータ
	 * @param ignore エラー無視フラグ(true:無視する / false:無視せず報告する)
	 * @return DACからの回答
	 * @throws IOException 通信中に発生したI/O例外
	 */
	public static final Response send(String dac, byte[] data, boolean ignore) throws IOException {
		if(StringUtils.isEmpty(dac) == true) {
			dac = "localhost";
		}

		// ソケットを作成する
		Socket socket = null;
		if(dac.indexOf(":") == dac.lastIndexOf(":")) {
			String[] tokens = dac.split(":");
			if(tokens.length == 1) {
				socket = new Socket(tokens[0], DacConfig.DEFAULT_PORT_NUMBER);
			} else {
				socket = new Socket(tokens[0], Integer.parseInt(tokens[1]));
			}
		} else {
			throw new IOException("illegal host format for 'dac'.");
		}

		byte[] rc = new byte[0];
		int resultcode = -1;

		try {
			// 通信
			BufferedOutputStream bw = new BufferedOutputStream(socket.getOutputStream());
			bw.write(data);
			bw.flush();

			// データ受信
			ExpandableBuffer exb = new ExpandableBuffer();

			// パケット数受信
			BufferedInputStream bi = new BufferedInputStream(socket.getInputStream());

			// 実行ステータス受信
			byte[] status = new byte[4];
			bi.read(status);
			resultcode = ByteStreamConverter.getInt(status);

			byte[] packetnum = new byte[4];
			bi.read(packetnum);

			int packets = ByteStreamConverter.getInt(packetnum);

			// パケットの読み込み
			byte[] packetsz = new byte[4];
			for(int i = 0; i < packets; i++) {
				bi.read(packetsz);
				int packetlen = ByteStreamConverter.getInt(packetsz);
				byte[] body = new byte[packetlen];

				// データの受信
				bi.read(body);
				exb.write(body);
			}

			// 全てのパケットの受信が完了したのでソケットを閉じる
			socket.close();

			rc = exb.byteStream();
		} catch(IOException e) {
			if(ignore == false) {
				throw e;
			}
		}
		return new Response(resultcode, rc);
	}
}
