/*
	sky.ajax.js
	2007-04-16 ~ 2007-04-17

	Seo, Jaehan <daddyofsky@gmail.com>

    @dependence sky.base.js
*/

	var Ajax = Class({
		init : function(options) {
            Class.extend(this, {
				url : '',
				method : 'GET',  // GET, POST
				type : 'TEXT',   // TEXT, HTML, JSON, XML
                userid : null,
                password : null,
                header : {},
				param : {},
                callback : null,
                target : null,
                repeat : 1,
                delay : 5
			});
            this.http = null;
            this.postData = null;
            this.timer = null;
            this.count = 0;

            this.initHTTP();
            if (options) {
                this.request(options);
            }
		},
    	initHTTP : function() {
            if (!this.http) {
                if (window.XMLHttpRequest) {
                    this.http = new XMLHttpRequest();
                    this.httpType = 'XMLHttpRequest';
                } else if (window.ActiveXObject) {
                    var pid = ['MSXML2.XMLHTTP', 'Microsoft.XMLHTTP', 'MSXML.XMLHTTP', 'MSXML3.XMLHTTP'];
                    for (var i=0; i<pid.length; i++) {
                        try {
                            this.http = new ActiveXObject(pid[i]);
                            this.httpType = pid[i];
                            break;
                        } catch (e) {
                            // nothing
                        }
                    }
                }
            }
        },
        setUrl : function(url) {
            var pos = url.indexOf('?');
            if (pos != -1) {
                var query = url.substring(pos+1);
                var param = query.parseQuery(false);
                for (var key in param) {
                    this.param[key] = param[key];
                }
                url = url.substring(0, pos);
            }
            this.url = url;
        },
        setMethod : function(method) {
            this.method = (typeof method == 'string' && method.toUpperCase() == 'POST') ? 'POST' : 'GET';
        },
        setParam : function(param) {
            this.param = param;
        },
        addParam : function(key, value) {
            this.param[key] = value;
        },
        setHeader : function() {
            this.header = header;
        },
        addHeader : function(key, value) {
            this.header[key] = value;
        },
        setCallback : function(callback) {
            if (typeof callback == 'function') {
                this.callback = callback;
            }
        },
        applyParam : function() {
            var query = '';
            query = query.encodeQuery(this.param);
            this.requestUrl = this.url;
            this.postData = null;
            if (this.method == 'POST') {
                this.postData = query;
            } else {
                if (query) this.requestUrl += '?' + query;
            }
        },
        applyHeader : function() {
            if (this.method == 'POST') {
                this.header['Content-type'] = 'application/x-www-form-urlencoded';
            }
            // See Mozilla Bugzilla #246651.
            if (this.http.overrideMimeType) {
                this.header['Connection'] = 'close';
            }

            for (var key in this.header) {
                this.http.setRequestHeader(key, this.header[key]);
            }
        },
        request : function(options) {
            if (options) {
                Class.extend(this, options);
            }
            this.setMethod(this.method);
            this.setUrl(this.url);
            this.applyParam();

            this.http.open(this.method, this.requestUrl, true, this.userid, this.password);
            this.http.onreadystatechange = this.onComplete.bind(this);

            this.applyHeader();
            this.http.send(this.postData);
        },
        stop : function() {
            if (this.http) this.http.abort();
            if (this.timer) clearTimeout(this.timer);
        },
        onComplete : function() {
            if (this.http.readyState == 4) {
                // TODO : redirect

                this.count++;
                var response = new Ajax.Response(this);
                if (typeof this.callback == 'function') {
                    this.callback.call(this, response);
                } else if (this.target) {
                    $(this.target).innerHTML = response.getValue('HTML');
                }
                this.http.onreadystatechange = function(){};
                if (this.count < this.repeat) {
                    if (this.delay < 1) this.delay = 1;
                    this.addParam('ajax_count', this.count);
                    this.timer = setTimeout(this.request.bind(this), this.delay*1000);
                }
            }
        }
    });

    Ajax.Response = Class({
        init : function(ajax) {
            Class.extend(this, {
                http : ajax.http,
                type : ajax.type,
                status : ajax.http.status,
                header : ajax.http.getAllResponseHeaders(),
                body : ajax.http.responseText,
                xml : ajax.http.responseXML
            });
            this.value = this.getValue();
        },
        isSuccess : function() {
            return (this.status == 200 || this.status == 0) ? true : false;
        },
        getHeader : function(key) {
            if (key) {
                return this.http.getResponseHeader(key);
            } else {
                return this.header();
            }
        },
        getBody : function() {
            return this.body;
        },
        getValue : function(type) {
            if (!type) type = this.type;
            switch (type.toUpperCase()) {
                case 'XML' :
                    var value = this.xml || this.body;
                    break;
                case 'JSON' :
					var value = eval('('+this.body+')');
                    break;
                case 'HTML' :
                case 'TEXT' :
                default :
                    var value = this.body;
            }
            return value;
        }
    });