YAHOO.namespace('cs');
YAHOO.cs.AjaxWrapper = function (el, handlers) {
    var method, uri, event, form, self = {}, events = {}, validators = [], isFileUpload = false;
    
    var fire = function (evt, data, extra) {
        if (events.hasOwnProperty(evt)) {
            events[evt].fire(data, extra);
        }
    };

    var success = function (o) {
        var data;

        try {
            data = YAHOO.lang.JSON.parse(o.responseText);
        } catch(e) {
            data = o.responseText;
        }
        //alert('missed it');
        if (typeof data === 'object') {
            for (var evt in data) {
                if (data.hasOwnProperty(evt)) {
                    fire(evt, data[evt], data);
                }
            }
        }
        if (!data.success) {
            fire('success', data);
        }
        fire('done', data);
    };
  
  
	var uploadHandler = {
		upload: function (o) {
			var data;
			
			try {
	            data = YAHOO.lang.JSON.parse(o.responseText);
	        } catch(e) {
	            data = o.responseText;
	        }
			
			if (typeof data === 'object') {
	            for (var evt in data) {
	                if (data.hasOwnProperty(evt)) {
	                    fire(evt, data[evt], data);
	                }
	            }
	        }
	
	        if (!data.success) {
	            fire('success', data);
	        }
	        fire('done', data);
		}
		
	};
	
	
    var failure = function (o) {
        var data;
        try {
            data = YL.JSON.parse(o.responseText);
            //data = o.responseText.parseJSON();
        } catch(e) {
            data = o.responseText;
        }
        fire('failure', data);
        fire('done', data);
    };

    var validate = function () {
        var i, vl = validators.length;
        for (i = 0; i < vl; i += 1) {
            if (!validators[i].apply(self, [el])) {
                return false;
            }
        }
        return true;
    };
    
    var trigger = function (e) {
        if (e) {
            YAHOO.util.Event.preventDefault(e);
        }
        
        if (!validate()) {
            return;
        }
        /** do not trigger if there is no content to send **/
        if(handlers.checkData) {
          if(handlers.checkData.value.length < 1) {
            return false;
          }
        }


        var url = uri;

        if (form) {
			//handle file uploads
			if (form.enctype && form.enctype == 'multipart/form-data') {
				YAHOO.util.Connect.setForm(form,true);
				isFileUpload = true;
			} else {
				YAHOO.util.Connect.setForm(form);
			}
            
        } else {
            // this is a stupid hack because sometimes previous setForm() calls don`t get cleared, resulting in form data being passed when not desired
            YAHOO.util.Connect.resetFormState();
        }
		
		
		if (isFileUpload) {
			YAHOO.util.Connect.asyncRequest(method, url, uploadHandler);
		} else {
			YAHOO.util.Connect.asyncRequest(method, url, { success: success, failure: failure});
		}
        	
        fire('trigger', e);
    };
    
    var init = function () {
        var match, appAction;
        el = YAHOO.util.Dom.get(el);
        self.el = el;
        self.handlers = handlers;
       
        if (el.tagName.toLowerCase() === 'form') {
            method = el.method || 'GET';        
            form = el;
            event = 'submit';
            if (el.getAttribute('link')) {
                uri = el.getAttribute('link');
            } else {
                uri = el.getAttribute('action');
            }
            //set a ws flag in the form if available.    that way the component
            //on the other end can do things differently with the same action url
            if (form.ws) {
                form.ws.value = "1";
            }
        }
        if (el.tagName.toLowerCase() === 'a') {
            method = 'GET';
            match = el.href.match(/http:\/\/[^\/]+rd\.yahoo\.com\/.+http%3A\/\/(.*)/);
            if (!match) {
                uri = el.href;     
            } else {
                uri = 'http://' + decodeURIComponent(match[1]);
            }
            event = 'click';
            if (uri.indexOf('#') >= 0) {
                uri = uri.substr(0, uri.indexOf('#'));
            }
        }

        if (!handlers.error) {
            handlers.error = ['dialog', 'error'];
        }
        for (var evt in handlers) {
            if (handlers.hasOwnProperty(evt)) {
                self.subscribe(evt, handlers[evt]);         
            }
        }
        YAHOO.util.Event.on(el, event, trigger);
    };
    
    self.trigger = trigger;
    
    self.subscribe = function (evt, handler) {
        if (!events.hasOwnProperty(evt)) {
            events[evt] = new YAHOO.util.CustomEvent(evt, self);
        }
        if (typeof handler === 'object' && handler.length) {	
            handler = YAHOO.cs.AjaxWrapper.eventHandlers[handler[0]].apply(self, handler.slice(1));
        }
        if (typeof handler === 'function') {
            events[evt].subscribe(handler);
        } else {
            //console.log('Cannot attach event handler ', handler);
        }
    };


    self.addValidator = function (validator) {
        validators.push(validator);
    };
    if ((YAHOO.util.Dom.inDocument(el)) || (typeof el === 'object')) {
        init();
    } else {
        YAHOO.util.Event.onAvailable(el, init);
    }
    return self;
};

YAHOO.cs.AjaxWrapper.eventHandlers = {
    replace: function (el) {
        return function (evt, args) {
            YAHOO.util.Dom.get(el).innerHTML = args[0]; 
        };
    },
    append: function (el) {
        return function (evt, args) {
            YAHOO.util.Dom.get(el).innerHTML += args[0];
        };
    },
    destroyItem: function(destroyClass) {
        return function (evt, args) {
           myEl = YAHOO.util.Dom.get(this.handlers.originID);
           destroyEl = YAHOO.util.Dom.getAncestorByClassName(myEl, destroyClass);
           YAHOO.util.Dom.setStyle(destroyEl, 'display','none');
           destroyEl.parentNode.removeChild(destroyEl);
        };
    },
    /*should only be used when using the CSS from the YUI button and we know with 
      100% certainty we have <span class="yui-button"><span class="first-child"><button>
    */
    progressbuttonlabel: function (label, oButton) {
        return function (evt, args) {
            var oldLabel;
            oldLabel = oButton.innerHTML;
            oButton.innerHTML = label;
            oButton.disabled = true;
            /*force redraw for button - booo!*/
            var redraw = oButton.parentNode.parentNode;
            redraw.style.paddingRight='1px';
            this.subscribe('done', function () {
                oButton.innerHTML = oldLabel;
                oButton.disabled = false;
                redraw.style.paddingRight='0px';
            });
        };
    },
    progresslabel: function (label) {
        return function (evt, args) {
            var e = args[0];
            var el = YAHOO.util.Event.getTarget(e);
            if (el.tagName.toLowerCase() === 'form') {
                if (e.explicitOriginalTarget) {
                    el = e.explicitOriginalTarget;
                } else {
                    el = YAHOO.util.Dom.getElementsBy(function (el) {
                        return el.type === 'submit';
                    }, 'input', el)[0];
                }
            }
            var oldlabel;
            if (el.tagName.toLowerCase() === 'input') {
                oldlabel = el.value;
                el.value = label;
                el.setAttribute('disabled', 'disabled');
            } else {
                oldlabel = el.innerHTML;
                el.innerHTML = label;
            }
            this.subscribe('done', function () {
                if (el.tagName.toLowerCase() === 'input') {
                    el.removeAttribute('disabled');
                    el.value = oldlabel;
                } else {
                    el.innerHTML = oldlabel;
                }
            });
        };
    },
    style: function (style, value) {
        return function (evt, args) {
            YAHOO.util.Dom.setStyle(this.el, style, value);
        };
    },
    dialog: function (after, obj) {
        return function (evt, args) {
            var params = { fixedcenter: true };
            var div = document.createElement('div');
            div.innerHTML = args[0];
            document.body.appendChild(div);
            YAHOO.util.Dom.addClass(div.getElementsByTagName('div')[0], 'overlay');
            var overlay = new YAHOO.widget.Overlay(div.firstChild, params);
            overlay.cfg.setProperty("zIndex", 9); 
            overlay.render();
            overlay.show();
            if (after) {
                after.call(this, overlay, div, obj);
            }
        };
    }
};
