/** Copyright (c) 2001-2011 Laszlo Systems, Inc. All Rights Reserved. */
var gDataDetection=new function(){
//Private vars
var self=this;
var actionDropDowns={};
var actionText={};
//Public vars
this.actionDropDown=null;
this.mousedOverElement=null;
//Not moused over state
this.borderWidth='1px';
this.borderStyle='dotted';
this.borderColor='#999';
this.backgroundColor='#FFF';
//Moused over state
this.borderStyleOver='solid';
this.borderColorOver='#999';
this.backgroundColorOver='#EEE';

/** Returns the parent window object of the given element.
    @param elem - DOM node */
this.getWindowByElement=function(elem){return elem.ownerDocument[wgBrowser.isie ? 'parentWindow' : 'defaultView'];};

/** Initializes the data detection spans.
    @param theWindow - Window containing the data detection spans. */
this.initDataItems=function(theWindow){
    if(!theWindow) return;

    //Create arrow
    var self=gDataDetection;
    var doc=theWindow.document;
    var dd={view:doc.createElement('div'),img:doc.createElement('div')};
    theWindow.wgDataDetection=dd

    //Default view attributes
    var s=dd.view.style;
    s.position='absolute';
    s.left='-9999px';
    s.top='-9999px';
    s.borderStyle=self.borderStyleOver;
    s.backgroundColor=self.backgroundColorOver;
    s.borderWidth=[self.borderWidth,self.borderWidth,self.borderWidth,'0px'].join(' ');
    s.width='15px';
    s.height='15px';
    s.borderColor=self.borderColor;

    //Round corners via CSS for browsers that support it
    if(s.MozBorderRadius !== undefined){
        s.MozBorderRadiusTopright='2em';
        s.MozBorderRadiusBottomright='2em';
    }else if(s.WebkitBorderRadius !== undefined){
        s.WebkitBorderTopRightRadius='2em';
        s.WebkitBorderBottomRightRadius='2em';
    }

    //Image properties
    s=dd.img.style;
    s.width='15px';
    s.height='15px';
    s.position='relative';
    s.backgroundPosition='0 0';
    s.cursor='pointer';
    s.backgroundImage='url(images/smartobject.png)';
    dd.img.appendChild(doc.createTextNode(' '));

    //Append image view to parent
    dd.view.appendChild(dd.img);

    //Events
    dd.view.onmouseover=_viewMouseover;
    dd.view.onmouseout=self.mousedOut;
    dd.img.onmouseover=_imgMouseover;
    dd.img.onmouseout=_imgMouseout;
    dd.img.onmousedown=_imgMousedown;
    dd.img.onmouseup=_imgMouseup;

    doc.body.appendChild(dd.view);

    //Init spans
    var spans=doc.getElementsByTagName('span');
    var span;
    for(var i=0; spans.length > i; i++){
        span=spans[i];
        if(span.className.indexOf('wt_') == -1) continue;

        s=span.style;
        s.backgroundColor=this.backgroundColor;
        s.borderStyle=this.borderStyle;
        s.borderColor=this.borderColor;
        s.borderWidth=this.borderWidth;
        s.padding='0 2px';

        span.onmouseover=function(){
            self.handleMouseOver(this);
            var mt=this.wt_mouseoutTimer;
            if(mt) top.clearTimeout(mt);
        };
        span.onmouseout=gDataDetection.mousedOut;
    }
};

/** Adds an item to the menu type and creates the menu if it does not exist.
    @param String lzxMethodName - The lzx method to call in gDataDetectionCallback when this item is clicked.
    @param Array types - Array of menu types to add the item to.
    @param String text - The text to display for the item.
    @param Function canActOnMethod - Method which determines if the menu item should be enabled. */
this.addMenuItems=function(lzxMethodName,types,text,canActOnMethod){
    var items={};
    actionText[lzxMethodName]=items;
    var type,menu;
    for(var i=0; i < types.length; i++){
        type=types[i];
        menu=actionDropDowns[type];
        if(!menu) menu=actionDropDowns[type]=new JMenu(type);
        items[type]=new JMenuItem(menu,text,lzxMethodName,canActOnMethod);
    }
};

/** Updates the text string for the lzx method name.
    @param String lzxMethodName - The lzx method associated with this action.
    @param String text - The new text to set for the item. */
this.updateMenuText=function(lzxMethodName,text){
    var items=actionText[lzxMethodName];
    for(var key in items){
        items[key].setText(text);
    }
};

/** Handles the mouseout event for element associated with data detection.
    We need to delay the actual mouseout handlers to allow time for the
    mouseover events to fire. The reason this is not private is becuase it
    is used by JMenus and JMenuItems for their mouseout handlers. */
this.mousedOut=function(){
    var elem=gDataDetection.mousedOverElement;
    if(!elem) return;//Occurs when clicking on JMenuItem
    elem.wt_mouseoutTimer=top.setTimeout(function(){self.handleMouseOut(elem);},10);
};

/** Handles the onmouseover event for data detector elements.
    @param Object elem - DOM element on which the event occured */
this.handleMouseOver=function(elem){
    var dd=this.getWindowByElement(elem).wgDataDetection;
    if(this.actionDropDown) dd.img.style.backgroundPosition=this.actionDropDown.visible ? '0 15px' : '0 0';

    var isNew=this.mousedOverElement != elem;
    this.mousedOverElement=elem;
    var s=elem.style;
    s.borderStyle=this.borderStyleOver;
    s.borderColor=this.borderColorOver;
    s.backgroundColor=this.backgroundColorOver;

    if(!elem.wt_smo){
        var constr=elem.className.split(',')[0].substring(3);//TODO: Look into why we need the split.
        var content=elem.textContent ? elem.textContent : elem.innerText;//Standards compliant way vs the IE way
        elem.wt_smo={type:constr,value:content};
    }
    if(!isNew) return;

    //Summon arrow
    this.actionDropDown=actionDropDowns[elem.wt_smo.type];

    //Set the siblings to the same height
    var siblingSpan=elem.nextSibling;
    siblingSpan.style.fontSize=elem.style.fontSize;

    var pos=lz.embed.getAbsolutePosition(siblingSpan);
    var borderWidthNum=this.borderWidth.substring(0,this.borderWidth.length-2) * 1;
    var h=siblingSpan.offsetHeight;
    s=dd.view.style;
    s.height=h+'px';
    s.width='15px';
    s.left=pos.x - borderWidthNum+'px';
    s.top=pos.y - borderWidthNum+'px';
    dd.img.style.top=(h-15)/2+'px';//Vertically center the arrow
};

/** Handles the onmouseout event for data detector elements.
    @param Object elem - DOM element on which the event occured */
this.handleMouseOut=function(elem){
    //Reset data element
    var s=elem.style;
    s.borderStyle=gDataDetection.borderStyle;
    s.borderColor=gDataDetection.borderColor;
    s.backgroundColor=gDataDetection.backgroundColor;

    //Reset arrow
    var dd=this.getWindowByElement(elem).wgDataDetection;
    dd.img.style.backgroundPosition='0 0';

    //Reset arrow, if we "own" it
    if(this.mousedOverElement == elem){
        s=dd.view.style;
        s.backgroundColor=this.backgroundColorOver;
        s.left='-9999px';
        s.top='-9999px';
        this.mousedOverElement=null;
    }

    //Hide menu
    var aDD=actionDropDowns[elem.wt_smo.type];
    if(aDD.visible) aDD.hide();
};

/** Enables or disables the items of an actionDropDown.
    @param String name - the name of the actionDropDown to enable/disable its items
    @param Array itemsEnabled - Array of booleans in the order of the actionDropDown's items */
this.enableDropDown=function(name,itemsEnabled){
    var menu=actionDropDowns[name];
    var items=menu.items;
    var len=itemsEnabled.length;
    for(var i=0; i < len; i++){
        items[i].setEnabled(itemsEnabled[i]);
    }

    //Summon menu
    var arrow=gDataDetection.getWindowByElement(gDataDetection.mousedOverElement).wgDataDetection.img;
    var pos=lz.embed.getAbsolutePosition(arrow);
    var frameElement=gDataDetection.getWindowByElement(arrow).frameElement;
    var iframePos=lz.embed.getAbsolutePosition(frameElement);
    var docElem;
    if(wgBrowser.isie7){
        docElem=frameElement.contentWindow.document.documentElement;
    }else{
        docElem=(wgBrowser.ischrome || wgBrowser.issafari) ? frameElement.contentWindow.document.body : frameElement.contentDocument.documentElement;
    }
    theX=pos.x - docElem.scrollLeft + iframePos.x + arrow.offsetWidth/2;
    theY=pos.y - docElem.scrollTop + iframePos.y + arrow.offsetHeight/2;

    menu.visible=true;
    var padding=10;//Minimum pixels to display between a menu and the document edge.

    //Determine actionDropDown height for use in maxY
    var parentHeight=0;
    var domChildren=menu.view.childNodes;
    for(var i=0; i < domChildren.length; i++){
        parentHeight+=domChildren[i].clientHeight;
    }

    //Determine max x and y positions
    var maxEdges;
    if(wgBrowser.isie){//Fix for EM-14526
        var iframeElement=gDataDetection.mousedOverElement.ownerDocument.parentWindow.frameElement;
        maxEdges=lz.embed.getAbsolutePosition(iframeElement);
        maxEdges.x+=iframeElement.clientWidth;
        maxEdges.y+=iframeElement.clientHeight;
    }else{
        maxEdges={x:document.body.clientWidth,y:document.body.clientHeight};
    }
    var maxX=maxEdges.x - domChildren[0].clientWidth - padding;
    var maxY=maxEdges.y - parentHeight - padding;

    //Adjust x and y so the menu stays in the bounds of the document
    if(theX > maxX) theX=maxX;
    if(theY > maxY) theY=theY - gDataDetection.actionDropDown.view.clientHeight;

    menu.view.style.left=theX+'px';
    menu.view.style.top=theY+'px';
};

/* Update menu item hilite color */
this.updateHiliteColor=function(hiliteColor){
    JMenu.hiliteColor=hiliteColor;
}

/* Onmouseover function for the arrow's container */
var _viewMouseover=function(){
    var mt=gDataDetection.mousedOverElement.wt_mouseoutTimer;
    if(mt) top.clearTimeout(mt);
};

/* Onclick function for the arrow */
var _imgMousedown=function(){
    var _dropDown=gDataDetection.actionDropDown;
    if(_dropDown.visible){
        this.style.backgroundPosition='-30px -15px';
        _dropDown.hide();
        return;
    }

    this.style.backgroundPosition='-30px 0';

    //Call canActOn methods in Webtop
    var items=_dropDown.items;
    var len=items.length + 2;
    var toConcat=new Array(len);
    toConcat[0]='gDataDetection.enableDropDown';
    toConcat[1]=_dropDown.name;
    for(var i=2; i < len; i++){
        toConcat[i]=items[i-2].canActOn;
    }
    lz.embed.setCanvasAttribute('gDataDetectionCanActOn',toConcat.join(':'));
};

/* Onmouseup function for the arrow */
var _imgMouseup=function(){
    this.style.backgroundPosition=gDataDetection.actionDropDown.visible ? '-15px -15px' : '-15px 0';
};

/* Onmouseover function for the arrow */
var _imgMouseover=function(){
    var aDD=gDataDetection.actionDropDown;
    if(aDD) this.style.backgroundPosition=aDD.visible ? '-15px -15px' : '-15px 0';
};

/* Onmouseout function for the arrow */
var _imgMouseout=function(){
    var aDD=gDataDetection.actionDropDown;
    if(aDD) this.style.backgroundPosition=aDD.visible ? '0 -15px' : '0 0';
};
}//End gDataDetection

/** JMenu Class
    @param String name - The name of this view */
function JMenu(name){
//Class vars
JMenu.hiliteColor='#D5EFF5';
JMenu.disabledTextColor='#B9B9B9';
//Public vars
this.name=name;
this.items=[];
this.view=document.createElement('div');
this.hide();
this.width=165;
this.visible=false;
//Set default view attributes
var s=this.view.style;
s.width=this.width+'px';
s.fontFamily='Verdana,Arial,sans-serif';
s.fontSize='9px';
s.letterSpacing='.1em';
s.wordSpacing='-.15em';
s.lineHeight='1.75em';
s.backgroundColor='#FFF';
s.borderColor='#9D9D9D';
s.borderWidth='1px';
s.borderStyle='solid';
s.position='absolute';
s.zIndex=99998;//Must be greater than iframe z-index
//Append view to body
document.body.appendChild(this.view);

this.view.onmouseover=function(){
    var mt=gDataDetection.mousedOverElement.wt_mouseoutTimer;
    if(mt) top.clearTimeout(mt);
};

this.view.onmouseout=gDataDetection.mousedOut;
}//End JMenu

/** Hides the JMenu if it's visible. We cannot use display:hidden because it makes the clientHeight and clientWidth zero. */
JMenu.prototype.hide=function(){
    this.visible=false;
    this.view.style.left='-9999px';
    this.view.style.top='-9999px';
}

/** JMenuItem Class
    @param JMenu menu - JMenu to attach view to
    @param String text - Text to display
    @param callbackParams - Name/value pairs to pass to the callback function
    @param Function canActOnMethod - Method name to check for enabled */
function JMenuItem(menu,text,callbackParams,canActOnMethod){
//Public vars
this.view=document.createElement('div');
this.canActOn=canActOnMethod;
//Set default view attributes
this.view.style.padding='2px 2px 2px 13px';
this.view.style.cursor='pointer';
this.view.appendChild(document.createTextNode(text));
//Append view to menu
menu.view.appendChild(this.view);
menu.items.push(this);

this.view.onclick=function(){
    if(!this.wt_enabled) return;

    //Call data detection method in Webtop
    var elem=gDataDetection.mousedOverElement;
    var winId=gDataDetection.getWindowByElement(elem).frameElement.id;
    var smo=elem.wt_smo;
    var type=smo.type ? smo.type : '';
    var value=smo.value ? smo.value.replace(/'/g,"\\'") : '';
    value=value.replace(/\r/g,"");//remove \r under IE.EM-15768
    lz.embed.setCanvasAttribute('gDataDetection',[winId,callbackParams,type,value].join(':'));
    gDataDetection.handleMouseOut(elem);
    var theSwf=document.getElementById('lzapp');
    if(theSwf) theSwf.focus();
};

this._mouseOver=function(){this.style.backgroundColor=JMenu.hiliteColor;};
this._mouseOut=function(){this.style.backgroundColor='#ffffff';};
this.setText=function(text){this.view.firstChild.data=text;};

this.setEnabled=function(isE){
    var v=this.view;
    if(v.wt_enabled === isE) return;
    v.style.color=isE ? '#000' : JMenu.disabledTextColor;
    v.onmouseover=isE ? this._mouseOver : null;
    v.onmouseout=isE ? this._mouseOut : null;
    v.wt_enabled=isE;
};

this.setEnabled(true);
}//End JMenuItem

