package org.maachang.shutdown;

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

/**
 * シャットダウン待ちオブジェクト.
 *
 * @version 2008/03/25
 * @author masahito suzuki
 * @since MaachangBase 1.00
 */
public class WaitShutdown {
    
    /**
     * 受信タイムアウト待ち.
     */
    private static final int RECEIVE_TIMEOUT = 5000 ;
    
    /**
     * シャットダウン待ちコネクション.
     */
    private DatagramSocket connection = null ;
    
    /**
     * シャットダウン受信元ポート.
     */
    private int srcPort = -1 ;
    
    /**
     * コンストラクタ.
     */
    private WaitShutdown() {
        
    }
    
    /**
     * コンストラクタ.
     * <BR><BR>
     * シャットダウン待ちオブジェクトを生成します.
     * <BR>
     * @param port 対象のポート番号を設定します.
     * @exception Exception 例外.
     */
    public WaitShutdown( int port ) throws Exception {
        if( port <= 0 || port > 65535 ) {
            port = SendShutdown.DEFAULT_PORT ;
        }
        connection = new DatagramSocket( port,InetAddress.getByName( SendShutdown.LOCAL_ADDRESS ) ) ;
        connection.setSoTimeout( RECEIVE_TIMEOUT ) ;
    }
    
    /**
     * シャットダウン待ち.
     * <BR><BR>
     * シャットダウン待ちを行います.
     * <BR>
     * @return boolean [true]の場合、シャットダウンを受け付けました.
     */
    public boolean isShutdown() {
        boolean ret = false ;
        try {
            DatagramPacket packet = new DatagramPacket( new byte[ 512 ],512 ) ;
            connection.receive( packet ) ;
            if( packet.getLength() == SendShutdown.SHUTDOWN_BINARY.length ) {
                if( equals( packet ) == true ) {
                    srcPort = packet.getPort() ;
                    ret = true ;
                }
            }
        } catch( Exception e ) {
            ret = false ;
        }
        return ret ;
    }
    
    /**
     * シャットダウンを完了通知.
     * <BR><BR>
     * シャットダウンを完了待ちにします.
     */
    public void exitShutdown() {
        if( srcPort > 0 ) {
            try {
                connection.send( new DatagramPacket(
                    SendShutdown.SHUTDOWN_BINARY,0,
                    SendShutdown.SHUTDOWN_BINARY.length,
                    InetAddress.getByName( SendShutdown.LOCAL_ADDRESS ),
                    srcPort ) ) ;
            } catch( Exception e ) {
            }
        }
    }
    
    /**
     * 受信データが規定条件と一致する場合.
     */
    private static final boolean equals( DatagramPacket packet ) {
        if( packet.getLength() == SendShutdown.SHUTDOWN_BINARY.length ) {
            boolean ret = true ;
            int len = packet.getLength() ;
            byte[] bin = packet.getData() ;
            for( int i = 0 ; i < len ; i ++ ) {
                if( ( SendShutdown.SHUTDOWN_BINARY[i] & 0x000000ff ) != ( bin[i] & 0x000000ff ) ) {
                    ret = false ;
                    break ;
                }
            }
            return ret ;
        }
        return false ;
    }
}
