///////////////////////////////////////////////////////////////////////////////
// jcomet.js
// Copyright (c) 2007 masahito suzuki, Inc. All Rights Reserved.
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
// 接続用Jsonpオブジェクト.
///////////////////////////////////////////////////////////////////////////////
var MJsonp = function() {} ;
MJsonp.prototype = {
    // インスタンス名.
    instanceName: null,
    // timeout.
    timeout: 0,
    // 戻り情報.
    resultInfo: null,
    // 処理終了時間.
    resultTime: new Date().getTime(),
    // 初期化.
    init: function(instanceName,timeout) {
        if( useString( instanceName ) == false ) {
            return -1 ;
        }
        if( isNull( timeout ) && isNumeric( ""+timeout ) == true ) {
            this.timeout = timeout ;
        }
        else {
            this.timeout = 0 ;
        }
        this.instanceName = trim( instanceName ) ;
        return 0 ;
    },
    // オブジェクト破棄.
    destroy: function() {
        this.instanceName = null ;
        this.timeout = 0 ;
        this.resultInfo = null ;
        this.resultTime = null ;
    },
    // getJson
    getJson: function(url,method,params) {
        if( useString( this.instanceName ) == false || useString( url ) == false ) {
            return -1 ;
        }
        if( useString( method ) == true ) {
            method = trim( method ) ;
        }
        else {
            method = null ;
        }
        if( useString( params ) == false ) {
            params = "" ;
        }
        else if( startsWith( params,"&" ) ) {
            params = params.substring( 1 ) ;
        }
        // インスタンス名を設定.
        if( useString( params ) == false ) {
            params = "ins="+this.instanceName+".resultJson" ;
        }
        else {
            params += "&ins="+this.instanceName+".resultJson" ;
        }
        // 処理結果を受け取るメソッド名を設定.
        if( method != null ) {
            if( useString( params ) == false ) {
                params = "method="+method ;
            }
            else {
                params += "&method="+method ;
            }
        }
        // コネクションタイムアウトを設定.
        if( this.timeout > 0 ) {
            if( useString( params ) == false ) {
                params = "timeout="+this.timeout ;
            }
            else {
                params += "&timeout="+this.timeout ;
            }
        }
        // 戻り情報を設定.
        if( this.resultInfo != null ) {
            for( var k in this.resultInfo ) {
                params += "&"+k+"="+this.resultInfo[k] ;
            }
        }
        return jsonp( url,params ) ;
    },
    // jsonp処理結果格納処理.
    resultJson: function( resultInfo ) {
        if( isNull( resultInfo ) == false ) {
            this.resultInfo = resultInfo ;
        }
        else {
            this.resultInfo = null ;
        }
        this.resultTime = new Date().getTime() ;
    }
} ;

///////////////////////////////////////////////////////////////////////////////
// 接続用JCometオブジェクト.
///////////////////////////////////////////////////////////////////////////////
var MJComet = function() {} ;
MJComet.prototype = {
    // インスタンス名.
    instanceName: null,
    // グループID.
    groupId: null,
    // コネクションURL.
    url: null,
    // 基本パラメータ.
    params: null,
    // 拡張パラメータ.
    addParams: null,
    // コネクションオブジェクト.
    mjsonp: null,
    // コネクター.
    mjconn: null,
    // 初期化処理.
    init: function( instanceName,url,params,groupId,timeout ) {
        if( useString( instanceName ) == false || useString( url ) == false ) {
            return -1 ;
        }
        if( useString( params ) == false ) {
            params = null ;
        }
        if( useString( groupId ) == false ) {
            groupId = null ;
        }
        if( isNull( groupId ) ) {
            groupId = "jsonp~"+ MD5_hexhash( url ) + "~" + url.length ;
        }
        this.instanceName = trim( instanceName ) ;
        this.groupId = groupId ;
        this.url = url ;
        if( isNull( params ) ) {
            params = "groupId="+groupId ;
        }
        else {
            params += "&groupId="+groupId ;
        }
        this.params = params ;
        
        this.mjconn = new MjConnector() ;
        this.mjsonp = new MJsonp() ;
        this.mjconn.startup() ;
        return this.mjsonp.init( instanceName+".mjsonp",timeout ) ;
    },
    // オブジェクト破棄.
    destroy: function() {
        if( isNull( this.mjsonp ) == false ) {
            this.mjsonp.destroy() ;
        }
        if( isNull( this.mjcon ) == false ) {
            this.mjcon.destroy() ;
        }
        this.mjsonp = null ;
        this.mjcon = null ;
        this.instanceName = null ;
        this.url = null ;
        this.params = null ;
    },
    // 指定URLにデータ送信.
    send: function( url,method,params ) {
        if( useString( url ) == false || useString( method ) == false ) {
            return -1 ;
        }
        if( useString( params ) == false ) {
            params = null ;
        }
        method = trim( method ) ;
        if( useString( params ) == false ) {
            params = "method="+method+"&groupId="+this.groupId ;
        }
        else {
            params += "&method="+method+"&groupId="+this.groupId ;
        }
        return jsonp( url,params ) ;
    },
    // 処理結果コールバック.
    callback: function( args ) {
        // 処理結果の振舞いを実装.
    },
    // コメット開始処理.
    start: function( addParams ) {
        if( isNull( this.instanceName ) == true ) {
            return -1 ;
        }
        if( isNull( addParams ) ) {
            addParams = null ;
        }
        this.addParams = addParams ;
        this.mjconn.connection( this ) ;
        return 0 ;
    },
    // privateコネクションコールバック.
    private_call: function( args ) {
        if( isNull( args ) ) {
            args = null ;
        }
        // 戻り値に変数が存在しない場合は、
        // 処理しない.
        if( args != null ) {
            this.addParams = this.mjsonp.resultInfo ;
            this.callback( args ) ;
        }
        // 再接続.
        this.private_exec() ;
    },
    // privateコネクション実装.
    private_exec: function() {
        var pms = this.params ;
        if( this.addParams != null && this.addParams.length == 1 ) {
            var addPms = this.addParams[0] ;
            for( var k in addPms ) {
                pms += "&"+k+"="+addPms[k] ;
            }
        }
        return this.mjsonp.getJson( this.url,this.instanceName+".private_call",pms ) ;
    }
} ;

// jcomet再コネクション待ちオブジェクト.
var MjConnector = function() {} ;
MjConnector.prototype = {
    jcomet: null,
    settingTime: null,
    handle: null,
    startup: function() {
        if( isOPERA == false ) {
            this.handle = setInterval( this.interval.bind( this ),500 ) ;
        }
    },
    shutdown: function() {
        if( isOPERA == false ) {
            if( this.handle != null ) {
                clearInterval( this.handle ) ;
                this.mjcon = null ;
            }
        }
    },
    connection: function( jcomet ) {
        if( isOPERA == true ) {
            jcomet.private_exec() ;
        }
        else {
            this.settingTime = new Date().getTime() ;
            this.jcomet = jcomet ;
        }
    },
    interval: function() {
        if( this.jcomet != null && ( this.settingTime + 500 ) <= new Date().getTime() ) {
            var x = this.jcomet ;
            this.jcomet = null ;
            x.private_exec() ;
        }
    }
} ;
