(function($) {
    
    var W = window, D = W.document;
    
    if(!W.LOP) {
        W.LOP = {};
    }
    
    // if(typeof W.console != 'object') {
    //     W.console = {};
    //     W.console.log = function() {};
    // }
    
    if(!W.cmSetProduction || 
       !W.cmCreatePageviewTag || 
       !W.cmCreateProductviewTag || 
       !W.cmCreateRegistrationTag || 
       !W.cmCreateErrorTag || 
       !W.cmCreatePageElementTag || 
       !W.cmCreateConversionEventTag) {
        return;
    }
    
    // define ClientID as global var
    cm_ClientID = "90285935";

    // set working environment
    var reDevHost = /\.(validation|contentmanager3|web[\d]{2})\.e-loreal\./i;
    // 
    if(!reDevHost.test(location.hostname)) {
       W.cmSetProduction();
    }
    
    // flag for popin tag duplicates
    var isPopin = false;
    
    var toTitleCase = function(str) {
        var tmp = str.split('_'), i = 0, l = tmp.length;
        while(i < l) {
            tmp[i] = tmp[i].charAt(0).toUpperCase() + tmp[i].substring(1);
            i++;
        }
        return tmp.join('_');
    };
    
    // specific tag creation
    var createTag = {
        article: function(datas) {
            var code = datas.code;
            if(!code && D.getElementById('dataCode')) {
                code = D.getElementById('dataCode').value;
            }
            return datas.url.replace(/.+\//, '').replace(/\.aspx/, '') + '_' + code;
        },video: function(datas) {
            return this.article(datas);
        },product: function(datas) {
            var code = datas.code;
            if(!code && D.getElementById('dataPrdCode')) {
                code = D.getElementById('dataPrdCode').value;
            }
            return datas.url.replace(/^\//, '').replace(/\//g, '_').replace(/\.aspx/, '') + '_' + code + (datas.suffix || '');
        },diag: function() {
            return D.getElementById('dataCode').value;
        },diagExpertAdvice: function() {
            return '1_' + getURLParams().code;
        },register: function() {
            return (D.referrer.indexOf('register-mandatory.aspx') > -1 || D.referrer.indexOf('my-datas-mandatory.aspx') > -1);
        },productPrint: function(datas) {
            var url;
            var code;
            if(D.getElementById('productPrint') && D.getElementById('dataPrdCode')) {
                url = D.getElementById('productPrint').value;
                code = D.getElementById('dataPrdCode').value;
            }
            return url.replace(/^\//, '').replace(/\//g, '_').replace(/\.aspx/, '') + '_' + code;
        },articlePrint: function(datas) {
            var url;
            var code;
            if(D.getElementById('articlePrint') && D.getElementById('dataCode')) {
                url = D.getElementById('articlePrint').value;
                code = D.getElementById('dataCode').value;
            }
            return url.replace(/.+\//, '').replace(/\.aspx/, '') + '_' + code;
        }
    };
    
    // extract tag datas from a string value and return a map
    var extract = function(str) {
        var results = {}, parts = str.split(';'), i = parts.length, tmp;
        while(i--) {
            tmp = parts[i].split('=');
            results[tmp[0]] = tmp[1];
        }
        if(createTag[results.tag]) {
            // trim product category hierarchy
            if(results.tag == 'product' && results.category.indexOf('^') > -1) {
                results.category = results.category.replace(/.+\^/, '');
            }
            results.tag = createTag[results.tag](results);
        }
        // manage search datas
        if(results.category == 'Search' && results.search) {
            var pages = D.getElementById('pages'), prd = D.getElementById('products');
            if(pages && prd) {
                results.number = pages.getElementsByTagName('li').length + prd.getElementsByTagName('li').length;
            } else {
                results.number = '0';
            }
        }
        // manage case on categories
        if (results.category) {
            results.category = toTitleCase(results.category);   
        }
        //console.log(results);
        return results;
    };
    
    // extract parameters from URL query string and return a map
    var getURLParams = function() {
        var qs = location.search;
        if(qs) {
            qs = qs.replace('?', '');
            var p = qs.split('&'), i = p.length, l = i - 1, tmp, r = {};
            while(i--) {
                tmp = p[l - i].split('=');
                if(tmp[1]) {
                    r[tmp[0]] = tmp[1];
                }
            }
            return r;
        }
        return null;
    };
    
    // tags bridges to CM methods, always need a datas object returned from the extract method
    var tags = {
        tagPageView: function(datas) {
            W.cmCreatePageviewTag(datas.tag, datas.category, datas.search || null, datas.number || null);
        },tagPopinPageView: function(datas) {
            W.cmCreatePageviewTag(datas.tag, datas.category, null, null);
        },tagProductView: function(datas) {
            W.cmCreateProductviewTag(datas.code, datas.tag, datas.category);
        },tagRegisterView: function(datas) {
            if(createTag.register()) {
                W.cmCreateRegistrationTag(datas.email, datas.email, datas.city, null, datas.zip, null, null);
            }
        },tagLoginView: function(datas) {
            W.cmCreateRegistrationTag(datas.email, datas.email, datas.city, null, datas.zip, null, null);
        },tagErrorView: function(datas) {
            W.cmCreateErrorTag(datas.tag, datas.category);
        },tagElementView: function(datas) {
            W.cmCreatePageElementTag(datas.tag, datas.category);
        },tagConversionView: function(datas){
            if(datas.page == 'optional') {
                if(createTag.register()) {
                    W.cmCreateConversionEventTag(datas.event, datas.type, datas.category, null);
                }   
            } else {
                W.cmCreateConversionEventTag(datas.event, datas.type, datas.category, null);
            }
        }
    };
    
    var reValidPreProdHost = /\.(validation|web[\d]{2})\.e-loreal\./i;
    
    // loop on HTML identifiers to find and call tags (if possible)
    var findAndExecTags = function() {
        // on validation or preprod hosts, no tagging allowed
        if(reValidPreProdHost.test(location.hostname)) {
            return;
        }
        
        var i = arguments.length, field, type, c = 0;
        
        while(i--) {
            type = arguments[i];
            if(tags[type]) {
                field = D.getElementById(type);
                if(field && field.value) {
                    tags[type](extract(field.value));
                    ++c;
                }
            }
        }
        
        // speed tagging if no tag found on page
        if(c === 0 && !isPopin && !D.getElementById('noTag')) {
            W.cmCreatePageviewTag(null, null, null, null);
        }
        
        isPopin = false;
    };
    
    // find tags on domReady
    $(function() {
        // find tags on popins opening
        if(LOP.popins) {
            LOP.popins.addListeners({
                'open': {
                    'fn': function() {
                        isPopin = true;
                        findAndExecTags('tagPopinPageView');
                    }
                },
                'open#brand': {
                    'fn': function() {
                        isPopin = true;
                        findAndExecTags('tagPopinPageView');
                    }
                }
            });
        }
        findAndExecTags('tagPageView', 'tagProductView', 'tagRegisterView', 'tagLoginView', 'tagErrorView', 'tagConversionView');
    });
    
    LOP.findAndExecPopinTag = function() {
        isPopin = true;
        findAndExecTags('tagPopinPageView');
    };
    
    // call tags with a descriptive string (can be called from a user click on a link for example)
    LOP.execStatCM = function(str) {
        if(typeof str == 'string' && str) {
            var datas = extract(str);
            
            if(tags[datas.type]) {
                tags[datas.type](datas);
            }
        }   
    };
    
})(jQuery);
