//
// WK: wie waere es mit "Weinhalle" als Namensraum ? NUREG muss da IMHO nicht unbedingt auftauchen...

// Den globalen Namensraum nicht verseuchen
if (!window.nureg) {
    window.nureg = {};
    window.nureg.weinhalle = {};
}

if (!window.console) { // primitive logging for IE
    window.console = {};
    window.console.log = function(s) {
        // enable if a log target element is there and logging wanted
        //$('log').innerHTML = s + '<br>' + $('log').innerHTML;
    };
}

//
// callback function called from .flv player.
//
function video_at_end(name) {
    //console.log('END name = ' + name);
}

function video_state_change(state, name) {
    //console.log('player-state: ' + state + ', name: ' + name);
    if (name === 'home_aktuell_player') {
        var player = $(name);
        if (state === 'playing') {
            player.previous('.close').removeClassName('hide');

            var div = player ? player.up('div') : null;
            if (div && div.hasClassName('home_intro_video')) {
                // initial play.
                // console.log('setting initial state');
                div.className = 'home_small_video';
            }
        }
        //else if (state==='rewinding') {
        //    player.previous('.close').addClassName('hide');
        //}
    }
}

function video_hd_switch(hd, name) {
    var video = Element.down($('video_overlay'), 'object') || Element.down(document, 'object');
    // console.log('HD video = ' + video + ', name = ' + name);
    if (video) {
        var container = video.up('div');
        var homebox = video.up('.homebox');
        var overlay = video.up('#video_overlay');
        if (homebox) {
            homebox.setStyle({overflow: 'visible'});
        }
        if (overlay) {
            // console.log('overlay');
            if (overlay.className.match(/small/)) {
                overlay.className = 'hd_video';
            } else {
                overlay.className = 'small_video';
            }
        } else if (container) {
            // console.log('container');
            if (container.className.match(/small|intro/)) {
                container.className = 'home_hd_video';
            } else {
                container.className = 'home_small_video';
            }
        }
    }
}

//
// cart magic -- a button with a popup
// Quantity --> qty parameter (defaults to 1)
//
nureg.weinhalle.AddCartButton = Class.create({
    initialize: function(el) {
        this._button = el;
        var span = new Element('span');
        span.className = 'add_to_cart_positioner';
        el.insert({after: span});
        this._positioner = span;

        this._outer_div = el.up('div.add_basket');

        el.observe('click', this.onClick.bindAsEventListener(this));
    },

    // add-to-cart link clicked -- show popup to ask for quantity.
    onClick: function(e) {
        e.stop(); // prevent href="" from firing

        if (this._outer_div) {
            this._outer_div.setStyle({zIndex: 2}); // IE wants this...
        }
        var url = this._button.readAttribute('href');
        if (url.match(/javascript:setLocation/)) {
            url = url.replace(/^javascript:setLocation\('(.*)'\).*$/, '\\$1');
        }
        this._url = url;

        // get package size
        // 1. get product id
        var package_text=null;
        var productId=null;
        var url_paths=url.split('/');
        productId=url_paths[ url_paths.length-2 ];

        // 2. find product block containing .package
        var product_block=null;
        if (productId) {
            var possible_product_block_ids = [
                                              'product-'+productId+'-detail',
                                              'product-'+productId+'-home',
                                              'product-'+productId+'-bestseller',
                                              'product-'+productId+'-list',
                                              'product-'+productId+'-list-tall',
                                              'product-'+productId+'-list-wishlist'
            ];
            for (var i=0; i<possible_product_block_ids.length; i++) {
                product_block = $(possible_product_block_ids[i]);
                if (product_block) {
                    break;
                }
            }

            if (product_block) {
                //3. find .package node
                var package_nodes=product_block.select('.package');

                //4. set package text
                if (package_nodes[0]) {
                    package_text=package_nodes[0].innerHTML;
                }
                else {
                    var capacity_nodes=product_block.select('.capacity');
                    if (capacity_nodes[0]) {
                        package_text=capacity_nodes[0].innerHTML;
                    }
                }
            }
        }

        // 3. check if our link has some 'data-xxx' attributes.
        // create indicator_(ok|out|wait) span's...
        var qty = Math.round(this._button.readAttribute('data-qty'));
        var backorders = this._button.readAttribute('data-backorders');

        var indicators = '';

        if (backorders && qty) {
            // • x verfügbar / • sonst 3 wochen
            indicators = '<span class="indicator_ok">•</span> ' + qty + ' verfügbar<br/>' +
                         '<span class="indicator_wait">•</span> mehr in 3 Wochen';
        } else if (backorders) {
            // • lieferbar in 3 wochen, jetzt bestellbar
            indicators = '<span class="indicator_wait">•</span> lieferbar in 3 Wochen<br/>&nbsp;&nbsp;jetzt bestellbar';
        } else if (qty) {
            // • x verfügbar / • dann ausverkauft
            indicators = '<span class="indicator_ok">•</span> ' + qty + ' verfügbar<br/>' +
                         '<span class="indicator_out">•</span> dann ausverkauft';
        } else {
            // • auf lager
            indicators = '<span class="indicator_ok">•</span> verfügbar';
        }

        // build a simple pop up form -- ID is needed by J2t_Ajaxcheckout -- do not change!!!
        // there are nicer ways to build HTML but this is readable...
        this._positioner.innerHTML =
          '<div class="add_to_cart kuform" action="' + url + '">' +
          '  <div><b>Wieviele dürfen es denn sein?</b></div>' +
          '  <div class="stock_info">' + indicators + '</div>' +
          '  <div><input type="text" name="qty" value="1" size="4" maxlength="2" /> Flaschen/Stück/Menge</div>' +
          '  <div>' + (package_text ? 'Gebindegröße: ' + package_text : '') + '</div>' +
          '  <input type="reset"  class="secondary-button" name="Abbruch" value="Abbruch" />' +
          '  <input type="submit" class="primary-button"   name="In den Warenkorb" value="In den Warenkorb" />' +
          '</div>';

        this._submit_button = this._positioner.down('input[type="submit"]');
        this._reset_button  = this._positioner.down('input[type="reset"]');

        this._submit_button.observe('click', this.onSubmit.bindAsEventListener(this));
        this._reset_button .observe('click', this.onCancel.bindAsEventListener(this));
    },

    // quantity form submission requested
    onSubmit: function(e) {
        e.stop();
        var qty = this._positioner.down('input[name="qty"]').value;
        // console.log('add to cart, qty = ' + qty);
        sendcart(this._url + '?qty=' + qty, 'url'); // requires J2t_Ajaxcheckout... -- must be installed and set up!!!
        // sendcart(this._url, 'form'); // requires J2t_Ajaxcheckout... -- must be installed and set up!!!

        this.cleanup();
    },

    // quantity form cancel requested
    onCancel: function(e) {
        e.stop();

        this.cleanup();
    },

    // clean up the popup form
    cleanup: function() {
        this._submit_button.stopObserving('click');
        this._reset_button .stopObserving('click');
        this._submit_button = null;
        this._reset_button = null;
        this._positioner.innerHTML = '';
        if (this._outer_div) {
            try {
                this._outer_div.setStyle({zIndex: 'auto'}); // IE wants this...
            }
            catch (e) {
                this._outer_div.setStyle({zIndex: 1}); // ...but IE6 and 7 fails with value "auto" (type-conflict; may be a prototype problem.)
            }
        }
    }
});

nureg.weinhalle.SoldOutButton = Class.create({
    initialize: function(el) {
        this._button = el;
        var span = new Element('span');
        span.className = 'sold_out_positioner';
        el.insert({after: span});
        this._positioner = span;

        this._outer_div = el.up('div.add_basket');
        this._want_close = false;
        this._visible = false;

        el.observe('click', this.onClick.bindAsEventListener(this));
    },

    leaveCheck: function(e) {
        var t = e.target;

        if (t === this._positioner || Element.up(t, 'span.sold_out_positioner')) { // inside popup
            this._want_close = false;
            this._ticks = 0;
            // console.log('DO NOT CLOSE');
        } else {
            this._want_close = true;
            // console.log('want close');
        }
    },

    onTick: function(e) {
        //console.log('tick');
        if (!this._visible) return;
        if (!this._want_close) return;

        if (++this._ticks < 5) return;

        this.cleanup();
    },

    // add-to-cart link clicked -- show popup with "sold out" info message
    onClick: function(e) {
        e.stop(); // prevent href="" from firing

        if (this._outer_div) {
            this._outer_div.setStyle({zIndex: 2}); // IE wants this...
        }

        // build a simple pop up
        // there are nicer ways to build HTML but this is readable...
        this._positioner.innerHTML =
          '<div class="sold_out kuform" action="#">' +
          '  <div><b>Leider ausverkauft.</b></div>' +
          '  <div>&nbsp;</div>' +
          '  <input type="reset" class="primary-button" name="OK" value="OK" />' +
          // '  <input type="submit" class="primary-button"   name="In den Warenkorb" value="In den Warenkorb" />' +
          '</div>';

        // this._submit_button = this._positioner.down('input[type="submit"]');
        this._reset_button = this._positioner.down('input[type="reset"]');

        // this._submit_button.observe('click', this.onSubmit.bindAsEventListener(this));
        this._reset_button.observe('click', this.onCancel.bindAsEventListener(this));

        this._listener = this.leaveCheck.bindAsEventListener(this);
        document.observe('mousemove', this._listener);

        this._timer = new PeriodicalExecuter(this.onTick.bind(this),1);
        this._ticks = 0;

        this._want_close = false;
        this._visible = true;
    },

    // quantity form cancel requested
    onCancel: function(e) {
        e.stop();

        this.cleanup();
    },

    // clean up the popup form
    cleanup: function() {
        // stop timer
        this._timer.stop();

        // this._submit_button.stopObserving('click');
        this._reset_button .stopObserving('click');
        // this._submit_button = null;
        this._reset_button = null;
        this._positioner.innerHTML = '';
        if (this._outer_div) {
            try {
                this._outer_div.setStyle({zIndex: 'auto'}); // IE wants this...
            }
            catch (e) {
                this._outer_div.setStyle({zIndex: 1}); // ...but IE6 and 7 fails with value "auto" (type-conflict; may be a prototype problem.)
            }
        }

        this._visible = false;
    }
});

//
// general Overlay stuff
//
nureg.weinhalle.Overlay = Class.create({
    initialize: function(overlay, options) {
        options = options || {};
        $w('beforeOpenHook afterOpenHook beforeCloseHook afterCloseHook')
        .findAll(function(hook) { return Object.isFunction(options[hook]); })
        .each(function(hook) { this['_' + hook] = options[hook]; }, this);

        this._overlay = $(overlay || 'overlay');
        this._curtain = $('curtain');
        this._overlay.className='';
    },

    open: function(makeSkeleton) {
        if (this._beforeOpenHook) {
            this._beforeOpenHook();
        }

        $$('body')[0].addClassName('overlayOpen');

        document.observe('keydown', this.onOverlayKeypress.bindAsEventListener(this));

        this._curtain.show(); // TODO: more logic here -- we have overlay on top of an overlay (!)
        this._overlay.observe('click', this.onOverlayClick.bindAsEventListener(this));
        this._overlay.className='';
        this._overlay.show();
        this._overlay.innerHTML = '';
        this._closeButton = undefined;
        if (makeSkeleton) {
            var positioner  = new Element('div');
            positioner.className='positioner';
            var content     = new Element('div');
            content.className='content';
            var closeButton = new Element('button', { value: 'Schließen', title: 'Schließen' } ).insert('Schließen');
            closeButton.className='close';
            this._closeButton = closeButton;

            this._overlay.insert(
                positioner.insert(
                    content
                ).insert(closeButton)
            );
        }

        this._overlay.focus();

        if (this._afterOpenHook) {
            this._afterOpenHook();
        }
    },

    onOverlayClick: function(e) {
        // check if click occured within close button
        var t = $(e.target);
        var closeButton = this._closeButton || this._overlay.down('.close');
        if (t === closeButton) { // t.hasClassName('close')) {
            e.stop();
            this.closeOverlay();
        }
    },

    onOverlayKeypress: function(e) {
        if (e.keyCode===27) { //Escape
            e.stop();
            this.closeOverlay();
        }
    },

    closeOverlay: function() {
        if (this._beforeCloseHook) {
            this._beforeCloseHook();
        }

        this._curtain.hide();
        this._overlay.hide();
        this._overlay.innerHTML = '';
        this._overlay.stopObserving('click');

        $$('body')[0].removeClassName('overlayOpen');

        document.stopObserving('keydown');

        if (this._afterCloseHook) {
            this._afterCloseHook();
        }
    }
});

//
// intercept links to product detail
//
nureg.weinhalle.ProductDetailLink = Class.create({
    initialize: function(el) {
        this._url = el.readAttribute('href');
        this._id = el.readAttribute('data');
        this._hash = this._url.replace(/^.*\//, '').replace(/\.\w+$/, '');
        this._overlay = $('overlay');
        el.observe('click', this.onClick.bindAsEventListener(this));
        this._overlayHandler = new nureg.weinhalle.Overlay();
    },

    onClick: function(e) {
        this._overlayHandler.open();
        // var url = '/ajax/product/view/' + this._hash + '.html';
        var url = '/index.php/ajax/product/view/' + this._id;
        // window.location.hash = this._hash;

        $('curtain').addClassName('bottle');

        e.stop();
        new Ajax.Updater(this._overlay,
                         url,
                         {
                             onComplete: this.loadingDone.bind(this),
                             evalScripts: true
                         });
    },

    closeOverlay: function() {
        // window.location.hash = '';
    },

    // callback from Ajax call indicating we are done
    loadingDone: function() {
        $('curtain').removeClassName('bottle');

        this._overlay.select('a._addcart').each(function(x) {
            new nureg.weinhalle.AddCartButton(x);
        });
        this._overlay.select('a._soldout').each(function(x) {
            new nureg.weinhalle.SoldOutButton(x);
        });
        this._overlay.select('a._video').each(function(x) {
            new nureg.weinhalle.VideoLink(x);
        });
        this._overlay.select('span[class*="_replace_"]').each(function(x) {
            new nureg.weinhalle.GlossaryLink(x);
        });
    }
});


//
// Filter Navigation (Prototype Version...)
//
nureg.weinhalle.FilterNav = Class.create({
    config: {
        MAX_FILTER_NAV_POINTS: 5
    },

    initialize: function(el) {
        this._element = el;
        this._box = $(el.parentNode);
        this._headline = $(el.parentNode).select('.boxHeadline')[0].firstChild.data;
        this._to_hide = [];
        this._visible = true;
        el.select('li')
          .each(function(x,i) {
                    var threshold=this.config.MAX_FILTER_NAV_POINTS;
                    if(this._box.hasClassName('showOnlyHeadline')) {
                        threshold = 0;
                    }
                    else if(this._headline === 'Jahrgang') {
                        threshold = 3;
                    }

                    if (i >= threshold) {
                        this._to_hide.push(x);
                    }
                }, this);
        if (this._to_hide.length > 0) {
            // add a more button
            this._button = new Element('button', {type: 'button', value: '+', title: 'alle anzeigen' }).insert('+');
            this._button.className='filterNavButton';
            el.insert({bottom: this._button});
            this._button.observe('click', this.onClick.bindAsEventListener(this));

            this.showHide(false);
        }
    },

    // button clicked
    onClick: function(e) {
        this.showHide(!this._visible);
    },

    // show-hide toggle
    showHide: function(status) {
        this._to_hide.invoke(status ? 'show' : 'hide');
        if(status) {
            this._element.addClassName('shown');
            this._element.removeClassName('hidden');
        }
        else {
            this._element.removeClassName('shown');
            this._element.addClassName('hidden');
        }
        this._button.innerHTML = status ? '–' : '+';
        this._button.writeAttribute('title', status ? 'weniger anzeigen' : 'alle anzeigen');
        this._visible = status ? true : false;
    }
});

//
// Toggles the details section in the advanced search form
//
nureg.weinhalle.AdvancedSearchFormToggler = Class.create({
    initialize: function(el) {
        this._fieldset = el;
        el.select('legend').each(function(x) {
            x.addClassName('toggleButton');
            x.parentNode.select('ul').each(function(x) {
                x.addClassName('hide');
            });

            x.observe('click', this.onClick.bindAsEventListener(this));
        }, this);
    },

    onClick: function(e) {
        Event.element(e).parentNode.select('ul').each(function(x) {
            if (x.hasClassName('hide')) {
                x.removeClassName('hide');
            }
            else {
                x.addClassName('hide');
            }
        });
    }
});


//
// Handling a single video link with class '_video'
//
nureg.weinhalle.VideoLink = Class.create({
    initialize: function(el) {
        this._link = el;

        // let a click open a video overlay window
        this._overlay = $('video_overlay');
        this._overlayHandler = new nureg.weinhalle.Overlay(
            'video_overlay',
            {
                afterOpenHook: this.onOverlayOpen.bind(this),
                beforeOpenHook: this.onOverlayClose.bind(this)
            });
        el.observe('click',this.onClick.bindAsEventListener(this));

        // see if we have a preview image -- wrap something around...
        this._preview_image = Element.down(el, 'img');
        if (this._preview_image) {
            // we have to fire the onPreviewImageLoad after the images was downloaded (onload). Unfortunately it doesn't work, if the image was cached, so we detect, if it has a height and if yes call the function manually.
            //var w = this._preview_image.readAttribute('width') || this._preview_image.getWidth();
            var h = this._preview_image.height;
            if (h>10) {
                // console.log("image was from cache: h="+h);
                this.onPreviewImageLoad.bind(this).delay(0.5); // give firefox some time to settle.
            }
            else {
                // console.log("using load handler: h="+h);
                this._preview_image.observe('load', this.onPreviewImageLoad.bindAsEventListener(this));
            }
        }
    },

    onPreviewImageLoad: function(e) {
        var el = this._link;
        this._preview_image.addClassName('video_preview');
        Element.addClassName(el,'video_preview_link');
        var span = this._preview_image.wrap('span', {style: 'position: relative'});
        var size = 60; // width && height of play_indicator image
        var l = 10;
        var b = 10;
        var wrapper = this._preview_image.up();
        //console.log(this._preview_image.getHeight());
        //var w = this._preview_image.readAttribute('width') || this._preview_image.getWidth();
        var h = this._preview_image.readAttribute('height')  || this._preview_image.getHeight();
        //console.log('img ' + this._preview_image.readAttribute('src') + ': ' + w + 'x' + h);
        //if (w && h) {
        //    l = Math.round((w - size) / 2);
        //    b = Math.round((h - size) / 2);
        //}

        if (h) {
            b = Math.round((h - size) / 2);
            if (b < 0) {
                // last chance to correct a bad position -- should never happen but we never know...
                b = 0;
            }
        }
        span.insert(new Element('img',
                               {
                                style: 'position: absolute; bottom: ' + b + 'px', //left: ' + l + 'px; bottom: ' + b + 'px;'
                                width: size, height: size,
                                src: '/skin/frontend/default/weinhalle/images/play_normal2.png',
                               'class': 'play_indicator'}));
    },

    // link clicked
    onClick: function(e) {
        this._overlayHandler.open(true);
        var video_url  = (this._link.readAttribute('href') || '').replace(/^.*\#/, ''); // chop off anything in front of # -- in case we change the uri scheme.
        var player_url = '/skin/frontend/default/weinhalle/swf/videoplayer.swf?12';

        // we need to insert TEXT into the container's .innerHTML property to beat IE...
        // this makes this code ugly but at least it works, thanks billy boy
        var o = '<object ' +
                    'type="application/x-shockwave-flash" ' +
                    'name="overlay_video" ' +
                    'id="overlay_video" ' +
                    'data="' + player_url + '" ' +
                    'class="video">' +
                        '<param name="movie" value="' + player_url + '">' +
                        '<param name="quality" value="high">' +
                        '<param name="bgcolor" value="#FFFFFF">' +
                        '<param name="flashvars" value="flv=' + video_url + '&amp;hd=1&amp;controlbar=always&amp;autoplay=1">' +
                '</object>';

        this._overlay.down('.content').innerHTML = o;
        e.stop();
    },

    onOverlayOpen: function() {
        // this._overlay.addClassName('video_container');
    },

    onOverlayClose: function() {
        // this._overlay.removeClassName('video_container');
    }
});

//
// Opens a layer with the product description on list pages
//
nureg.weinhalle.DescriptionLink = Class.create({
    initialize: function(el) {
        //this.link = el;
        el.observe('click',this.onClick.bindAsEventListener(this));
    },

    onClick: function(e) {
        var clickedLink=Event.element(e);
        //strip "#" from link
        var descriptionElementId=clickedLink.readAttribute('href').substr(1);

        var descriptionObj=$(descriptionElementId);
        if (descriptionObj.hasClassName('hide')) {
            descriptionObj.hide();
            descriptionObj.removeClassName('hide');
            $(descriptionObj.parentNode).observe('keydown',this.onKeyPress.bindAsEventListener(this) );

            var closeButton=new Element("button", { 'value' : 'Schließen', 'title' : 'Schließen' } ).insert('Schließen');
            closeButton.className='descriptionClose';
            closeButton.observe('click',this.closeDescription.bindAsEventListener(this));
            $(descriptionObj.parentNode).insert(closeButton);
            if(descriptionObj.focus) {
                try {
                    descriptionObj.focus();
                }
                catch(e) {
                    //fuck off, IE
                }
            }

            Effect.SlideDown(descriptionElementId);
        }
        else {
            this.closeDescription(e);
        }

        try {
            e.stop();
        }
        catch(e) {
            //fuck off, IE
        }
    },

    onKeyPress: function(e) {
        if (e.keyCode===27) { //Escape
            e.stop();
            this.closeDescription(e);
        }
    },

    closeDescription: function(e) {
        //Da wir mehrere Möglichkeiten haben, von wo das Event aus gefeuert werden kann, müssen wir erst den Container finden und suchen uns von dort aus die zu manipulierenden Elemente
        var containerElement=$(Event.element(e).parentNode);
        var i=0;
        var containerFound=false;
        while (i<20) { //Endlosschleife verhindern.
            if (containerElement.nodeName.toLowerCase()==='li' && $(containerElement).hasClassName('item')) {
                containerFound=true;
                break;
            }
            containerElement=containerElement.parentNode;
            i++;
        }

        if (containerFound) {
            //So, Container gefunden. Nun closeButton wieder rausschmeißen und alles andere rückgängig machen.
            var closeButton=containerElement.select('.descriptionClose')[0];
            var descriptionObj=containerElement.select('.description')[0];
            if (descriptionObj && descriptionObj.hasClassName('hide') === false) {
                descriptionObj.addClassName('hide');
                descriptionObj.parentNode.stopObserving('keydown');
                closeButton.remove();
            }
        }
    }
});

//
// a simple pageslide info display
//   follows a link at href="" of the given element
//   slides the entire page to the left
//   loads the requested page into a new container right
//
//   TODO: think if hard coded '300px' width is clever!?
//
nureg.weinhalle.PageSlideLink = Class.create({
    initialize: function(el) {
        this._element = el;
        this._url = el.readAttribute('href');
        this._wrapper = Element.down(document, 'div.wrapper');
        this._moved = false;

        this._div = Element.down(document,'div.pageslide_container');
        if (!this._div) {
            var div = new Element('div');
            div.className = 'pageslide_container';
            div.setStyle({right: '-300px'});
            this._wrapper.insert({before: div});
            this._div = div;
        }

        el.observe('click', this.onClick.bindAsEventListener(this));
    },

    onClick: function(e) {
        e.stop();
        if (this._moved) return;

        new Effect.Move(this._wrapper, { x: -300, y: -0, mode: 'relative', duration: 0.5 });
        new Effect.Morph(this._div, {style: {right: '0px'}, duration: 0.5 });
        document.observe('click', this.onDocumentClick.bindAsEventListener(this));

        // TODO: add Ajax loader for div...
        this._div.innerHTML = 'just my 2 ct';

        this._moved = true;
    },

    onDocumentClick: function(e) {
        e.stop();
        if (!this._moved) return;

        this._div.innerHTML = '';
        new Effect.Move(this._wrapper, { x: +300, y: -0, mode: 'relative', duration: 0.5 });
        new Effect.Morph(this._div, {style: {right: '-300px'}, duration: 0.5 });
        document.stopObserving('click');

        this._moved = false;
    }
});

//
// hoverable images :: scale to double size upon rollover
//   used for homepage and grid display
//
nureg.weinhalle.HoverableImage = Class.create({
    initialize: function(img) {
        var span = img.wrap('span', {style: 'position:relative'});
        var img_float = img.getStyle('float');
        if (img_float && img_float !== 'none') {
            // transfer float from image to span (home page)
            span.setStyle({'float': img_float, zIndex: 2});
            img.setStyle({'float': ''});
        } else {
            // list pages do not float. make the a tag above relative and this one absolute...
            var a = span.up('a');
            if (a) {
                a.setStyle({position: 'relative'});
                span.setStyle({position: 'absolute' });
                if (img.up('.listing-type-list')) {
                    span.setStyle({top: '10px'});
                }
                else {
                    span.setStyle({bottom: '0px'});
                }

                if ($$('body')[0].className.indexOf('wishlist')>=0 || img.up('.listing-type-list')) {
                    span.setStyle({left: '0px'});
                }
                else {
                    span.setStyle({right: '0px'});
                }
            }
        }

        // hide original image
        img.setStyle({opacity: 0, filter: 'alpha(opacity=0)', '-moz-opacity': 0});

        // add another image for later hovering
        var img_attr = {src: img.readAttribute('src'), style: 'position:absolute; bottom:0px; right:0px'};
        $w('width height alt title')
        .findAll(function(x) { return img.readAttribute(x) })
        .each(function(x) {
            img_attr[x] = img.readAttribute(x)
        });

        var hover_image = new Element('img', img_attr);
        span.insert(hover_image);

        // save a few things in our object
        this._original_image = img;
        this._span = span;
        this._hover_image = hover_image;

        this._hovered = false;

        // watch mouse movements
        document.observe('mousemove', this.onMouseMove.bindAsEventListener(this));
    },

    onMouseMove: function(e) {
        var t = e.target;
        if (e.target == this._hover_image) {
            // we contacted the hover image
            if (!this._hovered) {
                // console.log('over hover image');
                this._hovered = true;
                // TODO: animate bigger
                this._hover_image.setStyle({zIndex: 1000});
                var h = this._hover_image.getHeight();
                var w = this._hover_image.getWidth();
                if (!this._orig_h) {
                    this._orig_h = h;
                    this._orig_w = w;
                } else {
                    // don't trust read values, could be a multi-hover...
                    h = this._orig_h;
                    w = this._orig_w;
                }
                var w2 = Math.round(w/2);
                var h2 = Math.round(h/2);
                var multiplier = 3;
                //if(this._hover_image.up('.listing-type-list')) {
                //    multiplier = 4;
                //}

                if (Prototype.Browser.IE) {
                    multiplier = 2;
                }

                if(this._hover_image.up('.homebox')) {
                    multiplier=2;
                }
                new Effect.Morph(this._hover_image, {style: {height: h*multiplier + 'px', width: w*multiplier + 'px', top: -h + 'px', left: (-w-22) + 'px', padding: '20px'},
                                                     duration: 0.5,
                                                     afterFinish: this.onFullHeight.bindAsEventListener(this)});
            }
        } else if (this._hovered) {
            // console.log('out of hover image');
            this._hovered = false;
            // TODO: animate smaller
            var h = this._orig_h;
            var w = this._orig_w;
            new Effect.Morph(this._hover_image, {style: {height: h + 'px', width: w + 'px', top: '0px', left: '0px', padding: '0px'},
                                                 duration: 0.5,
                                                 afterFinish: this.onOrigHeight.bindAsEventListener(this)});
        }
    },

    onFullHeight: function() {
        // console.log('resize done');
        this._hover_image.addClassName('hovered');
        this._hover_image.setStyle({zIndex: 2000});
        var item = this._hover_image.up('li.item');
        if (Prototype.Browser.IE && item) {
            // set a z-Index for the surrounding item to prevent z-index bug to capture us.
            item.setStyle({zIndex: 5});
        }
    },

    onOrigHeight: function() {
        // console.log('shrink done');
        this._hover_image.removeClassName('hovered');
        this._hover_image.setStyle({zIndex: 2});
        var item = this._hover_image.up('li.item');
        if (Prototype.Browser.IE && item) {
            // lower the previously set z-Index for the surrounding item again
            item.setStyle({zIndex: 0});
        }
    }
});

//
// We extend the original Varien.DOB (date of birth) mechanism by saving the old one and overwrting Varien.DOB.validate.
// The old function is called first, then we do our age check.
//
nureg.weinhalle.DOB = {
    //orig : Object.clone(Varien.DOB),
    orig : Varien.DOB,
    age_threshold : 18
};
(function() {

    //Varien.DOB = nureg.weinhalle.DOB.orig; //Class.create(nureg.weinhalle.DOB.orig);
    Varien.DOB = Class.create(nureg.weinhalle.DOB.orig);
    Varien.DOB.prototype.validate = function () {
        var valid=false;
        var orig_validation = nureg.weinhalle.DOB.orig.prototype.validate.call(this);

        if (orig_validation === true) {
            var age_ok=false;
            var age_threshold = nureg.weinhalle.DOB.age_threshold;
            var now = new Date();
            var nowYear=now.getYear();
            if (nowYear<1900) { //Die IEs liefern das richtige Jahr zurück, die anderen die Jahre seit 1900.
                nowYear+=1900;
            }

            if (nowYear-this.year.value > age_threshold) {
                age_ok=true;
            }
            else if (nowYear-this.year.value === age_threshold ) {
                if(now.getMonth()+1-this.month.value >= 0) {
                    age_ok=true;
                }
                else if (now.getDate() - this.day.value >= 0) {
                    age_ok=true;
                }
            }

            if (!age_ok) {
                this.advice.innerHTML = 'Sie müssen mindestens 18 Jahre alt sein.';
                this.advice.show();
            }
            else {
                valid=true;
            }
        }
        else {
            valid=true;
        }

        return valid;
    };
})();

nureg.weinhalle.GlossaryLink = Class.create({
    initialize: function(el) {
        this._element = $(el);
        var glossary_id = this._element.classNames().grep(/^_replace_/).first().replace(/^_replace_/,'');
        // console.log('id = ' + glossary_id);
        if (!glossary_id) return;
        this._glossary = $('replacement_' + glossary_id);
        if (!this._glossary) return;

        this._visible = false;
        this._element.observe('mousemove', this.onMouseEnter.bindAsEventListener(this));

        close_button = this._glossary.down('.close');
        if (close_button) {
            close_button.observe('click', this.doClose.bind(this));
        }

        document.observe('glossary:close', this.forceClose.bindAsEventListener(this));

        // console.log('init done');
    },

    onMouseEnter: function(e) {
        // console.log('entered link');

        if (this._visible) return;

        // [ left, top ]
        var offset = this._element.cumulativeOffset();
        var l = offset[0];
        var t = offset[1] + 20;
        // console.log('l=' + l + ', t=' + t);

        // check if inside a popup --> modify left...
        var positioner = this._element.up('.positioner');
        if (positioner) {
            l -= positioner.cumulativeOffset[0];
        }

        this._glossary.setStyle({position: 'absolute', top: t + 'px', left: l + 'px', zIndex: 194}).show();
        this._visible = true;

        this._listener = this.leaveCheck.bindAsEventListener(this);
        document.observe('mousemove', this._listener);

        this._timer = new PeriodicalExecuter(this.onTick.bind(this),1);
        this._ticks = 0;

        document.fire('glossary:close', this);
    },

    leaveCheck: function(e) {
        var t = e.target;

        if (t === this._element) { // inside link
            this._want_close = false;
            this._ticks = 0;
        } else if (t === this._glossary || Element.up(t, 'div.glossary_popup')) { // inside popup
            this._want_close = false;
            this._ticks = 0;
        } else {
            this._want_close = true;
            // console.log('want close');
        }
    },

    onTick: function(e) {
        //console.log('tick');
        if (!this._visible) return;
        if (!this._want_close) return;

        if (++this._ticks < 5) return;

        this.doClose();
    },

    forceClose: function(e) {
        if (e.memo === this) return; // don't close myself...
        this.doClose();
    },

    doClose: function() {
        if (!this._visible) return;

        this._glossary.hide();

        this._visible = false;
        document.stopObserving('mousemove', this._listener);
        this._listener = undefined;

        if (this._timer) this._timer.stop();
        this._timer = undefined;
        this._ticks = 0;
    }
});

// special instructions for agent IE
nureg.weinhalle.InfoLabelFixer = Class.create({
    initialize: function(div) {
        this._div = div;
        this._item = div.up('.item');
        if (!this._item) return;

        this._popup = div.down('.attribute_popup');

        if (this._popup) {
            this._popup.setStyle({left: '20px'});
        }

        this._div.observe('mouseenter', this.onMouseEnter.bindAsEventListener(this));
        this._div.observe('mouseleave', this.onMouseLeave.bindAsEventListener(this));
    },

    onMouseEnter: function(e) {
        this._item.setStyle({zIndex: 5});
        this._div.setStyle({zIndex: 190});
    },

    onMouseLeave: function(e) {
        this._item.setStyle({zIndex: 4});
        this._div.setStyle({zIndex: 1});
    }
});

// a simple clearable select element
nureg.weinhalle.ClearableSelect = Class.create({
    initialize: function(el) {
        this._select = el;
        this._link   = el.next('a');

        if (!this._link) return;

        this._link.observe('click',    this.clearList.bindAsEventListener(this));
        this._select.observe('change', this.checkState.bindAsEventListener(this));
        this.checkState();
    },

    clearList: function(e) {
        e.stop();
        while (this._select.selectedIndex >= 0) {
            this._select.options[this._select.selectedIndex].selected = false;
        }

        this.checkState(e);
    },

    checkState: function(e) {
        if (this._select.selectedIndex >= 0) {
            // we have a selection
            this._link.show();
        } else {
            this._link.hide();
        }
    }
});

//
// beam me up, Scotty!
//
document.observe("dom:loaded", function() {
    $$('.col-left .box ol').each(function(x) {
        new nureg.weinhalle.FilterNav(x);
    });

    $$('a._addcart').each(function(x) {
        new nureg.weinhalle.AddCartButton(x);
    });

    $$('a._soldout').each(function(x) {
        new nureg.weinhalle.SoldOutButton(x);
    });

    $$('a._productdetail').each(function(x) {
        new nureg.weinhalle.ProductDetailLink(x);
    });

    //$$('body.catalogsearch-advanced-index form fieldset.advanced-search.toggleme').each(function(x) {
    //    new nureg.weinhalle.AdvancedSearchFormToggler(x);
    //});

    $$('a._video').each(function(x) {
        new nureg.weinhalle.VideoLink(x);
    });

    $$('a._descriptionLink').each(function(x) {
        new nureg.weinhalle.DescriptionLink(x);
    });

    $$('img._hoverable').each(function(x) {
        new nureg.weinhalle.HoverableImage(x);
    });

    $$('span[class*="_replace_"]').each(function(x) {
        new nureg.weinhalle.GlossaryLink(x);
    });

    $$('#home_aktuell_video .close').each(function(x) {
        if (Prototype.Browser.IE) {
            x.remove();
        }
        else {
            x.observe('click', function () {
                $$('#home_aktuell_video object').each(function(video) {
                    var parent=video.up();
                    video.remove();
                    parent.removeClassName('home_hd_video');
                    parent.addClassName('home_small_video');
                    parent.insert(video);

                    x.addClassName('hide');
                });

            });
        }
    });

    var search_field = $('search');
    if (search_field) {
        search_field.observe('focus', function() {search_field.setStyle({color: '#000000'})});
        search_field.observe('blur',  function() {search_field.setStyle({color: '#cccccc'})});
        search_field.setStyle({color: '#cccccc'});
    }

    $$('#advanced-search-list select[multiple]').each(function(el) {
        // console.log('found element: ' + el);
        new nureg.weinhalle.ClearableSelect(el);
    });

    if (Prototype.Browser.IE) {
        // thank you very much mr gates for this great product - yeah
        $$('div.info_label').each(function(x) {
            new nureg.weinhalle.InfoLabelFixer(x);
        });
    }

    // currently not needed
    // $$('a._pageslide').each(function(x) {
    //     new nureg.weinhalle.PageSlideLink(x);
    // });

    //
    // QUICK HACK #1: observe links to same domain
    //
    document.observe('click', function(e) {
        //alert('clicked');
        //if (!Event.isLeftClick(e)) return;
        // if (e.button > 1) return;
        var t = e.target;
        t = (t.tagName.toUpperCase() === 'A' ? t : Element.up(t,'a'));
        if (t && t.tagName.toUpperCase() === 'A') {
            //
            // we are a link. check if we want to see the spinning bottle.
            // no bottle in case of a pure hash-link like '#payment'
            //
            var href = Element.readAttribute(t, 'href') || '';
            if (href.match(/^#/)) return;
            if (href.match(/mailto:/)) return;

            var host = window.location.hostname;

            // don't continue if we have a target
            var target = Element.readAttribute(t, 'target');
            if (target) return;

            // don't continue if we have a onclick
            var onclick = Element.readAttribute(t, 'onclick');
            if (onclick) return;

            //
            // don't show a spinning bottle if an absolute URL with different host is clicked
            //
            var matches;
            if (matches = href.match(/^([a-z]+):\/\/([^\/:]+)/i)) {
                //
                // we have an absolute link
                // filter out javascript: protocol or hosts different to ourself
                //
                if (matches[1].toLowerCase() === 'javascript') return;
                if (matches[2].toLowerCase() !== host.toLowerCase()) return;
            }

            //
            // OK, show the curtain.
            //
            if (Prototype.Browser.IE) {
                $('curtain_bottle').setStyle({'position':'absolute', 'top': (document.documentElement.scrollTop + 150 + "px") });
            }
            // $('curtain').show().addClassName('bottle');
            $('curtain').addClassName('bottle');
            (function() {$('curtain').show()}).defer();
        };
    });

    //
    // QUICK HACK #2: pimp window.setLocation()
    //                handles page-size and sorting select boxes
    //
    (function() {
        var orig_setLocation = window.setLocation;

        window.setLocation = function(url) {
            if (Prototype.Browser.IE) {
                $('curtain_bottle').setStyle({'position':'absolute', 'top': (document.documentElement.scrollTop + 150 + "px") });
            }
            $('curtain').show().addClassName('bottle');
            orig_setLocation(url);
        }
    })();

    //
    // QUICK HACK #3: observe all GET-Forms submissions
    //                handles search forms
    //
    $$('form[method="get"]').each(function(f) {
        f.observe('submit', function(e) {
            if (Prototype.Browser.IE) {
                $('curtain_bottle').setStyle({'position':'absolute', 'top': (document.documentElement.scrollTop + 150 + "px") });
            }
            $('curtain').show().addClassName('bottle');
        });
    });

    // hide curtain on ESC
    document.observe('keydown',
            function (e) {
               if ($('curtain').hasClassName('bottle') && e.keyCode===27) { //Escape
                   //e.stop();
                   $('curtain').removeClassName('bottle');
                   $('curtain').hide();
               }
            }
    );


    // preload spinning bottle image
    $('curtain').insert({bottom: new Element('img',
                                             {
                                                id: 'curtain_bottle',
                                                src: '/skin/frontend/default/weinhalle/images/KU_Logo_dreh_128x128_64.gif'
                                             }
                                            )});
});
