if (!window.console) { 
    window.console = {
        log: function(obj){ },
        info: function(e){ 
            //alert("Info: " + e.toString()) 
        },
        error: function(e){ 
            //alert("Error:" + e.toString())
        },
        group: function(){},
        groupEnd: function(){},
        debug: function(d){ },
        warn: function(e){ 
            //alert("Warn:" + e.toString()) 
        }
    
    };
}

(function($) {
    /**
     * Create a new instance of the sticky ad plugin
     * 
     * @param {Object} options
     * @constructor
     * @example Invoke it wherever. What counts is that the selectors makes sense.
     * $(document).ready(function(){
     *     $('body').stickyad({
     *          stickyAdSelector: '#stickyAd'
     *     });
     * });
     */
    $.fn.stickyad = function(options) {
        
        /**
         * @projectDescription  A great sticky ad plugin
         * @author              Jonas G. Drange
         * @version             0.2
         * 
         * Will work if the structure is like this: 
         * 
         * *********************
         * <div id/class="totalWrapperSeletor">
         *      <div id/class="contentSelector"> CONTENT </div>
         *      <div id/class="outerRightSelector">
         *          <div id/class="stickyAdSelector"> STICKY AD </div>
         *      </div>
         * </div>
         * *********************
         * 
         * This plugin will set dynamic properties and change them
         * according to scroll and viewport size
         * 
         * The plugin assumes a couple of things
               * the contentSelector div is floated
               * the totalWrapperSelector is what outerRightSelector is positioned relative to
               *  
         */
        
        var settings = {
            stickyAdSelector: '#ads_outer_right > .ad:first',
            stickyAdWidth: 0,
            stickyAdLeftMargin: 0,
            stickyAdOffsetTop: 0,
            stickyClassWhenSticky: 'stickToTopOfScreen',
            stickyForceUnstickySelector: "#ikkesticky",
            outerRightSelector: '#ads_outer_right',
            totalWrapperSelector: '#stickyad_wrapper',
            totalWrapperWidth: 0,
            headerAdWrapperSelector: '.ads_header:first',
            headerAdSelector: 'embed, img, div',
            headerAdHeight: 0,
            headerAdWidth: 0,
            contentSelector: '#global',
            contentWidth: 0,
            viewPortWidth: $(window).width(),
            alwaysShowStickyAd: true, // try to show sticky ad as long as possible
            debug: false
        },
        stickyAd=false, // element that we stick to screen
        outerRight=false, // wrapper for element that we stick to screen
        totalWrapper=false, // the element that contains both
        headerAdWrapper=false, // wrapper with ads in top
        headerAd=false, // the header ad (either an object, image or div that represents the dimentions of the ad) 
        content=false; // content
        
        //provide the jquery object on which we invoked our plugin
        var $this = this;     

        // merge options with settings
        if ( options ) { $.extend( settings, options ); }
        
        // plugin private methods
        
        /**
         * check if something returned jquery and is not empty
         * @param {Object} the object to check
         * @param {String} jquery selector
         * @return {Boolean} true if jquery, false if not
         */
        function checkForJquery(obj, selector) {
            if( (obj.length == 0 ) || (obj.jquery == 'undefined') ) {
                // debug
                if(settings.debug) {
                    console.error(obj + " is not jquery. Selector: " + selector + ".");
                }
                return false;
            }
            return true;
        }
        
        /**
         * Sets the stickyAd variable if not set
         * 
         * @returns     {jQuery} stickyAd A jQuery object that represents what is to be "sticky"
         */
        function getStickyAd(){
            if(!stickyAd) stickyAd = $(settings.stickyAdSelector);
            checkForJquery(stickyAd, settings.stickyAdSelector);

            // debug
            if(settings.debug) {
                console.debug("getStickyAd", stickyAd);
            }
            return stickyAd;
        }
        /**
         * Sets the outerRight variable if not set
         * 
         * @returns     {jQuery} outerRight A jQuery object that represents the sticky stuff
         */
        function getOuterRight(){
            if(!outerRight) outerRight = $(settings.outerRightSelector);
            checkForJquery(outerRight, settings.outerRightSelector);

            // debug
            if(settings.debug) {
                console.debug("getOuterRight", outerRight);
                console.debug("getOuterRight type ", outerRight.jquery);
            }
            return outerRight;
        }
        /**
         * Sets the totalWrapper variable if not set
         * 
         * @returns     {jQuery} totalWrapper A jQuery object that represents everything
         */
        function getTotalWrapper(){
            if(!totalWrapper) totalWrapper = $(settings.totalWrapperSelector);
            checkForJquery(totalWrapper, settings.totalWrapperSelector);
            
            // debug
            if(settings.debug) {
                console.debug("getTotalWrapper", totalWrapper);
            }
            return totalWrapper;
        }
        /**
         * Sets the headerAdWrapper variable if not set
         * 
         * @returns     {jQuery} headerAdWrapper A jQuery object that represents header ads
         */
        function getHeaderAdWrapper(){
            if(!headerAdWrapper) headerAdWrapper = $(settings.headerAdWrapperSelector);
            checkForJquery(headerAdWrapper, settings.headerAdWrapperSelector);
            
            // debug
            if(settings.debug) {
                console.debug("getHeaderAdWrapper", headerAdWrapper);
            }
            return headerAdWrapper;
        }
        /**
         * Sets the headerAd variable if not set
         * 
         * @returns     {jQuery} headerAd A jQuery object that represents header ad
         */
        function getHeaderAd(){
            if(!headerAd) headerAd = $(settings.headerAdWrapperSelector).find(settings.headerAdSelector);
            if(headerAd.length > 1) headerAd = $(headerAd[0]); // at this time this means the largest of the two (the kloss is not used)
            checkForJquery(headerAd, settings.headerAdSelector);
            
            // debug
            if(settings.debug) {
                console.debug("getHeaderAd", headerAd);
            }
            return headerAd;
        }
        /**
         * Sets the content variable if not set
         * 
         * @returns     {jQuery} content A jQuery object that represents our main content
         */
        function getContent(){
            if(!content) content = $(settings.contentSelector);
            
            checkForJquery(content, settings.contentSelector);
            
            // debug
            if(settings.debug) {
                console.debug("getContent", content);
            }            
            return content;
        }
        
        /**
         * @returns     {Boolean} true if sticky ad should stick to the top of the screen, false if not defualts to true
         */
        function isStickyAdSticky(){
            var ad=getStickyAd(),
            sticky=true; // we default to stickyness

            // force disabling of sticky
            // it is possible for campaign to add <div id="stickyFlag"></div>
            if(ad.find(settings.stickyForceUnstickySelector).length > 0) {
                sticky=false;
            }
            if(settings.debug) { 
                console.debug("Sticky: ", sticky);
            }
            return sticky;
        }
        
        /**
         * This function takes care of the three scenarios defined in ST-40
            * SCENARIO #1: If head is 990 - 1010, "float" stickyad right of head
            * SCENARIO #2: If head is < 990, give it the traditional position (normally the same the edge of the content + margins), height as head
            * SCENARIO #3: If head is > 1010, give it the traditional position, but be careful to align it with head's edge
         * @returns {Object} {x, y}
         */
        function getPositionOfStickyAd() {
            var w = settings.headerAdWidth,
            ret = {
                x: 0,
                y: 0
            };
            if( (w >= 990) && (w <= 1010) ) {
                // Header ad is between 990 and 1010 pixels wide
                // SCENARIO #1 
                ret.x = settings.headerAdWidth;
                // lazy hax for ie7 
                if($.browser.msie && ( parseInt($.browser.version) == 7) ) { ret.x = settings.headerAdWidth - settings.contentWidth;}
                if($.browser.msie && ( parseInt($.browser.version) == 6) ) { ret.x = 0; }

                if(settings.debug) {
                    console.info("Header ad is between 990 and 1010 pixels wide");
                }
                ret.y = 0;
            }
            else if(w < 990) {
                // Header ad is less than 990 pixels wide
                // SCENARIO #2
                ret.x = settings.contentWidth  + settings.stickyAdLeftMargin;
                
                // lazy hax for ie7
                if($.browser.msie && ( parseInt($.browser.version) < 8) ) {
                    ret.x = settings.stickyAdLeftMargin;
                }
                ret.y = settings.headerAdHeight + settings.stickyAdOffsetTop;
                if(settings.debug) {
                    console.info("Header ad is less than 990 pixels wide");
                }
            }
            else {
                // Header ad is more than 1010 pixels wide
                // SCENARIO #3
                // the sticky ad's right edge should be aligned with header ad right edge
                // this could make it overlap the content
                ret.x = settings.headerAdWidth - settings.stickyAdWidth;
                
                // ie 6/7 fix
                if($.browser.msie && ( parseInt($.browser.version) == 6) ) { 
                    ret.x = settings.stickyAdWidth * -1;
                }                
                if($.browser.msie && ( parseInt($.browser.version) == 7) ) { 
                    ret.x = settings.headerAdWidth - settings.contentWidth - settings.stickyAdWidth;
                }                
                ret.y = settings.headerAdHeight  + settings.stickyAdOffsetTop;
                if(settings.debug) {
                    console.info("Header ad is more than 1010 pixels wide");
                }
            }
            return ret;
        }
        /**
         * Sets the sticky ad to fixed position (gives it a class)
         */        
        function checkUserScrollAndApplyStickyness(offset){
            // set some variables like how much weve scrolled and the sticky class. Also get the outer right wrapper
            var documentHasScrolled = $(document).scrollTop(),
            c = settings.stickyClassWhenSticky,
            container = getOuterRight();
            
            if(documentHasScrolled < offset) {
                container.removeClass(c);
            }
            else {
                container.addClass(c);
            }
        }
        /**
         * Binds the scroll event and initial stickyness (if we have scrolled before onload)
         * 
         * @param {Number} offset: when to activate the stickyness
         */
        function bindScrollEventAndSetInitialStickyNess(){
            
            
            // in ie, apply and remove the class, for unknown reasons, this fixes the init of the ad in ie6. 
            if($.browser.msie && ( parseInt($.browser.version) == 6) ) { getOuterRight().addClass(settings.stickyClassWhenSticky).removeClass(settings.stickyClassWhenSticky); }            
            
            // don't bind events to window if we dont have a sticky.
            if(!isStickyAdSticky()) return;

            // calculate sticky ad offset
            var offset = getPositionOfStickyAd().y;
            
            // bind scroll to window
            $(window).scroll(function(){
                checkUserScrollAndApplyStickyness(offset);
            });
            
            // fire it onload
            checkUserScrollAndApplyStickyness(offset);
        }
        
        /**
         * Function to always show the sticky ad as long as it has space to be shown
         */
        function alwaysShowStickyAd(){
            // set up some variables
            var stickyAdWidth = settings.stickyAdWidth,  // the sticky ad width
            wrapperWidth = getTotalWrapper().outerWidth(), // outer outer most container
            viewPortWidth = $(window).width();
            
            /*
             * CSS that should be used for this
            .stickRight { position: absolute !important; }
            .stickLeft { position: absolute !important; left: 7px; right: auto!important; }
            .stickNone { position: relative; right: auto !important; left: auto !important; } 
             */

            // we have room on the left, none on the right 
            // stick the total wrapper on the right side of screen
            if((viewPortWidth / 2) < ( (wrapperWidth / 2) + settings.stickyAdLeftMargin + stickyAdWidth ) ) {
                getTotalWrapper().css({
                    right: stickyAdWidth + settings.stickyAdLeftMargin
                });
                getTotalWrapper().attr("class", "stickRight");
            }
            // position the total wrapper on left.. we have reached the point where
            // the viewport cannot show everything
            if(viewPortWidth < ( wrapperWidth + settings.stickyAdLeftMargin + parseInt($("body").css("padding-left")) + stickyAdWidth ) ) {
                getTotalWrapper().attr("class", "stickLeft");
            }
            // we have room to show everything as is
            if((viewPortWidth / 2) > ( (wrapperWidth / 2) + settings.stickyAdLeftMargin + stickyAdWidth ) ) {
               getTotalWrapper().attr("class", "stickNone");
            }
        }
        
        function bindResizeEventAndInitialPositioningOfWrapper(){
            
            // check if we want this
            if(!settings.alwaysShowStickyAd) return;
            
            // bind the magic function to the resize event
            $(window).resize(function(){
                alwaysShowStickyAd();
            });
            
            // fire it onload (as this is fired onload)
            alwaysShowStickyAd();
        }
        /*
         * sets the settings.stickyAdWidth variable when it can't be detected properly
         */
        function searchForStickyAdWidth() {
            var i=0,
            $s=getStickyAd();
            while( (settings.stickyAdWidth == 0 ) && (i < 10) ) {
                settings.stickyAdWidth = $s.outerWidth();
                $s=$s.children(":not(script):first");
                i=i+1;
            }
            if(isNaN(settings.stickyAdWidth) || (settings.stickyAdWidth == null)) {
                if (settings.debug) {
                    console.info("Did not find stickyadwidth. Will be guessing it is 180px wide.");
                }
                settings.stickyAdWidth = 180;
            }
            else {
                if (settings.debug) {
                    console.info("Found new stickyAdWidth: " + settings.stickyAdWidth + "px, in " +i+ " attempts.");
                }
            }
        }
        
        // plugin public methods
        
        // init
        return this.each(function(){
            if(settings.debug) { 
                console.group("Initial setup:"); 
            }
            
            // initialize the most used jquery objects
            var $w = getTotalWrapper(), // wrapping everything
            $o = getOuterRight(), // "ads_outer_right" most of the time
            $s = getStickyAd(), // the sticky ad
            $h = getHeaderAd(), // find the header ad we can use to get widht/height
            $c = getContent(); // content 
            if(settings.debug) { 
                console.groupEnd(); 
            }

            // calculate settings that are not set
            if(settings.totalWrapperWidth == 0) settings.totalWrapperWidth = $w.outerWidth(); 
            if(settings.headerAdWidth == 0) settings.headerAdWidth = $h.outerWidth(); 
            if(settings.headerAdHeight == 0) settings.headerAdHeight = $h.outerHeight();
            if(settings.contentWidth == 0) settings.contentWidth = $c.outerWidth(); 
            if(settings.stickyAdWidth == 0) settings.stickyAdWidth = $s.outerWidth(); 
            
            // we need to make sure headerAdWidth is correct 
            // try to find the innermost (element most likely to have the width were looking for) ad element 
            var newHeaderAd = getHeaderAd().find("img:first, object:first, iframe:first");
            if(newHeaderAd.length > 0) {
                if(settings.debug) {
                    console.log("found new headerAd");
                }
                settings.headerAdWidth=$(newHeaderAd[0]).outerWidth();
            }
            if(settings.debug) {
                console.log("Setting new headerAdWidth to " +settings.headerAdWidth);
            }
                        
            
            // in ie6 (maybe higher), a flash object take extra time loading
            // go into the sticky ad and explicitly find something that has width
            if(settings.stickyAdWidth==0) {
                searchForStickyAdWidth();
            }
            
            // store gap between header ads and document
            gap = getHeaderAdWrapper().offset().top;
            
            // find what should be sticky's position
            var stickyAdPosition = getPositionOfStickyAd(); 
            
            // position sticky
            getStickyAd().css({
                left: stickyAdPosition.x,
                top: stickyAdPosition.y
            });
            
            // initialize the scroll event and the initial stickyness if we've scrolled
            bindScrollEventAndSetInitialStickyNess();
            
            // initialize the resize event and the initial "always show stickyad"
            bindResizeEventAndInitialPositioningOfWrapper();
            
            if(settings.debug) {
                 console.debug(this, settings, stickyAdPosition, isStickyAdSticky(),gap);
             }
        });

    }
})(jQuery);
