package jp.hasc.hupserver;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.HashMap;

/*
 * HUPWorker 各クライアント毎のサーバ
 */
public class HUPWorker implements Runnable{
	static HUPReporter logger;
	static final int BufSize = 1024;
	int dPort_;
	HUPServer hus_;
	InetAddress dstAddr_;
	DatagramSocket sSock_;
	DatagramSocket ds_;
	DatagramPacket dp_;
	Thread workerThread_;
	String myStr_;
	byte[] buf_ = new byte[BufSize];
	int sPort_; // 自分のサービス用のポート
	static HashMap<InetAddrAndPort,Integer> mapAddr = new HashMap<InetAddrAndPort, Integer>();
	
	public HUPWorker(InetAddrAndPort dAddr,HUPServer hus){
//		sSock_ = sSock;
		hus_ = hus;
		Integer pt = mapAddr.get(dAddr.ia_);
		dstAddr_ =dAddr.ia_;
		dPort_ = dAddr.port_;
		if (pt == null){ // 同じIPが使われていない場合
			try {
				ds_ = new DatagramSocket();
				sPort_ = ds_.getLocalPort();
				mapAddr.put(dAddr,new Integer(sPort_));
			} catch (SocketException e) {
				sPort_ = -1;
				e.printStackTrace();
			}			
		}else {// 過去のポートと同じもので作成してみる
			try{
				ds_ = new DatagramSocket(pt.intValue());
				sPort_ = ds_.getPort();
			}catch( SocketException e){
				mapAddr.remove(dAddr);
				try {// ポートを変えて作成してみる
					ds_ = new DatagramSocket();
					sPort_ = ds_.getPort();
					mapAddr.put(dAddr,new Integer(sPort_));
				} catch (SocketException e2) {
					sPort_ = -1;
					e.printStackTrace();
				}			
			}
		}
		if(sPort_ > 0) {
			workerThread_ = new Thread(this);
			myStr_ = ""+sPort_+"->"+dstAddr_.getHostAddress()+":"+dPort_;
			logger.addWorker(myStr_);
		}
	}
	public boolean loopflag_ = true;
	@Override
	public void run() {// 
		dp_ = new DatagramPacket(buf_,BufSize);
		logger.logln("Now Waiting for "+ds_.getLocalAddress()+":"+ds_.getLocalPort());
		logger.logln("Transfer for "+dstAddr_+":"+dPort_);
		while (loopflag_){
			try {
				ds_.receive(dp_); // 受け取ったパケットを
//				logger.logln("get packet"+dp_.getAddress()+":"+dp_.getPort());
//				logger.log(".");
				dp_.setAddress(dstAddr_);
				dp_.setPort(dPort_);
//				sSock_.send(dp_); // サーバソケットで送信
				hus_.sendPacket(dp_);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		logger.removeWorker(myStr_);
	}
}
