/*
**    File: fw_io.js
**    Created by: Zolotarev Anton (http://sourceforge.net/projects/ajaxos)
**
**    License Information:
**    -------------------------------------------------------------------------
**    Copyright (C) 2005 Zolotarev Anton
**
**    This program is free software; you can redistribute it and/or modify it
**    under the terms of the GNU General Public License as published by the
**    Free Software Foundation; either version 2 of the License, or (at your
**    option) any later version.
**    
**    This program is distributed in the hope that it will be useful, but
**    WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
**    General Public License for more details.
**    
**    You should have received a copy of the GNU General Public License along
**    with this program; if not, write to the Free Software Foundation, Inc.,
**    59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

if(!fw.io)
fw.io = function(){
    var out = {};
    for(var i in fw.io) out[i] = (typeof fw.io[i]);
    out['version'] = "v0.20";
    return out;
}

fw.io._handlers = {};
fw.io._type = 'IO';
fw.io._stype = 'IOID';
fw.io._ioSendTo	= 10000;
fw.io._ioWorkTo	= 50;
fw.io._ioMaxUrl	= 2000;

fw.io._dummy = function(){}

fw.io._AX = [
    //"Msxml2.XMLHTTP.6.0",
    //"Msxml2.XMLHTTP.5.0",
    //"Msxml2.XMLHTTP.4.0",
    //"Msxml2.XMLHTTP.3.0",
    "Msxml2.XMLHTTP",
    "Microsoft.XMLHTTP"
];

fw.io.getXmlO = function(){
    var req = null;
    for(var i=0;(!req && (i < this._AX.length));i++){
        try{
            req = new ActiveXObject(this._AX[i]);
            fw.info.io = this._AX[i];
        }catch(e){}
    }
    if(!req) try{ req = new XMLHttpRequest(); fw.info.io = 'Native XMLHTTP'; }catch(e) {}
    
    //alert(req);
    return req;
}

fw.io.create = function(furl,fpost,fmode,fto){// fmode: undef - sync=0, false - async=1, true - listen=2(fto - time)
	
		
    var hndlXML = null, hndlTO = null, hndlWRK = null;
    var id = fw.info.counter(this._type);
    
    if(furl && !fw.data.isStr(furl)) {return fw.data.error(2);}
    fpost = fpost? true : false;
    fmode = (fw.data.isSet(fmode)? (fmode? 2 : 1) : 0);
    
    hndlXML = this.getXmlO();
    if(!hndlXML) {
    	    	return fw.data.error(4);
    }	
    
    if(fmode){
        hndlTO = fw.timer.create('fw.io._timeout', id);
        hndlWRK = fw.timer.create('fw.io._sender', id);
        
        if(fw.data.isError(hndlTO)) return hndlTO;
        if(fw.data.isError(hndlWRK)) return hndlWRK;
    }
    
    this._handlers[id] = {
        hXML:   hndlXML,
        hTO:    hndlTO,
        hWRK:   hndlWRK,
        mode:   fmode,
        post:   fpost,
        url:    furl,
        to:     (fw.data.isUnd(fto)? this._ioSendTo : fto),
        stack:  [],
        pack:   null,
        frame:  0,
        ready:	true,
        stoped:	false,
        grand:  (furl.search('http://') != -1)
    };
    
    
    return id;
}

fw.io.reopen = function(id){
	if(!fw.data.isType(id, this._type)) return fw.data.error(2);
	var el = this._handlers[id];
	if(!el) return fw.data.error(3);
	
	try{
		el.hXML.onreadystatechange = this._dummy;
		el.hXML.abort();
	}catch(e){}
	try{ delete el.hXML; }catch(e){}
	
	var hndlXML = this.getXmlO();
	if(!hndlXML) return fw.data.error(4);
	
	el.ready = true;
	el.hXML = hndlXML;
	return true;
}

fw.io.close = function(id){
    if(!fw.data.isType(id, this._type)) return fw.data.error(2);
    if(!this._handlers[id]) return fw.data.error(3);
    
    this.abort(id,true);
    try{ delete this._handlers[id].hXML; }catch(e){}
    this._handlers[id] = null;
    return true;
}

fw.io.abort = function(id,all){
    if(!fw.data.isType(id, this._type)) return fw.data.error(2);
    var el = this._handlers[id];
    if(!el) return fw.data.error(3);
    
    try{
        fw.timer.stop(el.hTO);
        el.hXML.onreadystatechange = this._dummy;
        el.frame = 0;
        el.pack = null;
        if(all) el.stack = [];
        el.hXML.abort();
        el.ready = true;
    }catch(e){ return false; }
    return true;
}

fw.io.error = function(id,sid,code,msg){
	if(fw.data.isType(id, this._type)){
		var el = this._handlers[id];
		if(el){
			fw.timer.stop(el.hTO);
			el.stoped = true;
			el.ready = true;
//			if(code == 1 || code == 2) this.reopen(id);
		}
	}
	var m = ['IO','ERROR',id];
	if(sid) m.push(sid);
	fw.mess.Msg(m, code, msg);
}

fw.io.resume = function(id){
	if(!fw.data.isType(id, this._type)) return fw.data.error(2);
	var el = this._handlers[id];
	if(!el) return fw.data.error(3);
	if(!el.pack)  return fw.data.error(3);
	if(el.mode){
		if(el.stoped){
			el.stoped = false;
//			if(!fw.timer.info(el.hWRK).work)
			fw.timer.start(el.hWRK, this._ioWorkTo, 1, 1);
			fw.mess.Msg(['IO','BEGIN',id]);
		}
	}else{
		return this._sender(id);
	}
	return el.pack.s;
}

fw.io.transfer = function(id,data,sid){
	
    if(!fw.data.isType(id, this._type)) return fw.data.error(2);
    //if(fw.data.isUnd(data)) data = true;
    if(!data) data = true;
    else if(!fw.data.isObj(data)) return fw.data.error(2);
    var el = this._handlers[id];
    if(!el) return fw.data.error(3);
    if(sid && !fw.data.isStr(sid)) return fw.data.error(2);
    if(!sid) sid = fw.info.counter(this._stype);
    
        
    el.stack.push({s:sid, d:data});
    if(el.mode){
        if(!fw.timer.info(el.hWRK).work && el.ready && !el.stoped){
            fw.timer.start(el.hWRK, this._ioWorkTo, 1, 1);
            fw.mess.Msg(['IO','BEGIN',id]);
        }
    }else{
    
    	
    	 	
        return  this._sender(id);
    }
    return sid;
}

fw.io._timeout = function(id){
    if(fw.data.isType(id, this._type)){
        var el = fw.io._handlers[id];
        if(el){
            if(el.mode == 1){
            	el.hXML.abort();
            	el.stoped = true;
            	el.ready = true;
                fw.mess.Msg(['IO','TIMEOUT', id, el.pack.s]);
            }else{
                try{
                    rst = el.hXML.readyState;
                    if(rst < 3) return;
                    var out, fr = el.hXML.responseText;
                    if(fr.length > el.frame){
                        out = fr.slice(el.frame);
                        fw.mess.Msg(['IO','FRAME', id, el.pack.s], out);
                        el.frame = fr.length;
                    }
                }catch(e){ this.error(id, el.pack.s, 4, 'Bad Received Frame'); }
            }
        }
    }
}

fw.io._receiver = function(id,data,result){
	
	if(fw.data.isType(id, this._type)){
		var el = this._handlers[id];
		if(el){
		
			el.ready = true;
			fw.timer.stop(el.hTO);
			el.hXML.abort();
			
			if(fw.info.browser.isOp && !data) result = false;
				
			if(result && fw.data.isSet(data)){
				
				if(el.mode == 2) data = data.slice(el.frame);{
				fw.mess.Msg(['IO','RECEIVE', id, el.pack.s], data);
			}
				el.frame = 0;
				el.pack = null;
				if(el.stack.length){
					fw.timer.start(el.hWRK, this._ioWorkTo, 1, 1);
						
				}else{
					fw.mess.Msg(['IO','END',id]);
				}
			}else {this.error(id, el.pack.s, 5, 'Wrong Response Packet');}
		}
	}
}

fw.io._sender = function(id){
	
	//alert("_sender");
	
	  var _mtd, _data, _url, _asc = false, res = false;
    
    if(fw.data.isType(id, this._type)){
    	
       	
        var el = this._handlers[id];
        if(el.stoped) return res;
        
        if((el && el.stack.length) || el.pack){
            if(!el.pack) el.pack = el.stack.shift();
            _data = (el.pack && (el.pack.d !== true))? fw.data.plane(el.pack.d, !el.post) : null;
            
            if(el.post){
                _mtd = 'POST';
                _url = el.url;
            }else{
                _mtd = 'GET';
                _url = _data? (el.url + (el.url.indexOf('?')>=0? '&' : '?') + _data) : el.url;
								//alert(_url);
                _data = null;
                if(_url.length > this._ioMaxUrl){
                    this.error(id, el.pack.s, 6, 'GET Data too Big');
                    return res;
                } 
            }
           
                      
            if(el.mode){
                _asc = true;
                if(el.to && el.to !== true){
                    fw.timer.start(el.hTO, el.to, ((el.mode == 2)? true : 1), 1);
                }
                
                el.hXML.onreadystatechange = function(){
                    var _this = fw.io._handlers[id];
                    var result = null, rst = null, st = null;
                    try{
                        if(_this.pack){
                            rst = _this.hXML.readyState;
                            if(rst == 4){
                                _this.hXML.onreadystatechange = fw.io._dummy;
                                st = _this.hXML.status;
                                result = _this.hXML.responseText;
                             	
                                rst = (!st || (st >= 200 && st < 300));
																fw.io._receiver(id, result, rst);
                                                               
                                                           }
                        }else _this.hXML.onreadystatechange = fw.io._dummy;
                        
                    }catch(e){ fw.io.error(id, _this.pack.s, 1, 'Bad Input Communication'); }
                }
            
                fw.mess.Msg(['IO','SEND', id, el.pack.s]);
            }
             try{
            		 
                if(el.grand){
                    try{ netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead'); }catch(e){}
                }
                el.ready = false;
                
                el.hXML.open(_mtd, _url, _asc);
                
                   
                
                //if(el.post) el.hXML.setRequestHeader('Content-Type', 'application/octet-stream');//; charset=UTF-8
                if(el.post) el.hXML.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
                
                el.hXML.send(_data);
                if(!el.mode){
                	
                	                		
                    if(!el.hXML.status || (el.hXML.status >= 200 && el.hXML.status < 300))
                    res = el.hXML.responseText;
                    //alert(res);
                    el.pack = null;
                }else res = true;
                //alert(res);
            }catch(e){ this.error(id, el.pack.s, 2, 'Bad Output Communication'); }
        }else this.error(id, null, 3, 'Wrong Send Cycle');
    }

    return res;
}

fw.io();