//Needs prototype
/*
 *Created to avoid dom searching, used in UtilityService.prototype.getFirstMatching
*/
var CacheHandler=Class.create({

    initialize:function()
    {
        this.tELEMENT_CACHE=new Hash();
        this.cleaningServiceStarted=false;
    },

    isCleaningServiceStarted:function()
    {return this.cleaningServiceStarted;},

    getElementCache:function()
    {return this.tELEMENT_CACHE;},

    performCleaningService:function()
    {
        var keys=this.tELEMENT_CACHE.keys();
        for(var i=0;i<keys.size();i++)
        {
            var cachedElement=this.tELEMENT_CACHE.get(keys[i]);
            if(
                !(cachedElement) ||
                (cachedElement && !$(cachedElement.identify()))//if has been already removed from the dom
              )
               this.tELEMENT_CACHE.unset(keys[i]);//free the pair
        }
    },
    startCleaningService:function()
    {
        this.cleaningServiceStarted=true;
        var p=new PeriodicalExecuter
        (
           this.performCleaningService.bind(this),
           300
        );
    }
});

var UtilityService=Class.create(
{
    _cacheHandler:new CacheHandler(),
    initialize:function()
    {},

    getElementFromResponse:function(response,attr,attrValue)
    {// [attr=attrValue works as a selector]
        var tempE=new Element("div");
        tempE.update(response.responseText.stripScripts());
        var eMatches=tempE.select("["+attr+"='"+attrValue+"']");
        if(eMatches.size()>0)
            return eMatches.first();
        else
            return null;
    },

    //Interface effects
    fadeIn:function(element,duration)
    {//time in seconds
        if(duration<=0)
            return;

        var fPS=10;//frequency/updates per second
        var frequency=1/fPS;
        var nrOfExecs=duration*fPS*1.0;
        var increase=1/nrOfExecs;

        element.setOpacity(0.0);
        element.show();

        var periodicalExecuter=new PeriodicalExecuter(
           function()
           {
               var stopPE=UtilityService.prototype.execFadeIn(element,increase);
               if(stopPE)
               {
                   periodicalExecuter.stop();
               }
           }.bind(this,periodicalExecuter,element,increase)
           ,frequency);
    },

    execFadeIn:function(element,increase)
    {
        var oldOpacity=element.getStyle("opacity");
        oldOpacity=oldOpacity*1.0;
        var newOpacity=oldOpacity+increase;
        var stopPE=false;

        //to control overflow
        if(newOpacity>1.0)
        {
            newOpacity=1.0;
            stopPE=true;
        }

        element.setOpacity(newOpacity);
        return stopPE;
    },

    fadeOut:function(element,duration,removeAfterFade)
    {//time in seconds
        if(duration<=0)
        {
            element.remove();
            return;
        }
        var fPS=10;//frequency/updates per second
        var frequency=1/fPS;
        var nrOfExecs=duration*fPS*1.0;
        var diff=-1/nrOfExecs;

        element.setOpacity(1.0);
        var periodicalExecuter=new PeriodicalExecuter(
           function()
           {
               var stopPE=UtilityService.prototype.execFadeOut(element,diff);
               if(stopPE)
               {
                   element.hide();
                   periodicalExecuter.stop();
                   if(removeAfterFade)
                   {
                       element.remove();
                   }
               }

           }.bind(this,periodicalExecuter,element,diff)
           ,frequency);
    },

    execFadeOut:function(element,diff)
    {
        var oldOpacity=element.getStyle("opacity");
        oldOpacity=oldOpacity*1.0;
        var newOpacity=oldOpacity+diff;
        var stopPE=false;

        //to control overflow
        if(newOpacity<0.0)
        {
            newOpacity=0.0;
            stopPE=true;
        }

        element.setOpacity(newOpacity);
        return stopPE;
    },

    getNodeValue: function(tree, el){
      return tree.getElementsByTagName(el)[0].firstChild.nodeValue;
    },

    getFirstMatching:function(element,attr,attrValue,noUseCache)
    {
        //Profiler will show how much is saved in IE =D
        var elementRes=null;
        if(noUseCache)
          elementRes=UtilityService.prototype.getFirstMatchingNoCaching(element,attr,attrValue);
        else
          elementRes=UtilityService.prototype.getFirstMatchingWithCaching(element,attr,attrValue);

        return elementRes;
    },

    getFirstMatchingWithCaching:function(element,attr,attrValue)
    {
        element=$(element);
//        if(element instanceof HTMLDocument)
//           element=$(element.body);
        if(element == document)
           element=$(element.body);

       var hasCacheSupport=(UtilityService.prototype._cacheHandler)?true:false;
       var key=element.identify()+'.'+attr+'.'+attrValue;
       if(hasCacheSupport)
       {
           if(!UtilityService.prototype._cacheHandler.isCleaningServiceStarted())
               UtilityService.prototype._cacheHandler.startCleaningService();
           //console.debug('HAS CACHE SUPPORT');
            var elementFromCache=UtilityService.prototype._cacheHandler.getElementCache().get(key);
            if(
                elementFromCache
                && elementFromCache.descendantOf(element)//expensive?
                //checks if the element still exists in the dom because
                //it might have been replaced by other element due to i.e. an Ajax call
            )
                  return elementFromCache;
       }

       var eMatches=element.select("["+attr+"='"+attrValue+"']");
        if(eMatches.size()>0)
        {
            var foundElement=eMatches.first();
            if(hasCacheSupport)
            {
                //foundElement.identify();//in order to be searched later by the cache cleaner
                UtilityService.prototype._cacheHandler.getElementCache().set(key,foundElement);
            }

            return foundElement;
        }
        else
            return null;

    },

    getFirstMatchingNoCaching:function(element,attr,attrValue)
    {
        element=$(element);
//        if(element instanceof HTMLDocument)
//           element=$(element.body);
        if(element == document)
           element=$(element.body);

        var eMatches=element.select("["+attr+"='"+attrValue+"']");
        if(eMatches.size()>0)
            return eMatches.first()
        else
            return null;
    },

    writeToLog:function(message)
    {
        try{console.debug(message);}catch(exception){}
    },

    getCaption:function(logicalName,defaultCaption)
    {
        var caption="["+logicalName+"]";
        var captionFound=false;
        //Uses a global variable captionTable that will hold captions loaded through xsl
        if(!Object.isUndefined(captionHash) && captionHash!=null && captionHash instanceof Hash)
        {
            var captionInHash=captionHash.get(logicalName);
            if(captionInHash!=null)
            {
                caption=captionInHash;
                captionFound=true;
            }
        }
        if(!captionFound && !Object.isUndefined(defaultCaption))
            return defaultCaption;

        return caption;
    },

    //Resizes the window so that the document matches the new dimensions
    resizeWindowEnhanced:function(newInnerWidth,newInnerHeight,considerScrollbarsOffset)
    {
        try{
        var decorationOffsetWidth=window.outerWidth-window.innerWidth;
        var decorationOffsetHeight=window.outerHeight-window.innerHeight;

        //[PAG-178] IE doesn't support window.outerWidth so we'll guess the decoration offsets
        decorationOffsetWidth=decorationOffsetWidth?decorationOffsetWidth:40;
        decorationOffsetHeight=decorationOffsetHeight?decorationOffsetHeight:200;

        var scrollbarOffset=(considerScrollbarsOffset)?20:0;

        window.resizeTo(scrollbarOffset+newInnerWidth+decorationOffsetWidth,scrollbarOffset+newInnerHeight+decorationOffsetHeight);
        }catch(ex){}
    },

    isIE:function()
   {
       var isIE=Prototype.Browser.IE;
       if(isIE)
       {return true}
       return false;
   }
}

);
