package org.maachang.session.server.protocol ;

import org.maachang.session.engine.PersistenceEngine;
import org.maachang.util.ConvertParam;

/**
 * サーバ通信処理.
 * 
 * @version 2008/05/25
 * @author masahito suzuki
 * @since PersistenceSession 1.00
 */
public class IOServerProtocol {
    
    /**
     * サーバプロトコルを処理.
     * @param pse PersistenceSessionEngineを設定します.
     * @param binary 受信バイナリを設定します.
     * @param offset 受信バイナリオフセット値を設定します.
     * @return ServerProtocol 符号するサーバプロトコルが返されます.
     * @exception Exception 例外.
     */
    public static final ServerProtocol execution( PersistenceEngine pse,
        byte[] binary,int offset ) throws Exception {
        int type = -1 ;
        try {
            int p = offset ;
            type = ConvertParam.convertInt( p,binary ) ;
            type = type & ServerProtocol.TYPE_MASK ;
            p += 4 ;
            switch( type ) {
                case ServerProtocol.TYPE_CREATE_SESSION :
                    return createSession( pse,p,binary ) ;
                case ServerProtocol.TYPE_USE_SESSION_ID :
                    return useSession( pse,p,binary ) ;
                case ServerProtocol.TYPE_DELETE_SESSION_ID :
                    return deleteSession( pse,p,binary ) ;
                case ServerProtocol.TYPE_UPDATE_SESSION_ID :
                    return updateSession( pse,p,binary ) ;
                case ServerProtocol.TYPE_USE_TO_SESSOIN_ID :
                    return useToSessionId( pse,p,binary ) ;
                case ServerProtocol.TYPE_DELETE_SESSION_TIME :
                    return deleteSessionTime( pse,p,binary ) ;
                case ServerProtocol.TYPE_PUT_VALUE :
                    return putValue( pse,p,binary ) ;
                case ServerProtocol.TYPE_REMOVE_VALUE :
                    return removeValue( pse,p,binary ) ;
                case ServerProtocol.TYPE_GET_VALUE :
                    return getValue( pse,p,binary ) ;
            }
            return new SvErrorProtocol( "プロトコルタイプ[" + type + "]は不正です" ) ;
        } catch( Exception e ) {
            e.printStackTrace() ;
            String s = e.getMessage() ;
            if( s == null || ( s = s.trim() ).length() <= 0 ) {
                s = "例外[" + e.getClass().getName() + "]が発生しました" ;
            }
            else {
                s = e.getClass().getName() + ":" + s ;
            }
            return new SvErrorProtocol( "["+type+"] "+s ) ;
        }
    }
    
    private static ServerProtocol createSession( PersistenceEngine pse,int p,byte[] binary )
        throws Exception {
        SvCreateSessionIdProtocol ret = new SvCreateSessionIdProtocol() ;
        String s = pse.createSessionId() ;
        if( s == null || s.length() <= 0 ) {
            return new SvErrorProtocol( "セッションIDの取得に失敗しました" ) ;
        }
        ret.setResult( s ) ;
        return ret ;
    }
    
    private static ServerProtocol useSession( PersistenceEngine pse,int p,byte[] binary )
        throws Exception {
        SvUseSessionIdProtocol ret = new SvUseSessionIdProtocol( binary,p ) ;
        if( ret.getSessionId() == null ) {
            return new SvErrorProtocol( "セッションIDが指定されていません" ) ;
        }
        boolean flg = pse.containsKey( ret.getSessionId() ) ;
        ret.setResult( new Boolean( flg ) ) ;
        return ret ;
    }
    
    private static ServerProtocol deleteSession( PersistenceEngine pse,int p,byte[] binary )
        throws Exception {
        SvDeleteSessionIdProtocol ret = new SvDeleteSessionIdProtocol( binary,p ) ;
        if( ret.getSessionId() == null ) {
            return new SvErrorProtocol( "セッションIDが指定されていません" ) ;
        }
        pse.remove( ret.getSessionId() ) ;
        ret.setResult( null ) ;
        return ret ;
    }
    
    private static ServerProtocol updateSession( PersistenceEngine pse,int p,byte[] binary )
        throws Exception {
        SvUpdateSessionIdProtocol ret = new SvUpdateSessionIdProtocol( binary,p ) ;
        if( ret.getSessionId() == null ) {
            return new SvErrorProtocol( "セッションIDが指定されていません" ) ;
        }
        long time = pse.getLastUpdateTime( ret.getSessionId() ) ;
        ret.setResult( new Long( time ) ) ;
        return ret ;
    }
    
    private static ServerProtocol useToSessionId( PersistenceEngine pse,int p,byte[] binary )
        throws Exception {
        SvUseToSessionIdProtocol ret = new SvUseToSessionIdProtocol( binary,p ) ;
        if( ret.getSessionId() == null || pse.containsKey( ret.getSessionId() ) == false ) {
            ret.setResult( pse.createSessionId() ) ;
        }
        else {
            ret.setResult( ret.getSessionId() ) ;
        }
        return ret ;
    }
    
    private static ServerProtocol deleteSessionTime( PersistenceEngine pse,int p,byte[] binary )
        throws Exception {
        SvDeleteSessionTimeProtocol ret = new SvDeleteSessionTimeProtocol() ;
        long time = pse.getDeleteSessionTime() ;
        ret.setResult( new Long( time ) ) ;
        return ret ;
    }
    
    private static ServerProtocol putValue( PersistenceEngine pse,int p,byte[] binary )
        throws Exception {
        SvPutSessionKeyProtocol ret = new SvPutSessionKeyProtocol( binary,p ) ;
        if( ret.getSessionId() == null || ret.getKey() == null || ret.getValue() == null ) {
            if( ret.getSessionId() == null ) {
                return new SvErrorProtocol( "セッションIDが指定されていません" ) ;
            }
            if( ret.getKey() == null ) {
                return new SvErrorProtocol( "要素Keyが指定されていません" ) ;
            }
            if( ret.getValue() == null ) {
                return new SvErrorProtocol( "要素Valueが指定されていません" ) ;
            }
        }
        pse.put( ret.getSessionId(),ret.getKey(),ret.getValue() ) ;
        ret.setResult( null ) ;
        return ret ;
    }
    
    private static ServerProtocol removeValue( PersistenceEngine pse,int p,byte[] binary )
        throws Exception {
        SvRemoveSessionKeyProtocol ret = new SvRemoveSessionKeyProtocol( binary,p ) ;
        if( ret.getSessionId() == null || ret.getKey() == null ) {
            if( ret.getSessionId() == null ) {
                return new SvErrorProtocol( "セッションIDが指定されていません" ) ;
            }
            if( ret.getKey() == null ) {
                return new SvErrorProtocol( "要素Keyが指定されていません" ) ;
            }
        }
        pse.remove( ret.getSessionId(),ret.getKey() ) ;
        ret.setResult( null ) ;
        return ret ;
    }
    
    private static ServerProtocol getValue( PersistenceEngine pse,int p,byte[] binary )
        throws Exception {
        SvGetSessionKeyProtocol ret = new SvGetSessionKeyProtocol( binary,p ) ;
        if( ret.getSessionId() == null || ret.getKey() == null ) {
            if( ret.getSessionId() == null ) {
                return new SvErrorProtocol( "セッションIDが指定されていません" ) ;
            }
            if( ret.getKey() == null ) {
                return new SvErrorProtocol( "要素Keyが指定されていません" ) ;
            }
        }
        ret.setResult( pse.get( ret.getSessionId(),ret.getKey() ) ) ;
        return ret ;
    }
}

