var serviceURL = 'http://cownter.cownt.us/';    // URL of the Cownter service
var BUBBLEDELAY = 100;                          // How long to wait before showing bubbles, 0 gets annoying, ms
var POLLINTERVAL = 60000;                       // DO NOT CHANGE! time between polls that tell the server user is still on the page, ms
var SESSIONPERSISTANCE = 2880;                  // Amount of minutes that the session cookie remains in the browser
var IMGCOMPLETEINTERVAL = 100;                  // Interval checking if image completed downloading, ms 
var VERSION = 1.1                               // Version of the cowrate protocol
window.cownter_bubbleState = 'ON';              // Bubbles are on by default, global to avoid reading cookie all the time
// window.cowntus_token and window.cownt_us_ignore_param are the only exterval variables for cownter

// Add CSS that defines look of the bubble
document.write('<link rel="stylesheet" type="text/css" href="http://cownt.us/cownter.css" />');

// Add load and unload events
addLoadEvent(preparePage);
addBeforeUnloadEvent(cleanupPage)
addUnloadEvent(cleanupPage);

// Executes onLoad 
function preparePage() {

    // Capture URI, sans protocol prefix
    var myurl = window.location.toString().replace(/https?:\/\//,'');
    window.cownter_curr_key = encodeURIComponent(encodeURIComponent(myurl));
    
    // This is the only error you should see from the cownter JavaScript. 
    // You need to provide a token that was given to you when you signed up. Visit http://cowntus.com for info.
    if (!window.cowntus_token) {
      alert("Cownter requires a cowntus_token token to work. Visit cownt.us for info.");
      return false;
    }
    
    // Add bubble container to HTML body
    var container = document.createElement("div");
    container.setAttribute("id", "cownter_container"); 
    document.body.appendChild(container);

    // Increment page cownter on the server; start polling
    incrPage();
    window.cownter_poll_interval = setInterval(incrPage, POLLINTERVAL);

    // Add mouseover events
    addMouseOvers();

    // Show button in OFF position if user turned bubbles off
    if (readCookie("cownterBubbleState") == "OFF") {
        window.cownter_bubbleState = "OFF";
        var cownterImg;
        if (cownterImg = document.getElementById("cownterState")) {
            cownterImg.src= "http://cownt.us/images/cownter-off.png";
        }
    }
}


// Executes onUnload
function cleanupPage() {

    // Decrement the page counter
    decrPage();

    // Clear the bubble timer
    if (window.cownter_bubbletimer) {
        clearTimeout(window.cownter_bubbletimer);
    }

    // Clear the image interval timer
    if (window.cownter_num_img_interval){
        clearInterval(window.cownter_num_img_interval);
    }

    // Clear the poll interval
    if (window.cownter_poll_interval){
        clearInterval(window.cownter_poll_interval);
    }
}


// Executes onMouseOver
function linkMouseOverHandler(e) {

    // Show bubble if user wants to see it
    if (window.cownter_bubbleState == "ON") {
        if (window.event) {
            window.cownter_element = window.event.srcElement;
            link = window.cownter_element.toString();
        } else {          
            window.cownter_element = e.currentTarget;  
            link = window.cownter_element.toString();
        } 

       // Strip url then double-encode it
       var regex = /https?:\/\//;
       var myurl = link.replace(regex, "");
       window.cownter_over_key = encodeURIComponent(encodeURIComponent(myurl));

       // Pause a before showing bubble
       window.cownter_bubbletimer = setTimeout(showBubble, BUBBLEDELAY);
    }
}

// Called when mouse has remained over the link for BUBBLEDELAY ms 
function showBubble() {
    if (window.cownter_element) {
        // Get mouse position
        var pos = getElementPosition(window.cownter_element);
        var offsetWidth = window.cownter_element.offsetWidth?window.cownter_element.offsetWidth:0;

        // Make div with all needed position info (does not start displaying)
        window.cownter_img = document.createElement("div");
        window.cownter_img.setAttribute("id", "cownter_bubble");
        window.cownter_img.style.left = (pos.px + offsetWidth + 3) + "px"; 
        window.cownter_img.style.top = (pos.py - 5) + "px";

        getPage();
    }
}

// Executes onMouseOut
function linkMouseOutHandler(e) {   
    
    // Reset bubbletimer, do not want to show bubble after the mouse has moved from the link
    if (window.cownter_bubbletimer) {
        clearTimeout(window.cownter_bubbletimer);
    }
    
    // Reset image interval
    if (window.cownter_num_img_interval){
       clearInterval (window.cownter_num_img_interval);
    }

    if (window.cownter_img){
        var node = document.getElementById("cownter_container");
        while (node.hasChildNodes()) {
            node.removeChild(node.firstChild);
        }
    }
}

// Increment the counter
function incrPage() {

    // Generate sid if we don't already have one
    if (!window.cownter_sid) { 
        var sid  = readCookie("cownterSid");
        if (!sid) {
            sid = generateSid();
            setCookie("cownterSid", sid, SESSIONPERSISTANCE);
        }
        // We cannot pass args to interval/callback functions so set globals
        window.cownter_sid = sid;
    }

    // If no cownter_title given, pull it from the page
    if (!window.cownter_title) {
        window.cownter_title = document.title;
    }

    // Generate the request URI
    var req = serviceURL + VERSION + "/incr/"+ window.cownter_curr_key + "/" + window.cownter_title + "/" + window.cownter_sid + "/" + window.cowntus_token + "/" + generateSid();
    window.cownter_incr_img = null;
    window.cownter_incr_img = new Image();
    window.cownter_incr_img.src = req;
    window.cownter_incr_img_interval = setInterval(showDock, IMGCOMPLETEINTERVAL);
}

// Decrement the counter
function decrPage() {
    var req  = serviceURL + VERSION + "/decr/" + window.cownter_curr_key + "/" + window.cownter_sid + "/" + window.cowntus_token + "/" + generateSid();
    window.cownter_decr_img = null;
    window.cownter_decr_img = new Image();
    window.cownter_decr_img.src = req;
}

// Get count information from cownter server
function getPage() {
    var req  = serviceURL + VERSION + "/get/" + window.cownter_over_key + "/" + window.cownter_sid + "/" + window.cowntus_token + "/" + generateSid();
    window.cownter_num_img = new Image();
    window.cownter_num_img.src = req;
    window.cownter_num_img_interval = setInterval(showNumber, IMGCOMPLETEINTERVAL);
}

function waitForDecr(){
    if (window.cownter_dect_img_interval) {
        clearInterval(window.cownter_dect_img_interval);
    }
    if (!window.cownter_decr_img.complete) {
        window.cownter_dect_img_interval = setInterval(waitForDecr, IMGCOMPLETEINTERVAL);
    }
}

// Show the dock
function showDock() {
    if (window.cownter_incr_img.complete) {

        clearInterval(window.cownter_incr_img_interval);
        var dock = document.getElementById("cownter_dock");

        if (window.cownter_incr_img && dock) {
            var count = null;
            if (window.cownter_incr_img.height == 3) {
                count = '-';
            } else if (window.cownter_incr_img.height == 2) {
                count = 0;
            } else {
                count = window.cownter_incr_img.width;
            }

            dock.innerHTML = count + " visitors";
        }
    }
}

// Show the number in the cownter bubble
function showNumber() {
    if (window.cownter_num_img.complete) {
        clearInterval(window.cownter_num_img_interval);

        if (window.cownter_img) {
            var count = null;
            if (window.cownter_num_img.height == 3) {
                count = '-';
            } else if (window.cownter_num_img.height == 2) {
                count = 0;
            }else{
                count = window.cownter_num_img.width;
            }
          
            window.cownter_img.innerHTML = '<div id="cownter_number">' + count + '</div>';
            var container = document.getElementById("cownter_container");
            container.appendChild(window.cownter_img);
        }
    }
}


// Generate a "unique enough" session id 
function generateSid() {
      var now = new Date();
      var rnum = "" + now.getHours(); 
      return rnum.concat(now.getMinutes(), now.getSeconds(), now.getMilliseconds(), Math.floor(Math.random() * 10000));
}

// Called when the button is clicked to turn the bubbles on and off
function CownterBubbleToggle(e, elem) {
    var xLoc = e.clientX - elem.x;
    if (xLoc > 60) {
        if (window.cownter_bubbleState == "ON") {
            setCookie("cownterBubbleState", "OFF");
            window.cownter_bubbleState = "OFF";
            elem.src = "http://cownt.us/images/cownter-off.png";
        } else {
            removeCookie("cownterBubbleState");
            window.cownter_bubbleState = 'ON';
            elem.src = "http://cownt.us/images/cownter-on.png";
        }
    } else {
        document.location = "http://cownt.us/apps.html";
    }
}

// Called when the button is clicked to turn the bubbles on and off
function BubbleToggle(elem) {
    if (window.cowrate_bubbleState == "ON") {
        setCookie("cownterBubbleState", "OFF");
        window.cowrate_bubbleState = "OFF";
        elem.src = "http://cownt.us/images/cownter-off.png";
    } else {
        removeCookie("cownterBubbleState");
        window.cowrate_bubbleState = 'ON';
        elem.src = "http://cownt.us/images/cownter-on.png";
    }
}

// Add onLoad callback to the other onLoad events that may be registered
// Makes sure to not override current onLoad functionality 
function addLoadEvent(func) {
    var oldonload = window.onload;
    if (typeof window.onload != "function") {
        window.onload = func;
    } else {
        window.onload = function() {
            if (oldonload) {
                oldonload();
            }
            func();
        }
    }
}

function addBeforeUnloadEvent(func) {
    var oldonbeforeunload = window.onbeforeunload;
    if (typeof window.onbeforeunload != "function") {
        window.onbeforeunload = func;
    } else {
        window.onbeforeunload = function() {
            if (oldonbeforeunload) {
                oldonbeforeunload();
            }
            func();
        }
    }
}

function addUnloadEvent(func) {
    var oldonunload = window.onunload;
    if (typeof window.onunload != "function") {
        window.onunload = func;
    } else {
        window.onunload = function() {
            if (oldonunload) {
                oldonunload();
            }
            func();
        }
    }
}


// Add onMouseOver and onMouseOut handlers
function addMouseOvers() {
    if (document.getElementsByTagName) {
        var links = document.getElementsByTagName("a");
        for(var i = 0; i < links.length; i++) {

            // Account for existing onMouseOver events
            if (typeof links[i].onmouseover == "function") {

                links[i].oldmouseover = links[i].onmouseover;
                links[i].oldmouseout = links[i].onmouseout;

                links[i].onmouseover = function(e) {
                    this.oldmouseover();
                    linkMouseOverHandler(e);
                }
                links[i].onmouseout = function(e) {
                    this.oldmouseout();
                    linkMouseOutHandler(e);
                }
            } else {
                links[i].onmouseover = linkMouseOverHandler;
                links[i].onmouseout = linkMouseOutHandler;
            }
        }
    }
}


// Generic function to get position of an element; cross-browser
function getElementPosition(elem) {
    var positionX = 0;
    var positionY = 0;

    if (elem) {
        var elemParent = elem.offsetParent;

        if (elemParent) {
            while ((elemParent = elem.offsetParent) != null) {
                positionX += elem.offsetLeft;
                positionY += elem.offsetTop;
                elem = elemParent;
            }
        } else {
            positionX = elem.offsetLeft;
            positionY = elem.offsetTop;
        }
    }
    return {"px" : positionX, "py" : positionY};
}


// Set a domain cookie
function setCookie(key, value, expMin) {
    var expires_date;
    if (expMin) {
        var expires = expires * 1000 * 60;
        var d = new Date();
        expires_date = new Date(d.getTime() + (expires));;
        document.cookie = key + "=" + escape(value) + "; expires=" +  expires_date.toGMTString() + "; path=/";
    } else {
        document.cookie = key + "=" + escape(value) + "; path=/";
    }
}

// Remove a domain cookie
function removeCookie(key) {
    var cookieDate = new Date(2000,1,1,1,1,1);
    document.cookie = key + "=; expires=" + cookieDate.toGMTString() + "; path=/";
}

// Read a domain cookie
function readCookie(key) {
    var cookie = document.cookie;
    var first = cookie.indexOf(key + "=");

    if (first >= 0){
        var str = cookie.substring(first, cookie.length);
        var last = str.indexOf(";");

        if (last < 0) last = str.length;

        str = str.substring(0, last).split("=");
        return unescape(str[1]);

    } else {
        return null;
    }
}

