// Autolinks.
var MTAutolinks = Class.create();
MTAutolinks.prototype = {
    // Declaration default fields.
    initialize: function(keywords, default_css, limited, encrypt_url){
        this.keywords = keywords;
        this.default_css = default_css;
        this.limited = limited;
        this.encrypt_url = encrypt_url;
        // Initialize the current node.
        var rootNode;
        // Check the current node. If not exist, create the current node default.        
        rootNode = document.body;        
        // There are elements that exclude in current node.                
        this.excludes = 'option, select, noscript, form, br, script, object, iframe, a, img, input, button, textarea';
        // Loop: put the keyword into function replace keyword.
        keywords.each(function(keyword){
            this.findAndReplace(keyword, rootNode);
        }.bind(this));
    },
    // Function: find all nodes, initialization parameters and check conditions. 
    findAndReplace: function(keyword, searchNode) {
        // Check keywords have been replaced. If have no keywords replaced, assigned the value is: 0.
        if(!keyword.replaced)
            keyword.replaced = 0;
        // If limit exceeded, out of function.
        if(keyword.replaced == keyword.limit)
            return;
        // Check fields.
        if(keyword.custom_css == '')
            keyword.custom_css = this.default_css;
        if(keyword.limit == 0)
            keyword.limit = this.limited;
        // Create regular expression for keyword, childnodes.
        var regex = typeof keyword.keyword == 'string' ?
                    new RegExp(keyword.keyword, 'gi') : keyword.keyword,
            childNodes = searchNode.childNodes,
            cnLength = childNodes.length,
            excludes = this.excludes;
        // If occurrence = 1 replace from top to down else replace from bottom to up.
        if(keyword.occurrence == 'top-down') {            
            for(var i = 0; i < cnLength; i++) {
                var currentNode = childNodes[i];
                // Check node type of current node and remove elements that excluded.
                if (currentNode.nodeType == 1 && (excludes + ',').indexOf(currentNode.nodeName.toLowerCase() + ',') == -1) {
                    // Run function again get all nodes of current node.
                    this.findAndReplace(keyword, currentNode);
                }
                // If it is node element node, run next command else back function if.
                if (currentNode.nodeType != 3 || !regex.test(currentNode.data)) {
                    continue;
                }
                // Get strings have been replaced.
                var result = this.replaceKeyword(currentNode.data, keyword);
                // Create the element contain strings have been replaced.
                var parent = currentNode.parentNode,
                    frag = (function(){
                        var html = result,
                            wrap = document.createElement('div'),
                            frag = document.createDocumentFragment();
                        wrap.innerHTML = html;
                        while (wrap.firstChild) {
                            frag.appendChild(wrap.firstChild);
                        }
                        return frag;
                    })();
                parent.insertBefore(frag, currentNode);
                parent.removeChild(currentNode);
            }
        } else if(keyword.occurrence == 'bottom-up') {
            for(var i = cnLength; i > 0; i--) {
                var currentNode = childNodes[i - 1];
                if (currentNode.nodeType == 1 && (excludes + ',').indexOf(currentNode.nodeName.toLowerCase() + ',') == -1) {
                    this.findAndReplace(keyword, currentNode);
                }
                if (currentNode.nodeType != 3 || !regex.test(currentNode.data) ) {
                    continue;
                }
                var result = this.replaceKeyword(currentNode.data, keyword);
                var parent = currentNode.parentNode,
                    frag = (function(){
                        var html = result,
                            wrap = document.createElement('div'),
                            frag = document.createDocumentFragment();
                        wrap.innerHTML = html;
                        while (wrap.firstChild) {
                            frag.appendChild(wrap.firstChild);
                        }
                        return frag;
                    })();
                parent.insertBefore(frag, currentNode);
                parent.removeChild(currentNode);
            }            
        } else if(keyword.occurrence == 'random-up') {
            var n = 0;
            for(var i = 0; i < cnLength; i++) {
                var currentNode = childNodes[Math.floor(cnLength * Math.random())];                
                // Check node type of current node and remove elements that excluded.
                if (currentNode.nodeType == 1 && (excludes + ',').indexOf(currentNode.nodeName.toLowerCase() + ',') == -1) {
                    // Run function again get all nodes of current node.
                    this.findAndReplace(keyword, currentNode);                    
                }
                // If it is node element node, run next command else back function if.
                if (currentNode.nodeType != 3 || !regex.test(currentNode.data)) {
                    continue;
                }
                // Get strings have been replaced.
                var result = this.replaceKeyword(currentNode.data, keyword);
                // Create the element contain strings have been replaced.
                var parent = currentNode.parentNode,
                    frag = (function(){
                        var html = result,
                            wrap = document.createElement('div'),
                            frag = document.createDocumentFragment();
                        wrap.innerHTML = html;
                        while (wrap.firstChild) {
                            frag.appendChild(wrap.firstChild);
                        }
                        return frag;
                    })();
                parent.insertBefore(frag, currentNode);
                parent.removeChild(currentNode);
            }           
        } else {
            for(var i = cnLength; i > 0; i--) {
                var currentNode = childNodes[Math.floor(cnLength * Math.random())];
                if (currentNode.nodeType == 1 && (excludes + ',').indexOf(currentNode.nodeName.toLowerCase() + ',') == -1) {                    
                    this.findAndReplace(keyword, currentNode);
                }
                if (currentNode.nodeType != 3 || !regex.test(currentNode.data)) {
                    continue;
                }
                var result = this.replaceKeyword(currentNode.data, keyword);
                var parent = currentNode.parentNode,
                    frag = (function(){
                        var html = result,
                            wrap = document.createElement('div'),
                            frag = document.createDocumentFragment();
                        wrap.innerHTML = html;
                        while (wrap.firstChild) {
                            frag.appendChild(wrap.firstChild);
                        }
                        return frag;
                    })();
                parent.insertBefore(frag, currentNode);
                parent.removeChild(currentNode);
            }
        }
    },
    // Function: replace strings contain keywords in database.
    replaceKeyword: function(text, keyword) {
        var strReplacement;
        var rel = '';
        var target = '';
        if(keyword.target == 1) {
            target = '_blank';
        } else {
            target = '';
        }
        if(keyword.nofollow == 1) {
            rel = 'nofollow';
        } else {
            rel = '';
        }
        if(keyword.encrypt_url == 1) {
            if(rel != '') {
                if(target != '') {
                    strReplacement = '<a href = "' + this.encrypt_url + 'id/' + keyword.autolinks_id + '" rel = "' + rel + '" title = "' + keyword.title + '" style = "' + keyword.custom_css + '" target = "' + target + '">' + keyword.keyword + '</a>';        
                } else {
                    strReplacement = '<a href = "' + this.encrypt_url + 'id/' + keyword.autolinks_id + '" rel = "' + rel + '" title = "' + keyword.title + '" style = "' + keyword.custom_css + '">' + keyword.keyword + '</a>';    
                }                
            } else {
                if(target != '') {
                    strReplacement = '<a href = "' + this.encrypt_url + 'id/' + keyword.autolinks_id + '" title = "' + keyword.title + '" style = "' + keyword.custom_css + '" target = "' + target + '">' + keyword.keyword + '</a>';        
                } else {
                    strReplacement = '<a href = "' + this.encrypt_url + 'id/' + keyword.autolinks_id + '" title = "' + keyword.title + '" style = "' + keyword.custom_css + '">' + keyword.keyword + '</a>';    
                }                
            }            
        } else {
            if(rel != '') {
                if(target != '') {
                    strReplacement = '<a href = "' + keyword.url + '" rel = "' + rel + '" title = "' + keyword.title + '" style = "' + keyword.custom_css + '" target = "' + target + '">' + keyword.keyword + '</a>';    
                } else {
                    strReplacement = '<a href = "' + keyword.url + '" rel = "' + rel + '" title = "' + keyword.title + '" style = "' + keyword.custom_css + '">' + keyword.keyword + '</a>';
                }                
            } else {
                if(target != '') {
                    strReplacement = '<a href = "' + keyword.url + '" title = "' + keyword.title + '" style = "' + keyword.custom_css + '" target = "' + target + '">' + keyword.keyword + '</a>';        
                } else {
                    strReplacement = '<a href = "' + keyword.url + '" title = "' + keyword.title + '" style = "' + keyword.custom_css + '">' + keyword.keyword + '</a>';    
                }                
            }            
        }        
        var newText = '';
        var index = 0;
        var compare = '';
        var flag = false;
        var regexKeyword = new RegExp('\\b' + keyword.keyword + '\\b', 'gi');
        // Loop: replace each piece of string.
        while(true) {
            // If limit exceeded, return true end continue replace each piece of string. 
            if(keyword.replaced == keyword.limit)
                flag = true;
            // If the text has been replaced was 'undefined', out of loop.
            if(text[index] == undefined)
                break;
            // Loop: compare words in string with keywords.
            for(i = index; i < (index + keyword.keyword.length); i++) {
                // If word is not undefined, addition compare with current text.
                if(text[i] != undefined)
                    compare += text[i];
            }
            // If exist keyword in string, replace keyword and increment number of keywords that replaced.            
            if(compare == keyword.keyword && flag == false) {
                if(text.search(regexKeyword) != -1) {
                    newText += strReplacement;
                    index += keyword.keyword.length;
                    compare = '';
                    keyword.replaced += 1;
                }
            } else {
                newText += text[index];
                index +=  1;
                compare = '';
            }
        }        
        return newText;
    }
};
