(function() {

var TRANSLATION_TYPE_OVERRIDE = "O";
var TRANSLATION_TYPE_EXCEPTION = "E";
var TRANSLATION_TYPE_GOOGLE = "G";
    
//fake replacement for firebug console
if (!("console" in window) || !("firebug" in console)) {
    var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
                 "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
    window.console = {};
    for (var i = 0; i < names.length; ++i)
        window.console[names[i]] = function() {};
};

//fix for unsupported Array.indexOf for IE
if(!Array.indexOf){
    Array.prototype.indexOf = function(obj){
        for(var i=0; i<this.length; i++){
            if(this[i]==obj){
                return i;
            }
        }
        return -1;
    };
}

function parseHashParams() {
	var params = {};
    var splited = document.location.hash.substring(1).split(",");
    for(var i = 0; i < splited.length; i++) {
		console.debug(splited[i]);
        var p = splited[i].split("=");
		//just incase there is more than one "=" in p
		params[p[0]] = p.length > 1 ? splited[i].substr(p[0].length + 1) : null ;
    }
	return params;
}

var hashParams = parseHashParams();

function detectServer() {
    var ctcServer = null;

    var html = document.getElementsByTagName("html").item(0);
    var head = html.getElementsByTagName("head").item(0);
    var body = html.getElementsByTagName("body").item(0);

    var scriptsList = [head.getElementsByTagName("script")];
    if(body) {
		scriptsList[scriptsList.length] = body.getElementsByTagName("script");
	}
    for(var j=0; j < scriptsList.length; j++ ) {
        var scripts = scriptsList[j];
        for(var i=0; scripts.item(i); i++) {
            var script = scripts.item(i);
            if(script.getAttribute("type") == "text/javascript" &&
               script.getAttribute("src") &&
               script.getAttribute("src").indexOf("wi.js") >= 0)
            {
                ctcServer = script.getAttribute("src");
                ctcServer = ctcServer.substring(0, ctcServer.indexOf("wi.js") - 1);
            }
        }
    }
    return ctcServer;
}

var ctcServer;

function changeServer() {
	if(hashParams["server"]) {
		var ctcServer = hashParams["server"];		
		if(ctcServer.indexOf("http") != 0) {
			ctcServer = "http://" + ctcServer;
		}
		if(ctcServer != detectServer()) {	
			console.info("changing server to:" + ctcServer);
			document.write(unescape("%3Cscript src='" + ctcServer + "/wi.js' type='text/javascript'%3E%3C/script%3E"));
			return true;
		}
	}
	return false;
}

if(changeServer()) {
	return;
}

window.gifurl = function(options) {
    options = jQuery.extend({
        bg_color: "#FFFFFF",
        h: 25,
        w: 150,
        label: "OK",
        text_align: "center",
        text_valign: "middle",
        font_bold: 0,
        font_italic: 0,
        font_color: "#222222",
        font_size: 14,
        border_size: 0,
        border_color: "#000000",
        margin_left: 0,
        margin_right: 0,
        no_wrap: 0
    }, options);
    var args = "";
    jQuery.each(options, function(key, value){
        if (key == "label" || key == "bg_color" || 
			key == "font_color" || key == "border_color") 
		{
            value = encodeURIComponent(value);
        }
        args += "&" + key + "=" + value;
    });
    return ctcServer + "/picture/gif_no_cache?" + args.substring(1);
};

function getUniqueId() {
    return (new Date()).getTime();
}

function loadJS(url, addScriptId) {
    // TO AVOID DOUBLE REQUESTS AT IE
    var id = "script" + getUniqueId();
    if(addScriptId) {
        url += "&scriptId=" + id;
    }

    var script = document.createElement('script');
    script.setAttribute("type", "text/javascript");
    script.setAttribute("src", url);
    script.setAttribute("id", id);
    if (typeof script != "undefined")
        document.getElementsByTagName("head")[0].appendChild(script);
}

function loadCSS(url) {
    var style = document.createElement('link');
    style.setAttribute("type", "text/css");
    style.setAttribute("rel", "stylesheet");
    style.setAttribute("href", url);
    if (typeof style != "undefined")
        document.getElementsByTagName("head")[0].appendChild(style);
}

function setCookie(name, value, expires) {
    document.cookie = name + "=" + escape(value) + "; path=/" + 
		((expires == null) ? "" : "; expires=" + expires.toGMTString());
}

function getCookie(name) {
    var dc = document.cookie;
    var cname = name + "=";

    if (dc.length > 0) {
		begin = dc.indexOf(cname);
		if (begin != -1) {
			begin += cname.length;
			end = dc.indexOf(";", begin);
			if (end == -1) {
				end = dc.length;
			}
			return unescape(dc.substring(begin, end));
		}
    }
    return null;
}

function convertEntities(text) {
    function convertEntity(ent) {
        var num = parseInt(ent.replace(/\D/g, ''), 16);
        var esc = ((num < 16) ? '0' : '') + num.toString(16);
        return String.fromCharCode( esc );
    }

    var matches = text.match( /\&\#(\d+);/g );

    if (!matches) {
        console.warn("No match"+text);
        return null;
    } else {
        console.warn("No match! "+text);
    }

    for ( var i = 0; i < matches.length; i++ ) {
        text = text.replace( matches[i], convertEntity( matches[i] ) );
    };
    return text;
}


function hour2float(hour) {
    var splt = hour.split(":");
    hour = parseFloat(splt[0]);
    var minute = parseFloat(splt[1]);
    return (hour + (minute/60.0));
}

function extract_end_hour(daterange) {
    var endDate = jQuery.trim(daterange.split("to")[1]);
    return jQuery.trim(endDate.split(" ")[1]);
}

function extract_day(daterange) {
    var endDate = jQuery.trim(daterange.split("to")[1]);
    return jQuery.trim(endDate.split(" ")[0]);
}

var ecommerceTracker = function() {
var tracker = null;
var campaignId = null;
var transactions = [];

function track(t) {
    console.debug("transactions tracked", t);
    tracker._addTrans(t.orderID, campaignId, t.total, 
                      "0", "0", "Fake City", "Fake State", "France");
    tracker._addItem(t.orderID, "SKU", "fakeProduct", "Fake category", t.total, "1");
}

return {
    "setTracker": function(tr, cpgId) {
        console.debug("ecommerceTracker set");
        tracker = tr;
        campaignId = cpgId;
        if(transactions) {
            for(var j = 0; j < transactions.length; j++ ) {
                var t = transactions[j];
                track(t);
            }
            tracker._trackTrans();
            transactions = [];
        }
    },
    "trackTrans": function(orderID, total) {
        var t = {"orderID": orderID, "total": total};
        if(tracker) {
            track(t);
            tracker._trackTrans();

        } else {
            transactions.push(t);
        }
    }
};    
}();

function trackCampaign(trackerId, campaignId, lang) {
    var tracker = null;
    if(window._gat == null) {
        console.warn("still no ga, no ga tracking!");
    } else {
        tracker = _gat._getTracker(trackerId);
        tracker._setCustomVar(1, "CampaignId", campaignId, 3); 
        lang = lang ? lang : "original";
        tracker._setCustomVar(2, "Language", lang, 3);
        tracker._trackPageview();
        console.debug("page tracked, tracker:", trackerId, ", campaign:", campaignId, ", language:",  lang);
        ecommerceTracker.setTracker(tracker, campaignId);
    }
};


function loadDeps(loadTranslationApi, loadJQuery, loadIFC, loaded) {
    var ourjQuery = false;
    var ourGA = false;
    
    if(window.jQuery == null) {
        console.debug("no jquery, importing!");
        var jQueryUrl = "http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js";
        document.write(unescape("%3Cscript src='" + jQueryUrl + "' type='text/javascript'%3E%3C/script%3E"));
        ourjQuery = true;
    }

    if(loadTranslationApi && (window.google == null || window.google.load == null)) {
        document.write(unescape("%3Cscript src='http://www.google.com/jsapi' type='text/javascript'%3E%3C/script%3E"));
    }

    if(window._gat == null) {
        console.debug("no ga, importing!");
        var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
        document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
        ourGA = true;
    }
    
    // load alien CSS
    loadCSS(ctcServer + "/mltb/toolbar_style.css");

    var jQueryReady = false;
    var GAReady = false;
    var ifcReady = false;
    var ifcLoading = false;
    var googleTranslationApiReady = false;
    var googleJSApiReady = false;
    var period = 100;
    var iterations = 0;
    
    window._CTCheckScripts = function() {
        if(loadJQuery && window.jQuery != null && !jQueryReady) {
            console.debug("jQuery ready");
            jQueryReady = true;
            if(ourjQuery) {
                jQuery.noConflict();                
            }
        }

        if(window.jQuery != null && loadIFC && !ifcLoading) {
            console.debug("loading ifc");
            loadJS(ctcServer + "/ifc.js");
            ifcLoading = true;
        }
        
        if(window.jQuery && window.jQuery.ifcListener && !ifcReady) {
            console.debug("Ifc ready");
            ifcReady = true;                        
        }

        if(window._gat != null && !GAReady) {
            console.debug("GA ready");
            GAReady = true;
        }

        if(loadTranslationApi && 
           window.google != null && 
           window.google.load != null &&
           (!googleJSApiReady || !googleTranslationApiReady)) //temp solution for ie
        {
            googleJSApiReady = true; 
            google.load("language", "1", {"callback": function() {
                console.debug("TranslationApi ready");
                googleTranslationApiReady = true;
            }});
        }

        if((jQueryReady || !loadJQuery) && 
           (googleTranslationApiReady || !loadTranslationApi) &&
           (ifcReady || !loadIFC))
        {
            if(GAReady || iterations*period > 2000) {
                if(!GAReady) {
                    console.debug("Can't fetch ga. Proceeding without it.");
                }
                console.debug("All Deps ready");
                loaded();                 
                return;
            }
        }
        iterations++;
        window.setTimeout('_CTCheckScripts()', period);
    };
    _CTCheckScripts();
};


window._initCTC = function(params) {

    var emailReg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
    var phoneReg = /^[+0-9 ]{1,20}$/;

    var campaignId = params.campaign;
    var formLang = params.formLang ? params.formLang : null;
    var pageLang = params.pageLang;
    var logo = params.logo ? params.logo : null;
    var ask4ClientLang = params.ask4ClientLang ? params.ask4ClientLang : false;

    var offererLang = params.offererLang ? params.offererLang : null;
    var offererEmail = params.offererEmail ? params.offererEmail : null;
    var offererTimezone = params.offererTimezone ? params.offererTimezone : "";
    var offererServiceName = params.offererServiceName ? params.offererServiceName : null;
    
    var clientTimezone = params.clientTimezone ? params.clientTimezone : "";
    var clientServiceName = params.clientServiceName ? params.clientServiceName : null;

	ctcServer = detectServer();

    if(ctcServer == null) {
        console.warn("No ctcServer defined.");
        return;        
    } else if(ctcServer == "") {
        console.debug("Relative ctcServer location found.");        
    } else {
        console.debug("ctcServer: ", ctcServer);
    }

    var editorUrl = null;
    var dontTranslate = false;

	editorUrl = hashParams["editor_url"];

//	alert("editorUrl: " + editorUrl);
//	console.debug(document.location.href);

	if(editorUrl) {
		console.debug("editorUrl", editorUrl);
	}

	//return;

	if(hashParams["no_translation"] === null) {
		setCookie('translate_to', '');
		console.debug("translation disabled");
        dontTranslate = true;
	}

	formLang = hashParams["translate_to"] || hashParams["lang"];
    if(formLang) {
        if(!pageLang) {
            console.error("page language not set!");
            return;
        }
        setCookie('translate_to', formLang);
    } else {
        formLang = getCookie('translate_to');
        if(!formLang) {
            if (pageLang) {
                formLang = pageLang;
                console.warn("form language not set!");            
                dontTranslate = true;
            }
        }
    }
  
    var invalidStyle = {'background-color' : '#FFAFAF'};
    var validStyle = {'background-color' : '#FFF'};

    function addFormHandlers(elems, template) {
        var currentDay = template.find("input[name='currentDay']").val();
        var currentHour = parseInt(template.find("input[name='currentHour']").val());
        var officeHourStart = template.find("input[name='officeHourStart']").val();
        var officeHourEnd = template.find("input[name='officeHourEnd']").val();

        window._formSubmitted = function (formId, scriptId, result, reqId) {
            console.debug('Data sent and answer:', result, 'received for form: ', 
                          formId, ' via script:', scriptId);

            if(scriptId) {
                jQuery("#" + scriptId).remove();
            }            
            //jQuery(".ctcWidget").hide();
            // show information about sending status
            
            var widget = jQuery("#" + formId);
            if(result == 'payment_summary') {
                jQuery("#_ctcFakeForm")
                .attr("action", ctcServer + "/ctc/summary")
                .empty()
                .append("<input name='id' value='" + reqId + "'>")
                .submit();
            } else {
                widget.find(".ctcLoading").hide();
                widget.removeAttr("id");
                if(result == 'saved') {
                    widget.find(".ctcOK").show();
                    widget.find("#submit-result-for-selenium").val('1');
                } else if(result == 'etr_saved') {
                    widget.find(".etrOK").show();
                    widget.find("#submit-result-for-selenium").val('1');
                } else if(result == 'not_found') {
                    widget.find(".ctcErrorNotFound").show();
                } else if(result == 'not_enabled') {
                    widget.find(".ctcErrorNotEnabled").show();
                } else if(result == 'exception') {
                    widget.find(".ctcErrorException").show();
                } else {
                    widget.find(".ctcErrorException").show();
                }
            }
        };

        elems.each(function(e) {
            var widget = template.clone(true);

            jQuery(this).append(widget);

            var day = widget.find("select[name='day']");

            var email = widget.find("input[name='email']");
            var email2 = widget.find("input[name='emailEmail']");
            var phone = widget.find("input[name='phone']");

            day.change();

            widget.show();

            function showCtcCallTab() {
                widget.find("#ctcEmailForm").hide();
                widget.find("#ctcCallForm").show();
                widget.find("#ctcCall").css({"background-color":"#ddd","font-weight":"bold"});
                widget.find("#ctcEmail").css({"background-color":"#fff","font-weight":"normal"});
            };
            
            function showEtrTab() {
                widget.find("#ctcCallForm").hide();
                widget.find("#ctcEmailForm").show();
                widget.find("#ctcEmail").css({"background-color":"#ddd","font-weight":"bold"});
                widget.find("#ctcCall").css({"background-color":"#fff","font-weight":"normal"});
            };

            widget.find("#ctcCall").click(showCtcCallTab);
            widget.find("#ctcEmail").click(showEtrTab);

            widget.find(".ctcReset").click(function() {
                // RESETING VARS
                widget.find(".ctcField:not(.ctcDontReset)").each(function() {
                    jQuery(this).val('');
                });
                widget.find(".ctcFieldEmail:not(.ctcDontReset)").each(function() {
                    jQuery(this).val('');
                });

                showCtcCallTab();

                day.change();

                widget.find(".ctcMessage").hide();
                widget.find("#submit-result-for-selenium").val('0');
                widget.find(".ctcBody").show();

                if(widget.find(".ctcClose").html() != null){
                    widget.find(".ctcClose").show();
                    jQuery("#wiCtc", document).hide('slow');
                }
                
                if(widget.find(".ctcCloseFloatingBar").html() != null) {
                    widget.find(".ctcMessage").hide();
                    jQuery(".ctc-form-floatingbar").hide();
                }
            });
            
            widget.find(".ctcSubmitEmail").click(function() {
                var formValid = true;
                
                var widgetHeight = widget.find(".ctcBody").height();
                widget.find(".ctcMessage").css('height', widgetHeight);

                widget.find(".ctcFieldEmail").css(validStyle);
                
                widget.find(".ctcFieldEmail").each(function() {
                    var field = jQuery(this);
                    if(jQuery.trim(field.val()) == '' && field.attr('optional') == undefined)    
                    {
                        console.debug("invalid:", field.attr("name"), "=", field.val());
                        field.css(invalidStyle);
                        formValid = false; 
                    }
                });
                
                if(email2.size() && !emailReg.test(email2.val())) {
                    console.debug("invalid: email");
                    email2.css(invalidStyle);
                    formValid = false;
                }
                
                if(formValid) {
                    widget.find(".ctcLoading").show();
                    widget.find(".ctcBody").hide();
                    widget.find(".ctcClose").hide();
                
                    formId = "submitted" + getUniqueId();
                    widget.attr("id", formId);
                    submitUrl = "";

                    widget.find(".ctcFieldEmail").each(function() {
                        var field = jQuery(this);
                        if(field.val() != '') {
                            submitUrl += "&" + field.attr("name") + "=" + field.val();
                        }
                    });

                    submitUrl += "&formId=" + formId;
                    submitUrl = ctcServer + "/ctc/submit_etr?" + submitUrl.substring(1);

                    console.debug('Sending from e-mail form: ' + submitUrl);
                    loadJS(submitUrl);
                }
            });
            
            widget.find(".ctcSubmit").click(function() {
                // CALL ME FORM VALIDATION
                var formValid = true;
                
                var widgetHeight = widget.find(".ctcBody").height();
                widget.find(".ctcMessage").css('height', widgetHeight);

                widget.find(".ctcField").css(validStyle);

                widget.find(".ctcField").each(function() {
                    var field = jQuery(this);
                    //console.debug(field.attr("name"), field.val(), field.val() == '', !field.attr('mandatory') == 'false');
                    if(field.val() == '' && field.attr('optional') == undefined)                         
                    {
                        console.debug("invalid:", field.attr("name"), "=", field.val());
                        field.css(invalidStyle);
                        formValid = false; 
                    }
                });

                if(!phoneReg.test(phone.val())) {
                    console.debug("invalid: phone number: " + phone.val());
                    phone.css(invalidStyle);
                    formValid = false;
                }

                if(email.size() && !emailReg.test(email.val())) {
                    console.debug("invalid: email");
                    email.css(invalidStyle);
                    formValid = false;
                }

                if(formValid) {
                    widget.find(".ctcLoading").show();
                    widget.find(".ctcBody").hide();
                    widget.find(".ctcClose").hide();

                    formId = "submitted" + getUniqueId();

                    widget.attr("id", formId);

                    submitUrl = "";

                    widget.find(".ctcField").each(function() {
                        var field = jQuery(this);
                        if(field.val() != '') {
                            submitUrl += "&" + field.attr("name") + "=" + field.val();
                        }
                    });

                    submitUrl += "&formId=" + formId;

                    submitUrl = ctcServer + "/ctc/submit?" + submitUrl.substring(1);

                    console.debug('Sending: ' + submitUrl);

                    loadJS(submitUrl);
                } else {
                    console.debug(widget);
                }
            });//widget.find(".ctcSubmit")
        }); //elems.each(
    } //addFormHandlers

    function initCTCForm(found, enabled,  
                         formHtml, formStyle, formStyleGlobal,
                         glossary, fix) 
    {
        
        function initForm(template) {
            console.debug("init form called:", campaignId);

            var formEventSent = false;

            var are_styles = jQuery('.ctcWidget').css('backgroundColor');
            if(are_styles == 'transparent' || are_styles == 'rgba(0, 0, 0, 0)'){
                jQuery("head").append('<style type="text/css">' + formStyle + '</style>');
            }
            jQuery("head").append('<style type="text/css">' + formStyleGlobal + '</style>');

            // FORMS OPENED BY CTC BUTTONS    
            jQuery("body").append('<div id="wiCtc" style="display: none; position: absolute;"></div>');
            addFormHandlers(jQuery("#wiCtc"), template);

            jQuery(".ctc", document).each(function() {
                jQuery(this).click(function() {
                    // POSITION OF FLOATING WIDGET
                    var scrollTop;
                    if(self.pageYOffset){
                        scrollTop = self.pageYOffset;
                    } else if(document.documentElement && document.documentElement.scrollTop){ // Explorer 6 Strict
                        scrollTop = document.documentElement.scrollTop;
                    } else if(document.body){ // all other Explorers
                        scrollTop = document.body.scrollTop;
                    }
                    var elementPosition = jQuery(this).offset();
                    var widgetHeight = jQuery("#wiCtc").height();
                    var elementHeight = jQuery(this).height();
                    var windowHeight = jQuery(window).height();
                    var spaceAbove = elementPosition.top - scrollTop;
                    var spaceBelow = windowHeight - spaceAbove - elementHeight;

                    if(spaceBelow >= widgetHeight){
                        widgetY = elementPosition.top + elementHeight;
                    } else if(spaceAbove >= widgetHeight){
                        widgetY = elementPosition.top - widgetHeight;
                    } else {
                        if(widgetHeight <= windowHeight) {
                            widgetY = scrollTop + (windowHeight - widgetHeight) / 2;
                        } else {
                            widgetY = scrollTop;
                        }
                    }

                    // SHOWING WIDGET
                    jQuery("#wiCtc").show();
                    jQuery("#wiCtc").css('top', widgetY + 'px'); 
                    jQuery("#wiCtc").css('left', elementPosition.left + 'px');

                    var close = jQuery("#wiCtc").find(".ctcClose");

                    jQuery(close).click(function() {
                        jQuery("#wiCtc").hide();
                    });
                });
            });
            
            //Let's remove close button from template, 
            //from now it is going to be used just for inline forms
            jQuery(".ctcClose", template).remove();
            addFormHandlers(jQuery(".ctc-form"), template);
            
            //Floating Bar Form
            jQuery(".ctc-form-floatingbar .ctcBody")
                .prepend("<div class='ctcCloseFloatingBar' style='right:0px;'>x</div>");
            jQuery(".ctcFloatingBarButton").click(function() {
                jQuery(".ctc-form-floatingbar").show();
            });
            jQuery(".ctcCloseFloatingBar").click(function() {
                jQuery(".ctc-form-floatingbar").hide();
            });
        } //initForm;

        console.debug("_initCTCForm called: ", campaignId, found, enabled);
        var formTemplate = document.createElement("div");
        formTemplate.style.display = "none";
        document.body.appendChild(formTemplate);
        jQuery(formTemplate).html(formHtml);

        initForm(jQuery(formTemplate));
        jQuery("body").append("<form id='_ctcFakeForm' method='get' style='display: none'> </form>");        
    }; //initCTCForm

    var formUrl = ctcServer +
              "/ctc/form?campaign=" + campaignId + 
              "&ask4ClientLang=" + ask4ClientLang + 
              "&formLang=" + formLang +
              "&clientTimezone=" + clientTimezone +
              "&offererTimezone=" + offererTimezone +
              "&offererLang=" + offererLang + 
              "&offererEmail=" + encodeURIComponent(offererEmail);

    if(clientServiceName) {
        formUrl += "&clientServiceName=" + clientServiceName;
    }

    if(offererServiceName) {
        formUrl += "&offererServiceName=" + offererServiceName;
    }        

    if(logo) {
        formUrl += "&logo=" + logo;
    }        

    formUrl += "&mltb=" + pageLang + "," + formLang;

    console.debug("including form: " + formUrl);

    var continuation = false;
    window._initCTCForm = function (found, enabled, gaTrackerId, 
                                    formHtml, formStyle, formStyleGlobal,
                                    exceptions, overrides, fix) 
    {
        function cont() {                       
            if (formLang && !editorUrl && !dontTranslate) {                
                jQuery(document.body).prepend(
                    "<div class='ctcFloatingBar'>" +
                        "<!--<div id='ctc_message'></div>-->" +
                        "<div id='ctc_show_original'></div>" +
                        "<div class='ctcButtonSpace'>" +
                        "<button class='ctcFloatingBarButton'>Any questions ?</button></div>" +
                    "</div>"+
                    "<div class='ctc-form-floatingbar' style='display:none;'><div class='ctc-form'></div></div>"
                    );
                jQuery(document.body).append("<div class='filler'></div>");
            }

            if(pageLang && !dontTranslate) {
                trackCampaign(gaTrackerId, campaignId, formLang);
                translate(window.document, pageLang, formLang, exceptions, overrides, fix, campaignId, editorUrl,
                    function(all, translated) { 
                        if(all == translated) {
                            initCTCForm(found, enabled, 
                                        formHtml, formStyle, formStyleGlobal,
                                        overrides, fix);
                        }
                    });
            } else {
                trackCampaign(gaTrackerId, campaignId);
                initCTCForm(found, enabled,  
                            formHtml, formStyle, formStyleGlobal,
                            overrides, fix);
            }
        } //cont;

        if(continuation) {
            cont();
        } else {
            continuation = cont;
        };
    };


    loadDeps(true, true, editorUrl, function() {
        if(continuation) {
            continuation();
        } else {    
            continuation = true;
        }
    });

    loadJS(formUrl, false);

    return ecommerceTracker;
}; //window._initCTC


//TODO: fix that
window._initCTCRequest = function(params) {

    var campaignId = params.campaign;

    window._sendCTCRequest = function(params) {
        var ctcString = ctcServer + '/ctc/submit';
        ctcString += '?countryCodeSelector=';
        ctcString += '&countryCode=';
        ctcString += '&phone=' + params.phone;
        ctcString += '&campaign=' + campaignId;
        ctcString += '&clientLang=' + params.language;
        ctcString += '&day=' + params.date;
        ctcString += '&hour=' + params.hour;
        ctcString += '&clientTimezone=Europe/Paris'; // GET

        if(params.callback) {
            window._formSubmitted = function (formId, scriptId, result) {
                console.debug('Data sent and answer:', result, 'received via script:', scriptId);
                params.callback();
            };
        } else {
            window._formSubmitted = function (formId, scriptId, result) {};
        }
        loadJS(ctcString);
        return true;
    };

    window._initCTCTracker = function(found, enabled, gaTrackerId) {
        console.debug("tracker received: " + gaTrackerId);
        loadDeps(false, false, false, function() {
            trackCampaign(gaTrackerId, campaignId);
        });
    };

    trackerUrl = ctcServer + "/ctc/tracker?campaign=" + campaignId;

    console.debug("asking for tracker: " + trackerUrl);
    document.write(unescape("%3Cscript defer src='" + trackerUrl + "' type='text/javascript'%3E%3C/script%3E"));
}; //window._initCTCRequest

function translate(doc, srcLang, dstLang, exceptions, overrides, fix, 
                   campaignId, editorUrl, callback) {

    var regexNBSP = new RegExp(String.fromCharCode(160), "g");
    var regexSP = new RegExp(String.fromCharCode(32), "g");

    function fixWhiteSpaces(orig, translated) {
        // add &nbsp; if needed to keep right design of pages
        var testText = jQuery.trim(orig);
        if(regexNBSP.test(testText) && !regexSP.test(testText)) {
            translated = translated.replace(/ /g, '\u00A0');
        }
        // add empty space to as first or last character to keep text nodes look right
        if(jQuery.browser.msie && jQuery.browser.version.substr(0,1) < 8) {
            translated = " " + translated + " ";
        } else {
            if(orig[0] == " " || orig[0] == "\n")
                translated = " " + translated;
            if(orig[orig.length - 1] == " " || orig[orig.length - 1] == "\n")
                translated += " ";
        }
        //console.warn(orig, "===>", translated);
        return translated;
    }

    function groupTexts(elem, overrides, accumulate, maxGroupLength, f) {
        /* group elements into groups no longer that maxGroupLength long,
         * if element is longer break it into pieces. 
         */

        var texts = [];
        var totalLength = 0;
        var acc = "";

        function pushText(text, setter) {
            var newAcc = accumulate(acc, text);
            if(newAcc.length > maxGroupLength) {
                f(acc, texts);
                acc = accumulate("", text);
                texts = [];
            } else {
                acc = newAcc;                
            }
            texts.push({"text": text, "set": setter});                                   
        }

        function flushTexts() {
            if(texts) {
                f(acc, texts);
            }
        }

        function breakAndPush(text, setter) {
            if(text.replace(/[ \n\r\t]/g, "")) { //not empty
                if(accumulate("", text).length < maxGroupLength) { //not too long
                    pushText(text, function(translation) {
                        setter(fixWhiteSpaces(text, translation));
                    });
                } else { //text too long, lets split it
                    var acc = ""; //accumulator for translated fragments
                    var tail = text;
                    while(true) {
                        var fragment = tail.substr(0, maxGroupLength);
                        var u = 0;
                        while(accumulate("", fragment).length > maxGroupLength) {
                            for(var splitChar in {". ": 1, ", ": 1, "\n": 1, " ": 1, "cutone": 1}) {
                                if(splitChar == "cutone") {
                                    //console.debug("no split char found, cutting one char", fragment);
                                    fragment = fragment.substr(0, fragment.length - 1);
                                } else {
                                    var splitIndex = fragment.lastIndexOf(splitChar, -1); 
                                    if(splitIndex > 0 && (splitIndex + splitChar.length) < fragment.length) {
                                        fragment = fragment.substr(0, splitIndex + splitChar.length);
                                        //console.debug("long text broken at: '", splitChar, "'", fragment.length, splitIndex);
                                        break;
                                    }
                                }
                            }
                        }
                        tail = tail.substr(fragment.length);
                        if(tail) {
                            //console.debug("pushing text fragment:", fragment.length, "tail: ", tail.length);
                            pushText(fragment, function(translation) {
                                acc += fixWhiteSpaces(fragment, translation);
                            });
                        } else {
                            //console.debug("pushing last text fragment:", fragment.length);
                            pushText(fragment, function(translation) {
                                setter(acc + fixWhiteSpaces(fragment, translation));
                                acc = null; //not sure if necessary
                            });                                
                            break;
                        }
                    }
                }
            }
        }

        function useGlossaryOrPush(text, push, setter) {
            //we need to remove \n, cause override from DB into JS {} object can't have \n inside object's attr name
            //@see form.mako
            var trimmed = jQuery.trim(text).replace(/\n/g, '');
            
            var override = overrides[trimmed];
            if(override) {
                setter(fixWhiteSpaces(text, override), TRANSLATION_TYPE_OVERRIDE);
            } else {
                override = exceptions[trimmed];
                if(override) {
                    setter(override, TRANSLATION_TYPE_EXCEPTION);                    
                } else {
                    var orig = text;
                    jQuery.each(exceptions, function(term, override) {
                        //TODO: optimization oportunity here
                        override = ["<span class='notranslate'>", 
                                    override === undefined ? term : override, 
                                    "</span>"].join("");
                        text = text.replace(new RegExp(term, "g"), override);
                    });
                    if(orig != text) {
                        //console.debug("exception applied:", orig, "->", text);
                        push(text, function(text) {
                            setter(text.replace(RegExp("<span class='notranslate'>","g"), "")
                                   .replace(RegExp("</span>","g"), ""),
                                   TRANSLATION_TYPE_GOOGLE);
                        });
                    } else {
                        push(text, function (text) {
                            setter(text, TRANSLATION_TYPE_GOOGLE);
                        });
                    }
                }        
            }
        };

        function markAsEditable(node, text, push, setter){
            if((top.partnerWindow || editorUrl) && jQuery.trim(text)) {				
				if(node.get(0).nodeType === 3) { //i.e. textNode
					var parentNodeName = node.parent().get(0).nodeName.toLowerCase();
                    if(['p', 'div', 'li', 'span', 'b'].indexOf(parentNodeName) >= 0) {
                        //let's allow to edit node separately
                        node = node.wrap("<span></span>").parent();
                    } else {
                        node = node.parent();
                    }
				}
                var texts = node.data('texts');
                if(!texts) {
                    texts = new Array();
                }
                var placeholder = [jQuery.trim(text), undefined, undefined];
                texts.push(placeholder);
                node.data('texts', texts);
                node.addClass('editModeElement');                
                useGlossaryOrPush(text, push, function(translation, translationType) {                    
                    placeholder[1] = jQuery.trim(translation);            
                    placeholder[2] = translationType;
                    setter(translation);
                });
            } else {
                useGlossaryOrPush(text, push, setter);
            }
        };

        function handleElement(key, domNode) {
            if(domNode.nodeType === 3) { //i.e. textNode
				var node = jQuery(domNode);
                var parentNodeName = 
                    node.parent().get(0).nodeName.toLowerCase();
                if (parentNodeName != 'textarea') {                    
                    markAsEditable(node, 
                                   domNode.nodeValue, 
                                   breakAndPush, 
                                   function(translation) {
                                       domNode.data = translation;
                                   });
                }
            } else if(domNode.nodeType === 1) {
                var nodeName = domNode.nodeName.toLowerCase();
                var node = jQuery(node);
                if(nodeName == "input" &&
                   node.attr("type") && (node.attr("type") == 'submit' ||
                                          node.attr("type") == 'button' ||
                                          node.attr("type") == 'reset')) 
                {
                    markAsEditable(node, 
                                   node.attr("value"), pushText, 
                                   function(translation) {
                                       node.attr("value", translation);
                                   });
                } else if(nodeName != "form" && node.attr("title")) {
                    markAsEditable(node,
                                   node.attr("title"), breakAndPush, 
                                   function(translation) {
                                       node.attr("title", translation);
                                   });
                } else if(nodeName != "form" && node.attr("alt")) {
                    markAsEditable(node,
                                   node.attr("alt"), pushText, 
                                   function(translation) {
                                       node.attr("alt", translation);
                                   });
                }
            }
        }
        elem.each(function(key, domNode) {
			try {
				handleElement(key, domNode);
			} catch (x) {
				console.error(x);
			}
		});
        flushTexts();
    }; //groupTexts

    function disableLink(e) {
        e.preventDefault();
        e.stopPropagation();
        return false;
    }
      
    function editOverridesViaNewPortalEditor() {
        
        var editorWindow;
        window.focus();
    
        jQuery(document).find('a').each(function() {
            var baseHref = jQuery(this).attr('href');
            baseHref += "#translate_to=" + dstLang + ",editor_url=" + encodeURIComponent(editorUrl);
            jQuery(this).attr('href', baseHref);
        });
      
        var ifcListener = jQuery.ifcListener(window);
        ifcListener.start();
        
        var isHighlighted = false;
        var goThroughLink = false;
        //.addClass('editModeElementHighlighted')
        jQuery(document).find('.editModeElement').bind('click', disableLink);
        
        jQuery(document).keyup(function(e) {
            //console.debug(e.which);
            if (e.which == 113 && !isHighlighted) { //.addClass('editModeElementHighlighted')
                jQuery(document).find('.editModeElement')
                    .bind('click', disableLink);
                isHighlighted = true;
                goThroughLink = false;
            }
        });
        
        jQuery(document).keydown(function(e) {
            if (e.which == 113) {
                console.debug("down");
                jQuery(document).find('.editModeElement')
                                .unbind('click', disableLink);
                goThroughLink = true;
            }
        });

        jQuery(doc).find('form').attr('action', '#');
        jQuery(doc).find('*').attr('onclick', '');

        jQuery(doc).find('.editModeElement').click(function(event) {
            
            if (goThroughLink) {
                return;
            }
            event.stopPropagation();
            
            jQuery(doc).find('.editModeElementHighlighted').removeClass('editModeElementHighlighted');
            
            var clicked = jQuery(this);
            
            clicked.addClass('editModeElementHighlighted');
            isHighlighted = true;

            ifcListener.one("removeHighlight", function() {
                isHighlighted = false;
                clicked.removeClass('editModeElementHighlighted');
            });

            jQuery.ifcSend(
				editorUrl,
                top.window, 
                "editOverrides",
                {"srcLang": srcLang, 
                 "dstLang": dstLang,
                 "partner": window.location.href,
                 "phrases": jQuery(this).data('texts')});
        });
        
        var bodyHeight = jQuery('body').height();
        // if page is loaded by javascript
        if (bodyHeight<200) {
            bodyHeight = 4000;
        }
        
        //alert("hide: " + editorUrl);		

        jQuery.ifcSend(
			editorUrl,
            top.window, 
            "hideLoader", 
            {"partner": window.location.href,
             "bodyHeight": bodyHeight});
    }
    
    window.editError = function(info){
        jQuery('#editor .preloader').html('<b style="color: red;">' + info + '</b>');
    };

    window.editOK = function(info){
        jQuery('#editor .preloader').html('<b style="color: green;">' + info + '</b>');
        setTimeout("jQuery('#editor').remove()", 500);
        if (window.location.hash == '') {
            location.href = window.location.href + 'translate_to=' + dstLang + ',edit=' + editSecret;
        }
        location.reload();
    };
    
    console.debug('Translating...');

    var context = 0;
    var texts = [];
    var totalLength = 0;
    var allTexts = {};

    var translated = 0;
    var all = 0;
    var isAlreadyDone = false;

    // timing
    var start = new Date();

    function fixTranslation(t) {        
        return t.replace(/&#39;/g, "'")
            .replace(/&quot;/g, '"')
            .replace(/&lt;/g, "<")
            .replace(/&gt;/g, ">")
            .replace(/&amp;/g, "&");
    }

    window._translatedCallback = function(context, result) {
        jQuery(result).each(function(index, value) {
            var translatedText = value.responseData ? 
                                    value.responseData.translatedText : 
                                    value.translatedText;
            if(translatedText){
                allTexts[context][index].set(fixTranslation(translatedText));
            }
            delete allTexts[context][index];                    
        });
        translated++;

        if(all) {
            callback(all, translated);
        }
        if(all && translated == all && !isAlreadyDone) {
            isAlreadyDone = true;
            console.debug('Translated in: ',  
                          (new Date().getTime() - start.getTime()), ' ms');

            try {
                fix(doc, dstLang, ecommerceTracker);
            } catch (x) {
                console.error("Exception in fix function: " + x);
            }

            if(top.partnerWindow) {
                editOverridesViaNewPortalEditor();
            }
        }
    };

    groupTexts(
        jQuery(doc).find('html').find(":not(script,style,.ctcWidget)").contents(), 
        overrides, 
        function(acc, text) {
            if(!acc) {
                acc = "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0";
                acc += "&langpair=" + srcLang + "|" + dstLang;    
            };
            return acc + "&q=" + encodeURIComponent(text);
        },
        1900, //2000 is said to be the limit for GETs to google servers
        function(url, texts) {
            //console.debug(url.length);            
            url += "&context=" + context; 
            url += "&callback=_translatedCallback";
            allTexts[context] = texts;
            jQuery.getScript(url);
            context++;                                    
        });
    all = context;
};
})();
