/// <reference path="MicrosoftAjax.debug.js"/>

Browser = {};

Browser.InternetExplorer = {};
Browser.Firefox = {};
Browser.Safari = {};
Browser.Opera = {};

Browser.agent = null;
Browser.hasDebuggerStatement = false;
Browser.name = navigator.appName;
Browser.version = parseFloat(navigator.appVersion);

if (navigator.userAgent.indexOf(' MSIE ') > -1) {
    Browser.agent = Browser.InternetExplorer;
    Browser.version = parseFloat(navigator.userAgent.match(/MSIE (\d+\.\d+)/)[1]);
    Browser.hasDebuggerStatement = true;
}
else if (navigator.userAgent.indexOf(' Firefox/') > -1) {
    Browser.agent = Browser.Firefox;
    Browser.version = parseFloat(navigator.userAgent.match(/ Firefox\/(\d+\.\d+)/)[1]);
    Browser.name = 'Firefox';
    Browser.hasDebuggerStatement = true;
}
else if (navigator.userAgent.indexOf(' Safari/') > -1) {
    Browser.agent = Browser.Safari;
    Browser.version = parseFloat(navigator.userAgent.match(/ Safari\/(\d+\.\d+)/)[1]);
    Browser.name = 'Safari';
}
else if (navigator.userAgent.indexOf('Opera/') > -1) {
    Browser.agent = Browser.Opera;
}

function getWindowSize()
{
    var myWidth = 0, myHeight = 0;
    if( typeof( window.innerWidth ) == 'number' ) {
        //Non-IE
        myWidth = window.innerWidth;
        myHeight = window.innerHeight;
    } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
        //IE 6+ in 'standards compliant mode'
        myWidth = document.documentElement.clientWidth;
        myHeight = document.documentElement.clientHeight;
    } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
        //IE 4 compatible
        myWidth = document.body.clientWidth;
        myHeight = document.body.clientHeight;
    }

    return { width: myWidth, height: myHeight };
}

function getInnerText(element)
{
    if( typeof(element.innerText) === "undefined" )
    {
        return element.textContent;
    } 
    else
    {
        return element.innerText;
    }
}

function getMouseLocation( evt )
{
    if (evt.pageX) 
        return { x: evt.pageX, y: evt.pageY }; 
    else if (evt.clientX) 
    {
        if( document.documentElement.scrollLeft  != null )
        {
            return { x: evt.clientX + document.documentElement.scrollLeft, y: evt.clientY + document.documentElement.scrollTop }; 
        }
        else
        {
            return { x: evt.clientX + document.body.scrollLeft, y: evt.clientY + document.body.scrollTop }; 
        }
    }
    else 
        return { x: 0, y: 0 };
}

MD5 = function()
{
}

/*
 * Configurable variables. You may need to tweak these to be compatible with
 * the server-side, but the defaults work in most cases.
 */
MD5.hexcase = 1;  /* hex output format. 0 - lowercase; 1 - uppercase        */
MD5.b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
MD5.chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */

MD5.prototype =
{
    getHEX : function( text )
    {
        return MD5.binl2hex(MD5.core_md5(MD5.str2binl( text ), text.length * MD5.chrsz));
    }
}

MD5.core_md5 = function(x, len)
{//Calculate the MD5 of an array of little-endian words, and a bit length
  /* append padding */
  x[len >> 5] |= 0x80 << ((len) % 32);
  x[(((len + 64) >>> 9) << 4) + 14] = len;

  var a =  1732584193;
  var b = -271733879;
  var c = -1732584194;
  var d =  271733878;

  for(var i = 0; i < x.length; i += 16)
  {
    var olda = a;
    var oldb = b;
    var oldc = c;
    var oldd = d;

    a = MD5.md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
    d = MD5.md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
    c = MD5.md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
    b = MD5.md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
    a = MD5.md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
    d = MD5.md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
    c = MD5.md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
    b = MD5.md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
    a = MD5.md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
    d = MD5.md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
    c = MD5.md5_ff(c, d, a, b, x[i+10], 17, -42063);
    b = MD5.md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
    a = MD5.md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
    d = MD5.md5_ff(d, a, b, c, x[i+13], 12, -40341101);
    c = MD5.md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
    b = MD5.md5_ff(b, c, d, a, x[i+15], 22,  1236535329);

    a = MD5.md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
    d = MD5.md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
    c = MD5.md5_gg(c, d, a, b, x[i+11], 14,  643717713);
    b = MD5.md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
    a = MD5.md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
    d = MD5.md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
    c = MD5.md5_gg(c, d, a, b, x[i+15], 14, -660478335);
    b = MD5.md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
    a = MD5.md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
    d = MD5.md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
    c = MD5.md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
    b = MD5.md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
    a = MD5.md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
    d = MD5.md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
    c = MD5.md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
    b = MD5.md5_gg(b, c, d, a, x[i+12], 20, -1926607734);

    a = MD5.md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
    d = MD5.md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
    c = MD5.md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
    b = MD5.md5_hh(b, c, d, a, x[i+14], 23, -35309556);
    a = MD5.md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
    d = MD5.md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
    c = MD5.md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
    b = MD5.md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
    a = MD5.md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
    d = MD5.md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
    c = MD5.md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
    b = MD5.md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
    a = MD5.md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
    d = MD5.md5_hh(d, a, b, c, x[i+12], 11, -421815835);
    c = MD5.md5_hh(c, d, a, b, x[i+15], 16,  530742520);
    b = MD5.md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);

    a = MD5.md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
    d = MD5.md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
    c = MD5.md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
    b = MD5.md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
    a = MD5.md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
    d = MD5.md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
    c = MD5.md5_ii(c, d, a, b, x[i+10], 15, -1051523);
    b = MD5.md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
    a = MD5.md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
    d = MD5.md5_ii(d, a, b, c, x[i+15], 10, -30611744);
    c = MD5.md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
    b = MD5.md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
    a = MD5.md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
    d = MD5.md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
    c = MD5.md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
    b = MD5.md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);

    a = MD5.safe_add(a, olda);
    b = MD5.safe_add(b, oldb);
    c = MD5.safe_add(c, oldc);
    d = MD5.safe_add(d, oldd);
  }
  return Array(a, b, c, d);

}

/*
 * These functions implement the four basic operations the algorithm uses.
 */
MD5.md5_cmn = function(q, a, b, x, s, t)
{
  return MD5.safe_add( MD5.bit_rol( MD5.safe_add( MD5.safe_add(a, q), MD5.safe_add(x, t)), s), b);
}
MD5.md5_ff = function(a, b, c, d, x, s, t)
{
  return MD5.md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
MD5.md5_gg = function(a, b, c, d, x, s, t)
{
  return MD5.md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
MD5.md5_hh = function(a, b, c, d, x, s, t)
{
  return MD5.md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
MD5.md5_ii = function(a, b, c, d, x, s, t)
{
  return MD5.md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}

MD5.core_hmac_md5 = function(key, data)
{
///Calculate the HMAC-MD5, of a key and some data
  var bkey = MD5.str2binl(key);
  if(bkey.length > 16) bkey = MD5.core_md5(bkey, key.length * MD5.chrsz);

  var ipad = Array(16), opad = Array(16);
  for(var i = 0; i < 16; i++)
  {
    ipad[i] = bkey[i] ^ 0x36363636;
    opad[i] = bkey[i] ^ 0x5C5C5C5C;
  }

  var hash = MD5.core_md5(ipad.concat(MD5.str2binl(data)), 512 + data.length * MD5.chrsz);
  return MD5.core_md5(opad.concat(hash), 512 + 128);
}

/*
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * to work around bugs in some JS interpreters.
 */
MD5.safe_add = function(x, y)
{
  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  return (msw << 16) | (lsw & 0xFFFF);
}

/*
 * Bitwise rotate a 32-bit number to the left.
 */
MD5.bit_rol = function(num, cnt)
{
  return (num << cnt) | (num >>> (32 - cnt));
}

/*
 * Convert a string to an array of little-endian words
 * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
 */
MD5.str2binl = function(str)
{
  var bin = Array();
  var mask = (1 << MD5.chrsz) - 1;
  for(var i = 0; i < str.length * MD5.chrsz; i += MD5.chrsz)
    bin[i>>5] |= (str.charCodeAt(i / MD5.chrsz) & mask) << (i%32);
  return bin;
}

/*
 * Convert an array of little-endian words to a hex string.
 */
MD5.binl2hex = function(binarray)
{
  var hex_tab = MD5.hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i++)
  {
    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
  }
  return str;
}


BlinkInfor = function()
{
    this.timeOut = 300;
    this.xmlRequest = null;
    this.container = null;
    this.evt = null;
    this.mouseLoc = null;
    this.isOnContainer = false;
    this.isOnAnchor = false;
    this.timer = null;
    
    this._loadWindowDelegate = Function.createDelegate(this, this.initBlinkInfo);
    this._initShow = Function.createDelegate(this, this.initShow);
    this._hideDelegate = Function.createDelegate(this, this.hide);
    this._onContainerMouse = Function.createDelegate(this, this.onContainerMouse);
    this._onMouseAnchor = Function.createDelegate(this, this.onMouseAnchor);
    this._onTimer = Function.createDelegate(this, this.onTimer);
    this._requestCompleted = Function.createDelegate(this, this.requestCompleted);
    
    if ( Browser.agent != null )
    {
        $addHandler( window, 'load', this._loadWindowDelegate );
    }   
}

BlinkInfor.prototype = 
{
    dispose : function()
    {
        if( this._initShow != null )
        {
           delete this._initShow;
           delete this._hideDelegate;
           delete this._requestCompleted;
        }
        if( this._loadWindowDelegate != null )
        {
            delete this._loadWindowDelegate;
        }
    },

    createElement : function()
    {
        var div = document.createElement( "div" );
        div.setAttribute( "id", "blinkInfor" );
        
        if( Browser.agent == Browser.Firefox )
            div.setAttribute( "class", "tip" );
        else
            div.setAttribute( "className", "tip" );
        
        document.body.appendChild( div );
        
        $addHandler( div, 'mouseover', this._onContainerMouse );
        $addHandler( div, 'mouseout', this._onContainerMouse );
        return div;
    }, 

    initBlinkInfo : function()
    {
        delete this._loadWindowDelegate;
        
        if( this._initShow != null )
        {
            this.container = this.createElement();
            for( var i = 0; i < document.links.length; ++i )
            {
                var anchor = document.links[i];
                $addHandler( anchor, 'mouseover', this._onMouseAnchor );
                $addHandler( anchor, 'mouseout', this._onMouseAnchor );
            }
        }
    },
    
    onContainerMouse : function( evt )
    {
        if( evt.type == "mouseover" )
        {
            this.isOnContainer = true;
            this.stopTimer();
        }
        else
        {
            this.isOnContainer = false;
            this.startTimer();
        }
    },
    
    onMouseAnchor : function( evt )
    {
        if( evt.type == "mouseover" )
        {
            this.isOnAnchor = true;
            if( this.evt == null || 
                this.evt.target != evt.target )
            {
                this.stopTimer();
                this.hide();
                this.initShow( evt );
            }
        }
        else
        {
            this.isOnAnchor = false;
            this.startTimer();
        }
    },
    
    startTimer : function()
    {
        this.stopTimer();
        this.timer = window.setTimeout( this._onTimer, this.timeOut );
    },
    
    stopTimer : function()
    {
        if (this.timer != null) 
        {
            window.clearTimeout(this.timer);
            this.timer = null;
        }
    },
    
    onTimer : function()
    {
        this.stopTimer();
        if( !this.isOnContainer &&
            !this.isOnAnchor )
        {
            this.hide();
        }
    },
    
    initShow : function( evt )
    {
        if ( Browser.agent != null )
        {
            this.evt = evt;
            this.mouseLoc = getMouseLocation( evt );

            if(typeof(evt.target.href) === "undefined")
            {
                return;
            }
            
            var url = evt.target.href;
            if( url.endsWith("/") )
            {
                url = url.substring(0, url.length - 1);
            }
            
            var urlInnerText = getInnerText(evt.target).replace(/\s/g,'');
            if( urlInnerText.length > 0)
            {
                url += "-" + md5.getHEX(urlInnerText);
            }
             
            url +=".htm";
            
            var re = new RegExp("^http://*", "i");
            url = url.replace(re, "");
            re = new RegExp("^https://*", "i");
            url = url.replace(re, "");
            re = new RegExp("^ftp://*", "i");
            url = url.replace(re, "");

            if(typeof(blinkRootPath) !== "undefined")
            {
                url = blinkRootPath + "/" + url;
            }
            else
            {
                url = "blinkInfor/" + url;
            }
            
            if( this.xmlRequest != null )
            {
                var executor = this.xmlRequest.get_executor();
                executor.abort();
            }
            this.xmlRequest = new Sys.Net.WebRequest();
            this.xmlRequest.set_httpVerb("GET");
            this.xmlRequest.add_completed(this._requestCompleted);
            this.xmlRequest.set_url(url);
            this.xmlRequest.invoke();    
        }
    },

    requestCompleted : function(executor, eventArgs) 
    {
        if( executor.get_responseAvailable() )
        {
            if( executor.get_statusCode() == 200 ) 
            {
                var dm = this.container; 
                Sys.UI.DomElement.setLocation( dm, 0, 0 );
                dm.innerHTML = executor.get_responseData();
                
                this.xmlRequest = null;
                
                var eBoudns = Sys.UI.DomElement.getBounds( dm );
                var eW = eBoudns.width;
                var eH = eBoudns.height;

                var wSize = getWindowSize();
                var wH = wSize.height;
                var wW = wSize.width;
                
                var mousePosX = this.mouseLoc.x;
                var mousePosY = this.mouseLoc.y;
                
                var clientX = this.evt.clientX;
                var clientY = this.evt.clientY;
                
                lv = mousePosX - (eW/2); 
                tv = mousePosY + 10;
                
                if( clientY + eH + 10 > wH && clientY - eH > 10 )
                {
                    tv = mousePosY - eH - 10;
                }
                else
                {
                    tv = mousePosY + 10;
                }
                            
                if (clientX - eW/2 < 5)
                    lv -= clientX - eW/2 - 5;
                else if (clientX + eW/2 > wW - 20)
                {
                    lv -= clientX + eW/2 - wW + 20;
                }
                
                Sys.UI.DomElement.addCssClass( this.evt.target, "goodBlink" );
                Sys.UI.DomElement.setLocation( dm, lv, tv );
                dm.style.visibility = "visible";
            }
            else if( executor.get_statusCode() == 502 ||
                  executor.get_statusCode() == 409 ||
                  executor.get_statusCode() == 403 ||
                  executor.get_statusCode() == 504 ||
                  executor.get_statusCode() == 410 ||
                  executor.get_statusCode() == 500 ||
                  executor.get_statusCode() == 505 ||
                  executor.get_statusCode() == 301 ||
                  executor.get_statusCode() == 204 ||
                  executor.get_statusCode() == 406 ||
                  executor.get_statusCode() == 404 ||
                  executor.get_statusCode() == 402 ||
                  executor.get_statusCode() == 407 ||
                  executor.get_statusCode() == 408 ||
                  executor.get_statusCode() == 401 ||
                  executor.get_statusCode() == 401 )
            {
                Sys.UI.DomElement.addCssClass( this.evt.target, "errorBlink" );
            }
        }
    },

    hide : function()
    {
        if( this.xmlRequest != null )
        {
            var executor = this.xmlRequest.get_executor();
            executor.abort();
            this.xmlRequest = null;
        }

        if (this.container.style.visibility == "visible" || this.container.style.visibility == "show") 
        {
            this.container.style.visibility = "hidden"; 
        }
    }
}
var md5 = new MD5();
var blinkInfor = new BlinkInfor();
