﻿// tested with jquery 1.4.2
(function ($) {

    var tao = window.$t = function () { }; // namespance

    var undefined;
    
    tao.fn = tao.prototype = {
        version: '1.0',
        session: undefined,
        webService: {
            version: '1_0',
            proxy: false,
            url: window.location.protocol + '//tao-ws.yr-gruppe.ch/',
            getUrl: function (method) {
                var date = new Date();
                if (this.proxy) {
                    return this.url + '?method=' + method + '&version=' + this.version + '&nocache=' + date.getTime();
                } else {
                    return this.url + this.version + '/Entry.asmx/' + method + '?nocache=' + date.getTime();
                }
            }
        },
        methods: {
            CreateSession: "CreateSession",
            SessionIsValid: "SessionIsValid",
            PushFormDataXml: "PushFormDataXml",
            PushFormDataJson: "PushFormDataJson",
            PushFormData: "PushFormData"
        },
        formats: {
            Xml: "Xml",
            Json: "Json"
        },
        log: function (msg) {
            if (typeof console != 'undefined') {
                console.log(msg);
            }
        }
    };

    tao.extend = function (obj, target) {
        if (!target)
            target = this.fn;
        return $.extend(target, obj);
    }

    tao.def = {
        baseTypes: {}
    };

    tao.extend({
        Collection: function () { this.init(); }
    }, tao.def.baseTypes);

    tao.extend({
        init: function () {
            this.items = new Array();
        },
        add: function (value) {
            this.items.push(value);
        },
        clear: function () {
            this.items = new Array();
        },
        contains: function (value) {
            return this.indexOf(value) != -1;
        },
        getItem: function (indx) {
            return this.items[indx];
        },
        getLength: function () {
            return this.items.length;
        },
        forEach: function (delegate) {
            jQuery.each(this.items, delegate);
        },
        indexOf: function (value) {
            return jQuery.inArray(value, this.items);
        },
        remove: function (value) {
            this.items = jQuery.grep(this.items, function (el, indx) {
                return el != value;
            });
        },
        removeAt: function (indx) {
            this.remove(this.getItem(indx));
        },
        toString: function () {
            return this.items.toString();
        }
    }, tao.def.baseTypes.Collection.prototype);

    // queue object
    tao.def.queue = {
        items: new tao.def.baseTypes.Collection(),
        inCall: false,
        _hasAssignedEvents: false,
        ajaxError: function (event, request, settings) {
            tao.fn.log("ajaxError: " + (typeof this.items) + " , " + settings.url);
        },
        ajaxComplete: function (event, request, settings) {
            tao.fn.log("ajaxComplete: " + (typeof this.items) + " , " + settings.url);
            if (this.items.getItem(0).url != settings.url) {
                alert("Queue out of order!"); // should never happen, but just in-case
                return;
            }
            this.items.removeAt(0);
            this.next();
        },
        ajaxSend: function (event, request, settings) {
            tao.fn.log("ajaxSend: " + (typeof this.items) + " , " + settings.url);
        },
        init: function () {
            this._hasAssignedEvents = true; // don't forget!
            jQuery(this).ajaxComplete(this.ajaxComplete);
            jQuery(this).ajaxError(this.ajaxError);
            jQuery(this).ajaxSend(this.ajaxSend);
        },
        add: function (item) {
            tao.fn.log("queue.add: " + item.url);
            this.items.add(item);
            if (!this.inCall) {
                this.next();
            }
        },
        next: function () {
            tao.fn.log("queue.next: " + this.items.getLength());
            if (this.items.getLength() > 0) {
                tao.fn.log("queue.inCall: true");
                this.inCall = true;
                if (!this._hasAssignedEvents) {
                    this.init();
                }
                var item = this.items.getItem(0);
                jQuery.post(item.url, item.args, item.callback, item.format);
            } else {
                tao.fn.log("queue.inCall: false");
                this.inCall = false;
            }
        }
    };


    // tao functions
    tao.extend({
        formToken: '',
        dataProxy: function (method, args, callback, format) {

            if (!format)
                format = 'xml';

            var url = this.webService.getUrl(method);
            tao.fn.log("dataProxy: " + url);
            tao.def.queue.add({
                'url': url,
                'args': args,
                'callback': callback,
                'format': format
            });
        },
        cookie: {
            // code based on: http://www.quirksmode.org/js/cookies.html
            get: function (name) {
                var nameEQ = name + "=";
                var ca = document.cookie.split(';');
                for (var i = 0; i < ca.length; i++) {
                    var c = ca[i];
                    while (c.charAt(0) == ' ') c = c.substring(1, c.length);
                    if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
                }
                return undefined;
            },
            set: function (name, value, date /* Date or days */) {
                var expires = '';
                if (date != undefined) {
                    if (typeof date == 'number') {
                        var dt = new Date();
                        dt.setTime(dt.getTime() + (date * 24 * 60 * 60 * 1000));
                        expires = "; expires=" + dt.toGMTString();
                    }
                    else
                        expires = "; expires=" + date.toGMTString();
                }
                document.cookie = name + "=" + value + expires + "; path=/";
            },
            del: function (name) {
                this.set(name, "", -1);
            }
        },
        // helper method
        getSession: function (e) {
            var c = this.cookie.get("_tao_s");
            if (c && e) {
                e.call(this, c);
            }
            if (!c && e) {
                tao.fn.createSession(e);
            }
            return c;
        },
        setSession: function (value) { // use this only if you know what you're doing!
            this.cookie.set("_tao_s", value); // available till end of browser session
        },
        getWsValue: function (response) {
            if (response.childNodes.length > 1) {
                return response.childNodes[1].text;
            } else {

                return response.firstChild.textContent;
            }
        },
        createSession: function (clbk) {
            var s;
            // check for existing cookie
            if (this.getSession()) {
                // check if session is valid
                this.dataProxy(this.methods.SessionIsValid, { session: this.getSession() }, function (response) {

                    if (tao.fn.getWsValue(response) == "false") {
                        tao.fn.cookie.del("_tao_s");
                        // create new session here
                        tao.fn.dataProxy(tao.fn.methods.CreateSession, { path: location.href }, function (response) {
                            s = tao.fn.getWsValue(response);
                            tao.fn.setSession(value);
                            tao.fn.session = value;
                            if (clbk)
                                clbk.call(this, value);
                        });
                    }
                });
            }
            else {
                this.dataProxy(this.methods.CreateSession, { path: location.href }, function (response) {
                    var value = tao.fn.getWsValue(response);
                    tao.fn.setSession(value);
                    tao.fn.session = value;
                    if (clbk)
                        clbk.call(this, value);
                });
            }
        },
        // expects a named value array: $("*").serializeArray();
        createXml: function (jArr) {
            var xml = '<?xml version="1.0" encoding="UTF-8" ?>';
            xml += '<entry>';
            $.each(jArr, function (indx, obj) {
                xml += '<' + obj.name + '><![CDATA[' + obj.value + ']]></' + obj.name + '>';
            });
            xml += '</entry>';
            return xml;
        },
        getInvalidElementsForTaoException: function (taoException, isDotNet) {
            var elements = new Array();

            var fields = taoException.Message.split(" : ")[1];
            if (!fields)
                return elements;

            jQuery.each(fields.split(','), function (indx, value) {

                if (value == '')
                    return;

                if (isDotNet)
                    value = value.replace('$', '_');

                elements.push(jQuery('#' + value));
            });
            return elements;
        },
        init: function (args) {
            var settings =
				jQuery.extend({
				    webService: {
				        proxy: false,
				        url: 'http://tao-ws.yr-gruppe.ch/'
				    }
				}, args);
            if (settings.webService.proxy) {
                this.webService.proxy = true;
                this.webService.url = settings.webService.url;
            }
        },
        track: function (formToken, proxy) { // should be called on page load
            this.formToken = formToken;
            this.createSession();
        },
        define: function (formStepToken, args) {
            var settings =
				jQuery.extend({
				    form: 'form:first',
				    ajax: {
				        click: function () { },
				        success: function () { },
				        fadeIn: false
				    },
				    error: {
				        container: '#error-message',
				        message: 'Please check your entry!',
				        handler: function () { return true; }
				    }
				}, args);

            tao.fn.log(args);
            tao.fn.log(settings);

            var form = jQuery(settings.form);

            form.submit(function () {

                jQuery(form).fadeTo('slow', 0.3, function () {
                    if (settings.ajax.click)
                        settings.ajax.click.call(form, settings);

                    var entryXml = tao.fn.createXml(form.serializeArray());
                    tao.fn.log(entryXml);

                    tao.fn.postData(formStepToken, entryXml, function (response) {

                        tao.fn.log(response);

                        var status = 'success';

                        // returned as string not as xml object!
                        var json = response.replace('</string>', '').replace('<?xml version="1.0" encoding="utf-8"?>', '').replace('<string xmlns="http://tao-ws.yr-gruppe.ch/">', '');

                        var msg = eval("(" + json + ")");

                        tao.fn.log(msg);

                        if ((msg.Message)) { // error
                            status = 'error';
                        }
                        tao.fn.log('status: ' + status);

                        if (status == 'success') {
                            var anonymSuccess = function () {
                                if (settings.ajax.success) {
                                    settings.ajax.success.call(form, msg);
                                }
                                form.css('filter', '');
                            };
                            if (settings.ajax.fadeIn) {
                                form.fadeTo('slow', 1.0, anonymSuccess);
                            } else {
                                anonymSuccess.call(form);
                            }
                        } else {
                            form.fadeTo('slow', 1.0, function () {
                                form.css('filter', '');
                                var showMsg = true;
                                if (settings.error.handler) {
                                    showMsg = settings.error.handler.call(form, msg);
                                }
                                if (showMsg) {
                                    jQuery(settings.error.container)
										.html(settings.error.message)
										.show();
                                }
                            });
                        }

                    }, tao.fn.formats.Xml);
                });

                return false; // never submit, as it is ajax 
            });
        },
        postData: function (formStep, xml, callback, preferedFormat) {
            if (!preferedFormat) { // set to xml if no preferedFormat is provided
                preferedFormat = tao.fn.formats.Xml;
            }
            // lets go!

            tao.fn.getSession(
				function (s) {
				    tao.fn.dataProxy(tao.fn.methods.PushFormDataJson, { sessionToken: s, formStepToken: formStep, 'xml': xml }, function (response) {
				        if (callback) {
				            callback.call(tao, response);
				        }
				    }, preferedFormat);
				}
			);
        }
    }, tao.fn);

})(jQuery);
