window.addEvent('domready', function() {
    initEvents();
});

function initEvents() {
    
    if(!Browser.Engine.trident) {
        new HeaderEffectsController();
    }
    
    new NewsletterController({'form': $('newsletterform'), 'submitButton': $('newslettersubmitbutton'), 'container': $('newsletter'), 'containerFoldClasss': '.newsletterfold'});
    
    new ArticleSlider($('nextproductleft'), $('nextproductright'), $('slidercontainer'));
    
    new ArticleSlider($('gnextproductleft'), $('gnextproductright'), $('gslidercontainer'), {'interval': true, 'intervalTime': 11500});
    
    new CollapseManager($('newsletter'), 'closeButton', '.newsletterfold');
    new CollapseManager($('categoriedesc'), 'closeButton', '.categoriedescfold');
    
    var acc = new ArticleCartController({'cartContainer': $('basketfooter')});
    new ArticleCartEffects(acc);

    new BarPinner($('sbl'), 85);

    if ($$('.registernow')[0]) {
        var sbroffset = 110;
    } else {
        var sbroffset = 85;
    }
    new BarPinner($$('.categorierightbar')[0], sbroffset);

    var kontakt = true;
    if (!kontakt) {
        new InputLabelEffect($('cynname'), $('cyourname'));
        new InputLabelEffect($('cmail'), $('cyourmaillabel'));
    }
    
    new InputLabelEffect($('spusername'), $('spusernamelabel'));
    new InputLabelEffect($('sppassword'), $('sppasswordlabel'));
    new InputLabelEffect($('username'), $('usernamelabel'));
    new InputLabelEffect($('password'), $('passwordlabel'));
    
    if ($('lscfendtimestamp')) {
        var toDate = $('lscfendtimestamp').getProperty('text').toInt() * 1000;
        new Countdown({
            'toDate': toDate,
            'hoursElement': $('lscdhours'),
            'minutesElement': $('lscdminutes'),
            'secondsElement': $('lscdseconds')
        });
    }
    
    new FitsToModels();
    new InfoBubblesManager();
    new Callback();
    SqueezeBox.assign($$('#altimg a', '#aimg'));
    
    var lo = $('link_old');
    if (lo) {
     lo.setProperty('html', '<a class="old_shop" href="http://old.scooterkingz.com"></a><a class="report_bug" href="mailto:bugreport@scooterkingz.com"></a>');
    }
    
}

var BarPinner = new Class({
    
    initialize: function(element, offset) {
        if (element) {
            this.element = element;
            this.offset = offset;
            this.scrollOffset = element.getPosition().y - offset;
            this.loadObserver();
        }
    },
    
    loadObserver: function() {
        var inst = this;
        var dist = this.scrollOffset;
        ScrollObserver.getInstance().add({
            'y': dist,
            
            'beforeY': function() {
                inst.before();
            },
            
            'afterY': function() {
                inst.after();
            }
        });
        
        window.addEvent('resize', function() {
            inst.resize();
        });
    },
    
    after: function() {
        var position = this.element.getPosition();
        if (this.isPinable()) {
            this.element.setStyles({'position': 'fixed', 'top': this.offset, 'left': position.x});
            this.element.store('pinned', true);
        }
    },
    
    before: function() {
        if (this.element.retrieve('pinned')) {
            this.element.setStyles({'position': 'relative', 'top': 0, 'left': 0});
            this.element.store('pinned', false);
        }
    },
    
    isPinable: function() {
        var esize = this.element.getSize();
        var wsize = window.getSize();
        return esize.y < wsize.y;
    },
    
    resize: function() {
        var pinned = this.element.retrieve('pinned');
        this.before();
        if (pinned) {
            this.after();
        }
    }
    
});

//ScooterModel
var ScooterModel = new Class({
    
    initialize: function(id, name) {
        this.id = id;
        this.name = name;
    },
    
    setManufacturer: function(manufacturer) {
        //In a function to reduce recursion
        this.manufacturer = function() {
            return manufacturer;
        };
    },
    
    getManufacturer: function() {
        return this.manufacturer();
    }
    
});

//ScooterManufacturer
var ScooterManufacturer = new Class({
    
    models: new Array(),
    
    initialize: function(id, name) {
        this.id = id;
        this.name = name;
    },
    
    addModel: function(model) {
        this.models.push(model);
    },
    
    addModels: function(models) {
        this.models.combine(models);
    },
    
    getModels: function() {
        return this.models;
    }
    
});


//ModelChooseItem
var ModelChooseItem = new Class({
    
    checked: false,
    
    initialize: function(object, options) {
        this.internalId = ModelChooseItem.instances();
        
        this.id = object.id;
        this.name = object.name;
        this.type = getClassName(object);
        this.object = object;

        if (options) {
            this.showManufacturerName = options.showManufacturerName;
        }
        
        this.loadElements();
    },
    
    loadElements: function() {
        this.label = this.getLabel();
        this.checkBox = this.getCheckbox();
    },
    
    getLabel: function() {
        if (this.showManufacturerName) {
            var name = this.object.getManufacturer().name + ' ' + this.name;
        } else {
            var name = this.name;
        }
        this.label = this.label ? this.label : new Element('label', {'html': name, 'for': 'chooseModelItem'+this.internalId}).store('mci', this);
        return this.label;
    },
    
    getCheckbox: function() {
        this.checkBox = this.checkBox ? this.checkBox : new Element('input', {'type': 'checkbox', 'name': 'modelChooseItems', 'id': 'chooseModelItem'+this.internalId, 'value': this.id, 'checked': this.checked}).store('mci', this);
         return this.checkBox;
    },
    
    getModelChooseCheckbox: function() {
        this.modelChooseCheckbox = this.modelChooseCheckbox ? this.modelChooseCheckbox : new ModelChooseCheckbox(this);
        return this.modelChooseCheckbox;
    },
    
    isSelected: function() {
        return this.checkBox.checked;
    },
    
    inject: function(dest) {
        this.getCheckbox().inject(dest);
        this.getModelChooseCheckbox().inject(dest);
        this.getLabel().inject(dest);
    },
    
    destroyElements: function() {
        this.checkBox = this.checkBox.destroy();
        this.label = this.label.destroy();
        this.getModelChooseCheckbox().destroy();
    },
    
    syncChecked: function() {
        this.getModelChooseCheckbox().syncChecked();
        this.checked = this.checkBox.getProperty('checked');
    }
        
});
//Static
ModelChooseItem.instances = function() {
    if (typeof ModelChooseItem.count == 'undefined') {
        ModelChooseItem.count = 0;
    }
    return ++ModelChooseItem.count;
}

//ModelChooseCheckbox
var ModelChooseCheckbox = new Class({
    
    Implements: [Events],
    
    initialize: function(mci) {
        this.mci = mci;
        this.loader();
    },
    
    loader: function() {
        this.hideCheckBox();
    },
    
    hideCheckBox: function() {
        this.getCheckBox().setStyle('display', 'none');
    },
    
    getElement: function() {
        this.element = this.element ? this.element : new Element('div', {'class': this.getCheckBox().getProperty('checked') ? 'checked' : 'unchecked'});
        return this.element;
    },
    
    syncChecked: function() {
        this.getElement().morph(this.getCheckBox().getProperty('checked') ? '.chooseItemForm .checked' : '.chooseItemForm .unchecked');
    },
    
    inject: function(dest, position) {
        if (!position) {
            position = 'bottom';
        }
        this.hideCheckBox();
        this.getElement().store('mcc', this);
        this.getElement().inject(dest, position);
    },
    
    toElement: function() {
        return this.getElement();
    },
    
    toggleCheckbox: function() {
        this.getCheckBox().setProperty('checked', !this.getCheckBox().getProperty('checked'));
        this.syncChecked();
    },
    
    destroy: function() {
        this.getElement().destroy();
    },
    
    getCheckBox: function() {
        return this.mci.getCheckbox();
    }
    
});

//ModelChooseEventHandler
var ModelChooseEventHandler = new Class({
    
    initialize: function(container) {
        this.container = container;
        this.load();
    },
    
    load: function() {
        this.loadCheckboxEvents();
        this.loadElementEvents();
    },
    
    loadCheckboxEvents: function() {
        var inst = this;
        this.container.addEvent('change:relay(input[type=checkbox])', function(event, element) {
            inst.checkboxChange(event, element);
        });
    },
    
    loadElementEvents: function() {
        var inst = this;
        this.container.addEvent('mousedown:relay(div)', function(event, element) {
            inst.toggleCheckbox(event, element);
        });
    },
    
    checkboxChange: function(event, element) {
        var mci = element.retrieve('mci');       
        mci.syncChecked();
    },
    
    toggleCheckbox: function(event, element) {
        var mcc = element.retrieve('mcc');
        mcc.toggleCheckbox();
    }
    
});


//ModelChooser
var ModelChooser = new Class({
    
    Implements: [Options, Events],
    
    currentItems: new Array(),
    currentStep: null,
    choosedManufacturers: new Array(),
    
    steps: {1: 'Step1', 2: 'Step2', 3: 'Step3'},
    errorTypes: {NO_MANUFACTURER: "Du musst mindestens einen Hersteller auswählen!",
                 NO_MODEL: "Du musst mindestens ein Modell auswählen!"},
        
    initialize: function(destElement, models, options) {
        this.destElement = destElement;
        this.models = models;
        this.setOptions(options);
    },
    
    load: function() {
        this.currentStep = this.steps[1];
        this.destElement.set('html', '');
        this.createPanel();
        this.showItems(this.getManufacturer());
        this.initEvents();
    },
    
    initEvents: function() {
        var instance = this;
        
        this.nextButton.addEvent('mousedown', function(e) {
            e.stop();
            instance.goToNextStep();
        });
        
        this.searchTerm.addEvent('change', function() {
            instance.search();
        });
        
        this.searchTerm.addEvent('keyup', function() {
            instance.search();
        });
        
        this.prevButton.addEvent('mousedown', function() {
            instance.goToPreviousStep();
        });
    },
    
    goToNextStep: function() {
        if (this.steps[1] == this.currentStep) {
            this.loadStep2();
        } else if (this.steps[2] == this.currentStep) {
            this.loadStep3();
        }
    },
    
    goToPreviousStep: function() {
        if (this.steps[2] == this.currentStep) {
            this.loadStep1();
        } else if (this.steps[3] == this.currentStep) {
            this.loadStep2();
        }
    },
    
    loadStep1: function() {
        this.currentStep = this.steps[1];
        this.currentManufacturers = null;
        this.step.setProperties({'text': 'Step2', 'class': 'chooseItemStep1'});
        this.prevButton.setStyle('display', 'none');
        this.search();
        this.fireEvent('stepChanged', ['step1']);
    },
    
    loadStep2: function() {
        var selectedManufacturers = this.getSelectedItems();

        if (0 == selectedManufacturers.length) {
            this.showError(this.errorTypes['NO_MANUFACTURER']);
            return;
        }
    
        this.currentStep = this.steps[2];
        this.currentManufacturers = selectedManufacturers;
        this.step.setProperties({'text': 'Step2', 'class': 'chooseItemStep2'});
                
        this.prevButton.setStyle('display', 'block');
        var models = this.getModels(selectedManufacturers);
        this.showItems(models);
        this.fireEvent('stepChanged', ['step2']);
    },
    
    loadStep3: function() {
        var selectedModels = this.getSelectedItems();
        if (0 == selectedModels.length) {
            this.showError(this.errorTypes['NO_MODEL']);
            return;
        }
        
        this.showError('Modelle erfolgreich hinzugefügt. Links unter "Deine Modelle" kannst du das Modell auswählen.');

        this.fireEvent('modelsselected', [selectedModels, true]);
        this.fireEvent('stepChanged', ['step3']);
        this.loadStep1();
    },
    
    search: function() {
        var term = this.searchTerm.getProperty('value');
        this.showItems(this.filterItems(term));
        this.fireEvent('searched');
    },
    
    addPanel: function(panel) {
        panel.inject(this.destElement);
    },
    
    createPanel: function() {
        this.form = new Element('form', {'id': 'modellItemForm', 'class': 'chooseItemForm'});
        this.addPanel(this.form);
        
        this.step = new Element('p', {'id': 'chooseItemStep', 'class': 'chooseItemStep1', text: this.currentStep});
        this.addPanel(this.step);
        
        this.scroller = new Element('div', {'id': 'chooseItemScroller', 'class': 'chooseItemScroller'});
        this.addPanel(this.scroller);
        
        this.searchLabel = new Element('label', {'id': 'chooseItemSearchLabel', 'class': 'chooseItemSearchLabel', text: 'Suche'});
        this.addPanel(this.searchLabel);

        this.searchTerm = new Element('input', {'id': 'chooseItemSearchTerm', 'class': 'chooseItemSearchTerm'});
        this.addPanel(this.searchTerm);

        this.prevButton = new Element('span', {'id': 'chooseItemPrevButton', 'class': 'chooseItemPrevButton', text: 'Zurück'});
        this.prevButton.setStyle('display', 'none');
        this.addPanel(this.prevButton);

        this.nextButton = new Element('span', {'id': 'chooseItemNextButton', 'class': 'chooseItemNextButton',text: 'Weiter'});
        this.addPanel(this.nextButton);
        
        this.errorField = new Element('p', {'id': 'chooseItemErrorMessage', 'class': 'chooseItemErrorMessage'});
        this.errorField.setStyle('display', 'none');
        this.addPanel(this.errorField);
        
        this.list = new Element('ul', {'id': 'chooseItemScrollPanel'});
        this.list.inject(this.form);
        
        new InputLabelEffect(this.searchTerm, this.searchLabel);
    },
    
    getManufacturer: function() {
        if (this.manufacturers) {
            return this.manufacturers;
        }

        var manufacturers = new Array();
        
        this.models.each(function(manufacturer, index) {
            if (manufacturer.models.length != 0) {
                var mci = new ModelChooseItem(manufacturer);
                manufacturers.push(mci);
            }
        });
        this.manufacturers = manufacturers;
        
        return manufacturers;
    },
    
    getModels: function(manufacturers) {
        var modelItems = new Array();

        manufacturers.each(function(manufacturer, index) {
            manufacturer.object.models.each(function(model, index) {
                var mci = new ModelChooseItem(model, {showManufacturerName: (manufacturers.length > 1)});
                modelItems.push(mci);
            });
        });
                
        return modelItems;
    },
    
    removeAllItems: function() {
        this.currentItems.each(function(item, index) {
            item.destroyElements();
        });
        this.list.empty();
        
        this.currentItems = null;
    },
    
    showItems: function(items) {
        this.removeAllItems();
        this.currentItems = items;
        
        var list = this.list;
        items.each(function(item, index) {
            var li = new Element('li');
            item.inject(li);
            li.inject(list);
        });
        this.list.setStyle('width', this.getElementsSize().x / 2); 
        
    },
    
    getElementsSize: function() {
        var result = {'x': 0, 'y': 0};
        this.list.getElements('li').each(function(item, index) {
            result.x += item.getSize().x;
            result.y += item.getSize().y;
        });
        return result;
    },
       
    getSelectedItems: function() {
        var result = new Array();

        this.currentItems.each(function(item, index) {
            if (item.isSelected()) {
                result.push(item);
            }
        });
        
        return result;
    },
    
    filterItems: function(term) {       
        return this.getCurrentItems().filter(function(item, index) {
            if (item.name.toLowerCase().indexOf(term.toLowerCase()) != -1) {
                return true;
            }
            
            return false;
        });
    },
    
    getCurrentItems: function() {
        if (this.steps[1] == this.currentStep) {
            return this.getManufacturer();
        }
        
        if (this.steps[2] == this.currentStep) {
            return this.getModels(this.currentManufacturers);
        }
    },
    
    showError: function(error) {
        this.errorField.setProperty('text', error);
        var errorChain = new Chain();

        var inst = this;        
        var callShowErrorMsg = function() {
            inst.showErrorMsg();
            errorChain.callChain();
        }
        
        var callHideErrorMsg = function() {
            inst.hideErrorMsg();
            errorChain.callChain();
        }

        errorChain.chain(callShowErrorMsg).wait(3000).chain(callHideErrorMsg);
        errorChain.callChain();
    },
    
    showErrorMsg: function() {
        this.errorField.setStyle('display', 'block');
    },
    
    hideErrorMsg: function() {
        this.errorField.setStyle('display', 'none');
    }
    
});


//ModelChooserDragger
var ModelChooserDragger = new Class({
    
    Implements: [Options],
    
    options: {},
    
    initialize: function(options) {
        this.setOptions(options);
        
        this.scroller = options.scroller;

        this.loadElements();
        this.injectElements(options.target);
        this.loadSlider();
        this.loadEvents();
    },
    
    loadSlider: function() {
        var inst = this;
        this.slider = new Slider(this.slideArea, this.dragger, {
            onChange: function(pos) {
                inst.posChanged(pos);
            }
        });
    },
    
    loadEvents: function() {
        var inst = this;
        this.leftButton.addEvent('mousedown', function() {
            inst.toLeft();
        });
        
        this.rightButton.addEvent('mousedown', function() {
            inst.toRight();
        });
    },
    
    toLeft: function() {
        this.slider.set(this.slider.step - 1);
    },
    
    toRight: function() {
        this.slider.set(this.slider.step + 1);        
    },
    
    posChanged: function(pos) {
        var newPos = (pos / 100) * (this.scroller.getSize().x - this.scroller.getParent().getSize().x);
        this.scroller.setStyle('left', newPos * -1);
    },
    
    loadElements: function() {
        this.leftButton = new Element('span', {'class': 'leftButton'});
        this.rightButton = new Element('span', {'class': 'rightButton'});
        this.slideArea = new Element('div', {'class': 'slideArea'});
        this.dragger = new Element('span', {'class': 'dragger'});
    },
    
    injectElements: function(target) {
        this.leftButton.inject(target);
        this.rightButton.inject(target);
        this.slideArea.inject(target);
        this.dragger.inject(this.slideArea);
    },
    
    scrollable: function() {
        if (this.scroller.getSize().x <= this.scroller.getParent().getSize().x) {
            this.slider.detach();
        } else {
            this.slider.attach();
        }
    },
    
    resetScroller: function() {
        this.scrollable();
        this.slider.set(0);
    }
    
});

//ModelChooserController
var ModelChooserController = new Class({
    
    Implements: Options,
       
    initialize: function(options) {
        this.setOptions(options);
        
        this.load();
    },
    
    load: function() {
        this.loadCookieManager();
        this.loadScooterModelSelection();
        this.loadModelChoose();
        this.loadEvents();
        this.loadModels();
        this.loadModelChooseEventHandler();
        this.loadModelChooserScroller();
        this.addModelChooserEvents();
    },
    
    loadCookieManager: function() {
        this.cookieManager = new ModellCookieManager('skzmodels');
    },
    
    loadScooterModelSelection: function() {
        this.scooterModelSelection = new ScooterModelSelection({'targetElement': $('sidebarnav'),
                                                               'injectDest': 'top'});
    },
    
    loadModelChoose: function() {
        this.modelChooser = new ModelChooser($('modelchooser'), createModelStructureFromJson(getNewModelStructure()));
        this.modelChooser.load();
    },
    
    loadModelChooseEventHandler: function() {
        this.modelChooseEventHandler = new ModelChooseEventHandler($('modellItemForm'));
    },
    
    loadModelChooserScroller: function() {
        this.modelChooserDragger = new ModelChooserDragger({'target': $('modelchooser'), 'scroller': $('chooseItemScrollPanel')});
    },
    
    loadEvents: function() {
        var inst = this;
        
        this.modelChooser.addEvent('modelsselected', function(mci, setLast) {
            inst.cookieManager.addModels(mci);
            inst.reloadModels(setLast);
        });
        
        this.scooterModelSelection.addEvent('removeSelection', function() {
            inst.cookieManager.removeScooterSelection();
        });
    },
    
    loadModels: function(setLast) {
        var inst = this;
        var models = this.cookieManager.getModels();
        var currentModel = this.cookieManager.getCurrentModel();
        
        var groups = {};
        
        models.each(function(item, index) {
            if (currentModel) {
                if (item.id == currentModel.id) {
                    item.setActive(true);
                }
            }
            
            if (!groups[item.manufacturerName]) {
                groups[item.manufacturerName] = new Array();
            }
    
            groups[item.manufacturerName].include(item);
        });
        
        var keys = new Array();
        for (var key in groups) {
            keys.push(key);
        }
                
        keys.sort();
        keys.each(function(item, index) {
            
            groups[item].sort(function(a, b) {
                if (a.name ==  b.name) {
                    return 0;
                }
                
                return (a.name < b.name) ? -1 : 1;
            });
            
            
            inst.addModelToShortList(item);
            groups[item].each(function(item2, index) {
                inst.addModelToShortList(item2);
            });
            
        });
        
        if (!currentModel && setLast) {
            this.cookieManager.setModel(groups[keys.getLast()].getLast());
        }
        
        
    },
    
    reloadModels: function(setLast) {
        this.scooterModelSelection.clear();
        this.loadModels(setLast);
    },
    
    addModelToShortList: function(csm) {
        if (typeof csm == 'string') {
            this.scooterModelSelection.addGroup(csm);
        } else {
            this.addShortListEvents(csm);
            this.scooterModelSelection.addModel(csm);
        }
    },
    
    addShortListEvents: function(csm) {
        var inst = this;
        
        csm.addEvent('chooseItem', function() {
            inst.cookieManager.setModel(csm);
        });
        
        csm.addEvent('removeItem', function() {
            inst.cookieManager.removeModel(csm);
            if (csm.active) {
                inst.cookieManager.removeScooterSelection();
            }
            inst.reloadModels();
        });
    },
    
    addModelChooserEvents: function() {
        var inst = this;
        this.modelChooser.addEvent('stepChanged', function(step) {
            inst.stepChanged(step);
        });
        
        this.modelChooser.addEvent('searched', function() {
            inst.searched();
        });
    },
    
    stepChanged: function(step) {
        this.modelChooserDragger.resetScroller();
    },
    
    searched: function() {
        this.modelChooserDragger.resetScroller();
    }
    
});

//ScooterModelSelection
var ScooterModelSelection = new Class({
    
    Implements: [Options, Events],
    
    options: {
        'targetElement': '',
        'injectDest': 'bottom',
        'headlineClass': 'cmsheadline',
        'headlineText': '<span>SKZ</span>Modellauswahl',
        'listClass': 'modelSelectionList'
    },
    
    initialize: function(options) {
        this.setOptions(options);
        this.load();
    },
    
    load: function() {
        this.createContainerList();
        this.addEvents();
    },
    
    createContainerList: function() {
        this.menuListItem = new Element('li');
        this.menuListItem.inject(this.options.targetElement, this.options.injectDest);
        new Element('p', {'class': this.options.headlineClass, 'html': this.options.headlineText}).inject(this.menuListItem);
        this.list = new Element('ul', {'class': this.options.listClass});
        this.noSelection = new Element('li', {'html': '<span>Auswahl aufheben</span>', 'class': 'nomodel'});
        this.list.inject(this.menuListItem);
        this.noSelection.inject(this.list, 'after');
    },
    
    addEvents: function() {
        var inst = this;
        this.noSelection.addEvent('mousedown', function() {
            inst.fireEvent('removeSelection');
        });
    },
    
    addModel: function(csm) {
        csm.inject(this.list);
    },
    
    clear: function() {
        this.list.empty();
    },
    
    addGroup: function(groupName) {
        new Element('li', {'class': 'group', 'text': groupName}).inject(this.list);
    }
});

//CookieScooterModel
var CookieScooterModel = new Class({
    
    Implements: Events,
    
    initialize: function(id, name, manufacturerId, manufacturerName) {
        this.id = id;
        this.name = name;
        this.manufacturerId = manufacturerId;
        this.manufacturerName = manufacturerName;
        this.active = false;
        
        this.load();
    },
    
    load: function() {
        this.createElements();
        this.addEvents();
    },
    
    createElements: function() {
        this.container = new Element('li', {'class': 'model'});
        this.link = new Element('a', {'text': this.name, 'class': this.active ? 'active' : ''});
        this.deleteButton = new Element('span', {'text': 'X', 'class': 'delete'});

        this.deleteButton.inject(this.container);
        this.link.inject(this.container);
    },
    
    addEvents: function() {
        var inst = this;
        
        this.link.addEvent('mousedown', function() {
            inst.fireEvent('chooseItem');
        });
        
        this.deleteButton.addEvent('mousedown', function() {
            inst.remove();
            inst.fireEvent('removeItem');
        });
    },
    
    removeEvents: function() {
        this.link.removeEvents();
        this.deleteButton.removeEvents();
    },
    
    inject: function(target) {
        this.container.inject(target);
    },
    
    remove: function() {
        this.removeEvents();
        this.container.destroy();
    },
    
    setActive: function(value) {
        this.active = value;
        this.link.setProperty('class', value ? 'active' : '');
    }
    
});

//ModellCookieManager
var ModellCookieManager = new Class({
    
    Implements: Options,
    
    options: {
        'modelIdName': 'scooter_model_id',
        'manufacturerIdName': 'scooter_manufacturer_id',
        'saveTime': 365
    },

    initialize: function(cookieName, options) {
        this.cookieName = cookieName;
        this.setOptions(options);

        this.loadCookieData();
    },
    
    loadCookieData: function() {
        this.cookieObj = JSON.decode(Cookie.read(this.cookieName));
        if (null == this.cookieObj) {
            this.cookieObj = {};
        }
    },
    
    saveCookieData: function() {
        Cookie.write(this.cookieName, JSON.encode(this.cookieObj), this.options.saveTime);
    },
    
    addModel: function(modelChooseItem) {
        var model = modelChooseItem.object;
        var csm = new CookieScooterModel(model.id, model.name, model.getManufacturer().id, model.getManufacturer().name);
        this.cookieObj[model.id] = csm;
        this.saveCookieData();
    },
    
    addModels: function(modelChooseItems) {
        var inst = this;
        modelChooseItems.each(function(item, index) {
            inst.addModel(item);
        });
    },

    removeModel: function(csm) {
        delete this.cookieObj[csm.id];
        this.saveCookieData();
    },
    
    removeScooterSelection: function() {
        Cookie.dispose('scooter_manufacturer_id');
        Cookie.dispose('scooter_model_id');
        location.reload();
    },

    setModel: function(csm) {
        Cookie.write(this.options.modelIdName, csm.id);
        Cookie.write(this.options.manufacturerIdName, csm.manufacturerId);
        location.reload();
    },
    
    getModels: function() {
        var result = new Array();
        for (var item in this.cookieObj) {
            var co = this.cookieObj[item];
            var csm = new CookieScooterModel(co.id, co.name, co.manufacturerId, co.manufacturerName);
            result.push(csm);
        }
        return result;
    },
    
    getCurrentModel: function() {
        var currentModelId = Cookie.read('scooter_model_id');
        if (null == currentModelId) {
            return 0;
        }
        return this.cookieObj[currentModelId];
    }
    
});

//InputLabelEffect
var InputLabelEffect = new Class({

    labelVisible: 1,
    labelFocused: 0.7,
    labelHide: 0,
    inputFocus: false,

    initialize: function(inputField, inputLabel) {
        this.inputField = inputField;
        this.inputLabel = inputLabel;
        if (this.inputField && this.inputLabel) {
            this.observeInput();
            this.changeLabelState();
        }
    },
    
    observeInput: function() {
        var inst = this;
        if (this.inputField) {
            this.inputField.addEvent('focus', function() {
                inst.inputFieldGetFocus();
            });
            
            this.inputField.addEvent('keyup', function() {
                inst.inputFieldKeyUp();
            });
                       
            this.inputField.addEvent('blur', function() {
                inst.inputFieldBlur();
            });
        }
    },
    
    inputFieldGetFocus: function() {
        this.inputFocus = true;
        this.changeLabelState();
    },
    
    inputFieldKeyUp: function() {
        this.changeLabelState();
    },
       
    inputFieldBlur: function() {
        this.inputFocus = false;
        this.changeLabelState();
    },
    
    setLabelState: function(opacity) {
        this.inputLabel.fade(opacity);
    },
    
    changeLabelState: function() {
        if("" != this.inputField.getProperty('value')) {
            if(this.inputLabel.getStyle('opacity') >= this.labelFocused) {
                this.setLabelState(this.labelHide);
                return;
            }
            return;
        }
        
        if(this.inputFocus) {
            this.setLabelState(this.labelFocused);
            return;
        }
        
        this.setLabelState(this.labelVisible);
    }
    
    
});

//HeaderEffectsController
var HeaderEffectsController = new Class({
    
    Implements: [Options],
    options: {
        'welcomeskz': $('welcomeskz'),
        'logo': $('h1logo'),
        'logoLink': $$('#h1logo a')[0],
        'addInfo': $('addinfo'),
        'addInfoSupport': $('addinfosupport'),
        'callback': $('callback'),
        'searchform': $('searchform'),
        'topbar': $('topbar'),
        'hadd': $$('.hadd')[0],
        'labelsearchterm': $('labelsearchterm'),
        'loginbar': $('loginbar'),
        'addtopbar': $('addtopbar'),
        'searchterm': $('searchterm')
    },
    
    initialize: function(options) {
        this.setOptions(options);
        this.loadScrollObserver();
    },
    
    loadEvents: function() {
        var inst = this;
        if (this.options.loginbar) {
            this.options.loginbar.addEvent('mouseenter', function() {
                inst.loginbarMouseOver();
            });
            
            this.options.loginbar.addEvent('mouseleave', function() {
                inst.loginbarMouseLeave();
            });
        }
    },
    
    removeEvents: function() {
        if (this.options.loginbar) {
            this.options.loginbar.removeEvents();
        }
    },
    
    loadScrollObserver: function() {
        var inst = this;
        ScrollObserver.getInstance().add({
            'y': 40,
            
            'beforeY': function() {
                inst.blendInWelcomeSKZ();
                inst.moveLogoToHeader();
            },
            
            'afterY': function() {
                inst.blendOutWelcomeSKZ();
                inst.moveLogoToTopBar();
            }
        });
        
        ScrollObserver.getInstance().add({
            'y': 140,
            
            'beforeY': function() {
                inst.moveAddInfoToHeader();
                inst.origAddInfo();
                inst.origAddTopBar();
                inst.removeEvents();
            },
            
            'afterY': function() {
                inst.moveAddInfoToTopBar();
                inst.smallAddInfo();
                inst.smallAddTopBar();
                inst.loadEvents();
            }
        });
    },
    
    blendOutWelcomeSKZ: function() {
        this.options.welcomeskz.fade(0);
    },
    
    blendInWelcomeSKZ: function() {
        this.options.welcomeskz.fade(1);
    },
    
    moveLogoToTopBar: function() {
        this.options.logo.inject(this.options.topbar);
        this.options.logo.morph('.headerh1moved');
        this.options.logoLink.morph('.headerh1moveda');
    },
    
    moveLogoToHeader: function() {
        this.options.logo.morph('#h1logo');
        this.options.logoLink.morph('#h1logo a');
        this.options.logo.inject($('header'));
    },
    
    moveAddInfoToTopBar: function() {
        this.options.addInfo.inject(this.options.topbar);
    },
    
    moveAddInfoToHeader: function() {
        this.options.addInfo.inject(this.options.hadd);
    },
    
    smallAddInfo: function() {
        this.options.addInfoSupport.morph('.addinfosupportsmall');
        this.options.callback.morph('.callbacksmall');
        this.options.addInfo.morph('.addinfosmall');
    },
    
    origAddInfo: function() {
        this.options.addInfoSupport.morph('.addinfosupport');
        this.options.callback.morph('.callback');
        this.options.addInfo.morph('.addinfo');
    },
    
    smallAddTopBar: function() {
        this.options.searchform.morph('.searchformsmall');
        this.options.labelsearchterm.morph('.labelsearchtermsmall');
        this.options.addtopbar.morph('.addtopbarsmall');
        this.options.searchterm.morph('.searchtermsmall');
        if (this.options.loginbar) {
            this.options.loginbar.morph('.loginbarsmall');
        }
    },
    
    origAddTopBar: function() {
        this.options.searchform.morph('.searchform');
        this.options.labelsearchterm.morph('.labelsearchterm');
        this.options.searchterm.morph('.searchform #searchterm');
        this.options.addtopbar.morph('.topbar .addtopbar');
        if(this.options.loginbar) {
            this.options.loginbar.morph('.topbar .addtopbar .loginbar, .logoutbar');
        }
    },
    
    loginbarMouseOver: function() {
        this.options.loginbar.morph('.loginbarmouseover');
        this.options.addtopbar.morph('.addtopbarloginmouseover');
    },
    
    loginbarMouseLeave: function() {
        this.options.loginbar.morph('.loginbarsmall');
        this.options.addtopbar.morph('.addtopbarsmall');
    }
    
});

//Countdown
var Countdown = new Class({
    Implements: [Options],
    options: {
        'interval': 1000,
        'toDate': 0,
        'dayElement': null,
        'hoursElement': null,
        'minutesElement': null,
        'secondsElement': null,
        'milisecondsElement': null
    },
    
    initialize: function(options) {
        this.setOptions(options);
        this.startCountdown();
    },
    
    getHours: function(rest) {
        return Math.floor(rest % 24);
    },
    
    getMinutes: function(rest) {
        return Math.floor(rest % 60);
    },
    
    getSeconds: function(rest) {
        return Math.floor(rest % 60);
    },
    
    getMiliseconds: function(rest) {
        return Math.floor(rest % 1000);
    },
    
    getRemaining: function() {
        var result = {'days': 0, 'minutes': 0, 'seconds': 0, 'miliseconds': 0};
        var rest = this.options.toDate - (new Date().getTime());
        if (rest > 0) {
            result.miliseconds = this.getMiliseconds(rest);
            result.seconds = this.getSeconds((rest = rest / 1000));
            result.minutes = this.getMinutes((rest = rest / 60));
            result.hours = this.getHours((rest = rest / 60));                        
            result.days = Math.floor(rest / 24);
        }
        return result;
    },
    
    startCountdown: function() {
        var inst = this;
        this.showCountdown();
        (function() {inst.showCountdown();}).periodical(this.options.interval);
    },

    showCountdown: function() {
        var remaining = this.getRemaining();
        if (this.options.dayElement) {
            this.options.dayElement.setProperty('text', remaining.days);
        }
        if (this.options.hoursElement) {
            this.options.hoursElement.setProperty('text', remaining.hours);
        }
        if (this.options.minutesElement) {
            this.options.minutesElement.setProperty('text', remaining.minutes);
        }
        if (this.options.secondsElement) {
            this.options.secondsElement.setProperty('text', remaining.seconds);
        }
        if (this.options.milisecondsElement) {
            this.options.milisecondsElement.setProperty('text', remaining.miliseconds);
        }
    }
    
});

//NewsletterController
var NewsletterController = new Class({
    
    initialize: function(options) {
        this.options = options;
        if (this.options['form']) {
            this.loadEffects();
            this.loadEvents();
        }
    },
    
    loadEvents: function() {
        var inst = this;
        
        this.options.form.addEvent('submit', function(e) {
            e.stop();
            inst.formSend();
        });
        
    },
    
    loadEffects: function() {
        new InputLabelEffect($('mail'), $('nllabelmail'));
        new InputLabelEffect($('nlfirstname'), $('nllabelfirstname'));
    },
    
    formSend: function() {
        if ($('mail').getProperty('value') == "" || $('mail').getProperty('nlfirstname') == "") {
            new Notification("Fehler beim eintragen in den Newsletter", "Du musst deinen Namen und deine E-Mail Adresse angeben!");
            return; 
        }
    
        this.options['submitButton'].setProperty('disabled', 'true');
        
        var inst = this;
        
        this.options['form'].set('send', {
            onSuccess: function(responseText, responseXML) {
                inst.formSendSuccess(responseText, responseXML);
            },
            
            onRequest: function() {
                inst.formSendStart();
            }});
        
        this.options['form'].send();
    },
    
    formSendStart: function() {
        this.options['form'].fade(0);
    },
    
    formSendSuccess: function(responseText, responseXML) {
        var response = JSON.decode(responseText);
        if (response['success']) {
            this.formSuccess(response);
        } else {
            this.formFailure(response);
        }
    },
    
    formSuccess: function(reponse) {
        this.foldContainer();
        new Notification('Newsletter eintrag erfolgreich!', 'Du wurdest erfolgreich in den Newsletter eingetragen.');
    },
    
    formFailure: function(response) {
        new Notification('Fehler bei Newsletter eintrag!', 'Leider ist bei deiner eintragung in den Newsletter ein Fehler aufgetreten');
    },
    
    foldContainer: function() {
        this.containerDefaultClass = this.options.container.getProperty('class');
        this.options.container.morph(this.options.containerFoldClasss);
    },
    
    unFoldContainer: function() {
        this.options.container.morph(this.containerDefaultClass);
    }
    
    
});


//ArticleSlider
var ArticleSlider = new Class({
    
    Implements: Options,
    
    options: {
        'duration': 500,
        'interval': true,
        'intervalTime': 5000
    },
    
    initialize: function(buttonLeft, buttonRight, slideContainer, options) {
        this.buttonLeft = buttonLeft;
        this.buttonRight = buttonRight;
        this.slideContainer = slideContainer;
        
        this.setOptions(options);
        if (this.slideContainer) {
            this.initSlider();
        }
    },
    
    loadEvents: function() {
        var inst = this;
        
        this.buttonLeft.addEvent('mousedown', function() {
            inst.pushedButtonLeft();
        });
        
        this.buttonRight.addEvent('mousedown', function() {
            inst.pushedButtonRight();
        });
        
    },
    
    initSlider: function() {
        this.loadEvents();
        this.startInterval();
        
        this.position = 0;
        this.items = this.slideContainer.getChildren();
        this.steps = this.items.length - 1;
    },
    
    pushedButtonLeft: function() {
        this.resetInterval();
        this.goToPrevItem();
    },
    
    pushedButtonRight: function() {
        this.resetInterval();
        this.goToNextItem();
    },
    
    goToNextItem: function() {
        this.scrollToItem(this.getNextItem());
    },
    
    goToPrevItem: function() {
        this.scrollToItem(this.getPrevItem());
    },
    
    getPrevItem: function() {
        if (0 == this.position) {
            this.position = this.steps;
            return this.items[this.steps];
        }
        
        return this.items[--this.position];
    },
    
    getNextItem: function() {
        if (this.steps == this.position) {
            this.position = 0;
            return this.items[0];
        }
        
        return this.items[++this.position];
    },
    
    scrollToItem: function(item) {
        var stp = item.getPosition(this.slideContainer);
        this.slideContainer.tween('left', stp.x * -1);
    },
    
    startInterval: function() {
        if (this.options.interval) {
            this.timer = this.goToNextItem.periodical(this.options.intervalTime, this);
        }
    },
    
    resetInterval: function() {
        this.stopInterval();
        this.startInterval();
    },
    
    stopInterval: function() {
        if (this.timer) {
         $clear(this.timer);
        }
    }
     
});

//CollapseManager
var CollapseManager = new Class({
    
    collapsed: false,
    
    initialize: function(container, buttonClass, collapsedClass) {
        this.container  = container;
        this.buttonClass = buttonClass;
        this.collapsedClass = collapsedClass;
        if (this.container) {
            this.load();
        }
    },
    
    load: function() {
        this.defaultClass = this.container.getProperty('class');
        this.addCloseButton();
        this.addButtonEvents();
    },
    
    addCloseButton: function() {
        this.closeButton = new Element('span', {'class': this.buttonClass, 'text': 'Collapse'});
        this.closeButton.inject(this.container, 'top');
    },
    
    addButtonEvents: function() {
        var inst = this;
        this.closeButton.addEvent('mousedown', function() {
            inst.toggleCollapse();
        });
    },
    
    toggleCollapse: function() {
        if (!this.collapsed) {
            this.collapsed = true;
            this.lastHeight = this.container.getSize().y;
            this.container.morph(this.collapsedClass);
        } else {
            this.collapsed = false;
            this.container.morph({'height': this.lastHeight});
        }
    }
    
});


/*
* FUNCTIONS
*/
function createModelStructureFromJson(json) {
    var result = new Array();
    
    json.each(function(manufacturer, manufIndex) {
        var manuf = new ScooterManufacturer(manufacturer.id, manufacturer.name);
        
        manufacturer.models.each(function(model, modelIndex) {
            var model = new ScooterModel(model.id, model.name);
            model.setManufacturer(manuf);
            manuf.addModel(model);
        });
        
        result.push(manuf);
    });
    
    return result;
}

function getClassName(object) {
    var w = $H(window);
    return w.keyOf(object.constructor);
}

// ArticleCartController
var ArticleCartController = new Class({
    
    Implements: [Options, Events],
    
    options: {
        'draggables': $$('.artikclelistitem'),
        'droppables': $('cartslider'),
        'buyButtons': $$('.buybutton'),
        'cloneStyles': {'opacity': 0.7, 'position': 'absolute', 'z-index': '999', 'margin': '0'},
        'innerCartContainer': $('basketcontainer'),
        'articleList': $('cartitems'),
        'cartQuan': $('cartquan'),
        'cartTotal': $('carttotal'),
        'detailForm': $$('.productdetailcontent #cart_quantity')[0],
        'detailFormButton': $$('.productdetailcontent #addtocart')[0]
    },
    
    preArticle: {},
    dragStarted: false,
    
    initialize: function(options) {
        this.setOptions(options);
        this.errorElement = new Element('p', {'class': 'carterror'});
        this.load();
    },
    
    load: function() {
        this.loadArticleItems();
        this.loadBuyButtons();
        this.initCart();
        this.loadTimer();
        this.loadDetailFormAction();
    },
    
    loadDetailFormAction: function() {
        if(this.options.detailForm) {
            var inst = this;
            this.options.detailForm.addEvent('submit', function(event) {
                event.stop();
                inst.detailFormSend();
            });
            
            this.options.detailFormButton.addEvent('mouseenter', function() {
                inst.buttonMouseOver();
            });
            
            this.options.detailFormButton.addEvent('mouseleave', function() {
                inst.buttonMouseLeave();
            });
        }
    },
    
    detailFormSend: function() {
        var inst = this;
        this.options.detailForm.set('send', {
            
            method: 'get',
            
            onRequest: function() {
                inst.onCartRequest();
            },
            
            onComplete: function() {
                inst.onCartReqComplete();
            },
            
            onCancel: function() {
                inst.onCartReqCancel();
            },
            
            onFailure: function() {
                inst.onCartReqFailure();
            },
            
            onSuccess: function(cart) {
                inst.onCartReqSuccess(JSON.decode(cart));
            }
            
        });
        this.options.detailForm.send('/shopping_cart.php?ajax=true&action=add_product');
    },
    
    loadArticleItems: function() {
        var inst = this;
        this.options.draggables.each(function(item, index) {
            item.addEvent('mousedown', function(event) {
                inst.itemMousedown(event, item);
            });
            
            item.addEvent('mouseup', function(event) {
                inst.itemMouseup(event, item);
            });
        });
    },
    
    loadTimer: function() {
        this.periodTimer = this.initCart.periodical(60 * 1000, this);
    },
    
    initCart: function() {
        var inst = this;
        (function() {inst.sendInitialRequest();}).delay(500);
    },
    
    loadBuyButtons: function() {
        var inst = this;
        this.options.buyButtons.each(function(item, index) {
            item.addEvent('mousedown', function(event) {
                inst.addArticle(item.getParent().getProperty('id'));
            });
            
            item.addEvent('click', function(event) {
                event.stop();
            });
            
            item.addEvent('mouseenter', function() {
                inst.buttonMouseOver();
            });
            
            item.addEvent('mouseleave', function() {
                inst.buttonMouseLeave();
            });
        });
    },
    
    buttonMouseOver: function() {
        this.fireEvent('hoverBuyButton');
    },
    
    buttonMouseLeave: function() {
        this.fireEvent('leaveBuyButton');
    },
    
    itemMousedown: function(event, item) {
        this.startDragger(event, item);
    },
    
    itemMouseup: function(event, item) {
        $clear(this.startDraggerId);
    },
    
    startDragger: function(event, item) {
        var clone = this.cloneItem(item).inject(document.body);
        var dragger = this.loadDragger(clone);
        dragger.start(event);
    },
    
    cloneItem: function(item) {
        var clone = item.clone();
        clone.setStyles(item.getCoordinates());
        clone.setStyles(this.options.cloneStyles);
        clone.setProperty('id', item.getProperty('id'));

        var inst = this;
        clone.getElement('.article').addEvent('mouseup', function(event) {
            inst.followLink(this, event);
        });

        return clone;
    },
    
    followLink: function(url, event) {
        if (this.dragStarted == false && event.rightClick == false) {
            self.location.href = url;
        }
    },
    
    loadDragger: function(element) {
        var inst = this;
        var dragger = new Drag.Move(element, {
            droppables: this.options.droppables,
            
            onStart: function(element) {
                inst.onDragStart(element);
            },
            
            onCancel: function(element) {
                inst.onDragCancel(element);
            },
            
            onDrop: function(element, droppable, event) {
                inst.onItemDrop(element, droppable, event);
            },
                
            onEnter: function(element, droppable){
                inst.onDroppableEnter(element, droppable);
            },
            
            onLeave: function(element, droppable){
                inst.onDroppabelLeave(element, droppable);
            }
        });
        
        return dragger;
    },
    
    onDragStart: function(element) {
        this.fireEvent('dragBegin', [element]);
        this.dragStarted = true;
    },
    
    onDragCancel: function(element) {
        this.dragStarted = false;
        element.destroy();
    },
    
    onItemDrop: function(element, droppable, event) {
        this.dragStarted = false;
        if (droppable)  {
            this.itemDroppedOnDroppable(element, droppable, event);
        } else {
            this.itemDroppedAnywhere(element, droppable, event);
        }
    },
    
    onDroppableEnter: function(element, droppable) {
        this.fireEvent('dragEnterCart', [element]);
        this.addPreArticle(element);
    },
    
    onDroppabelLeave: function(element, droppable) {
        this.fireEvent('dragLeaveCart', [element]);
        this.removePreArticle();
    },
    
    itemDroppedOnDroppable: function(element, droppable, event) {
        this.fireEvent('droppedOnCart', [element]);
        
        if (element.getElements('.soldout').length > 0) {
            this.showErrorMsg('Dieser Artikel ist leider Ausverkauft.');
            element.destroy();
            return null;
        }

        this.addArticle(element.getProperty('id'));
        element.destroy();
    },
    
    itemDroppedAnywhere: function(element, droppable, event) {
        this.fireEvent('droppedAnywhere', [element]);
        element.destroy();
    },
    
    addArticle: function(id) {
        this.lastAddedArticleId = id;
        this.sendAddCartRequest(id);
    },
    
    addPreArticle: function(element) {
        var pos = this.isInCartArticleList(element.id)
        var cartItem = this.createCartItemFromElement(element);
        
        if (cartItem.priceStr.indexOf('ab') != -1) {
            this.showErrorMsg('Bitte wähle eine Variante aus.');
            return null;
        }
        
        if (element.getElements('.soldout').length > 0) {
            this.showErrorMsg('Dieser Artikel ist leider Ausverkauft.');
            return null;
        }
        
        if (this.cartArticleList[pos]) {
            this.preArticle = this.cartArticleList[pos];
            this.fireEvent('highlightArticle', [this.cartArticleList[pos]]);
        } else {
            this.preArticle = new CartArticle(cartItem, {'type': 'prearticle'});
            this.fireEvent('preItemBeforeAdd', [this.preArticle]);
            this.preArticle.inject(this.options.articleList);
            this.fireEvent('preItemAdded', [this.preArticle]);
        }
    },
    
    removePreArticle: function() {
        if (this.preArticle.options == undefined) {
            return;
        }

        if ('prearticle' == this.preArticle.options.type) {
            this.fireEvent('preItemBeforeRemove', [this.preArticle]);
            this.preArticle.remove.delay(500, this.preArticle);
            this.preArticle = {};
            this.fireEvent('preItemRemoved');    
        } else {
            this.fireEvent('unHighlightArticle', [this.preArticle]);
        }
    },
    
    createCartItemFromElement: function(element) {
        var img_src = element.getElement('.productimg').getProperty('src');
        var last_index_of_slash = img_src.lastIndexOf('/');
        img_src = img_src.substr(last_index_of_slash, img_src.length - last_index_of_slash);
        
        var name = element.getElement('.productnamedet').getProperty('html');
        
        var pricestr = element.getElement('.price').getProperty('html').trim(); 
        var price = pricestr.replace(',', '.').toFloat().numberFormat();
        
        return {'id': element.id, 'name': name, 'image': img_src, 'final_price': price, 'quantity': 1, 'priceStr': pricestr};
    },

    sendInitialRequest: function() {
        var inst = this;
        var myRequest = new Request.JSON({
            
            method: 'get',
            url: '/shopping_cart.php',
            
            onRequest: function() {
                inst.onCartRequest();
            },
            
            onComplete: function() {
                inst.onCartReqComplete();
            },
            
            onCancel: function() {
                inst.onCartReqCancel();
            },
            
            onFailure: function() {
                inst.onCartReqFailure();
            },
            
            onSuccess: function(cart) {
                inst.onCartReqSuccess(cart);
            }
            
        });
        myRequest.send('ajax=true&action=get_json_cart&nocache='+(new Date().getTime()));
    },
    
    sendAddCartRequest: function(articleId, type, additional) {
        var inst = this;
        if (!type) {
            var type = 'increment';
        }
        
        if(!additional) {
            var additional = '';
        }
        var myRequest = new Request.JSON({
            
            method: 'get',
            url: '/shopping_cart.php',
            
            onRequest: function() {
                inst.onCartRequest();
            },
            
            onComplete: function() {
                inst.onCartReqComplete();
            },
            
            onCancel: function() {
                inst.onCartReqCancel();
            },
            
            onFailure: function() {
                inst.onCartReqFailure();
            },
            
            onSuccess: function(cart) {
                inst.onCartReqSuccess(cart);
            }
            
        });
        myRequest.send('ajax=true&action=add_product&products_id='+articleId+'&type='+type+additional);
    },
    
    sendRemoveCartRequest: function(articleId) {
        var inst = this;
        var myRequest = new Request.JSON({
            
            method: 'get',
            url: '/shopping_cart.php',
            
            onRequest: function() {
                inst.onCartRequest();
            },
            
            onComplete: function() {
                inst.onCartReqComplete();
            },
            
            onCancel: function() {
                inst.onCartReqCancel();
            },
            
            onFailure: function() {
                inst.onCartReqFailure();
            },
            
            onSuccess: function(cart) {
                inst.onCartReqSuccess(cart);
            }
            
        });
        myRequest.send('ajax=true&action=update_product_cart&products_id='+articleId);
        
    },
    
    onCartRequest: function() {
        this.options.articleList.morph(this.options.articleListClass);
    },
    
    onCartReqComplete: function() {
        //Nothing
    },
    
    onCartReqCancel: function() {
        //First nothing
    },
    
    onCartReqFailure: function() {
        //First nothing
    },
    
    onCartReqSuccess: function(cart) {
        if (!cart) {
            this.showErrorMsg('Es ist ein Fehler aufgetreten, bitte wende dich an den Administrator.');
            return;
        }

        if (cart.success) {
            this.addToCartSuccess(cart);
            this.updateCartInfos();
        } else {
            this.addToCartError(cart.errormsg);
        }
    },
    
    loadCartInfos: function() {
        if (!this.options.cartQuan) {
            this.options.cartQuan = new Element('p', {'class': 'cartquan'}).inject(this.options.innerCartContainer);
        }
        
        if (!this.options.cartTotal) {
            this.options.cartTotal = new Element('p', {'class': 'carttotal'}).inject(this.options.innerCartContainer);
        }
        
    },
    
    updateCartInfos: function() {
        this.loadCartInfos();
        this.options.cartQuan.setProperties({'html': '<strong>' + this.countArticleInCart() + ' Artikel</strong> im Warenkorb'});
        this.options.cartTotal.setProperties({'html': 'Gesamtbetrag: <strong>' + this.lastCart.total.numberFormat(2) + ' EUR</strong>'});
    },
    
    countArticleInCart: function() {
        var result = 0;
        this.lastCart.products.each(function(item, index) {
            result += item.quantity.toInt();
        });
        return result;
    },
    
    showErrorMsg: function(errorMsg) {
        this.fireEvent('beforeShowErrorMsg', [this.errorElement]);
        this.errorElement.setProperty('text', errorMsg);
        this.fireEvent('showErrorMsg', [this.errorElement]);
    },
    
    addToCartSuccess: function(cart) {
        this.setLastCart(cart);
        this.loadCartArticle();
        this.loadRemovedArticle();
    },
    
    setLastCart: function(cart) {
        this.lastCart = cart;
        //Convert ID to INT
        this.lastCart.products.each(function(item, index) {
            item.id = item.id.toInt();
        });
    },
    
    addToCartError: function(message) {
        this.showErrorMsg(message);
    },
    
    loadCartArticle: function() {
        if (!this.cartArticleList) {
            this.cartArticleList = new Array();
            this.options.articleList.empty();
        }
        
        var inst = this;
        var cal = this.cartArticleList;
        
        this.lastCart.products.each(function(item, index) {
            var pos = inst.isInCartArticleList(item.id)
            if (cal[pos]) {
                if (cal[pos].serverArticle.quantity < item.quantity) {
                    inst.fireEvent('articleIncrement', [cal[pos], item.quantity]);
                }
                inst.fireEvent('unHighlightArticle', [cal[pos]]);
                cal[pos].setServerArticle(item);
            } else {
                var ca;
                if (inst.preArticle.id == item.id) {
                    ca = inst.preArticle;
                } else {
                    ca = new CartArticle(item);
                }
                inst.fireEvent('cartItemAdded', [ca]);
                ca.setOptions({'type': 'article'});
                
                inst.addCartArticleEvents(ca);
                
                ca.inject(inst.options.articleList);
                cal.push(ca);
            }
        });
        this.cartArticleList = cal;
    },
    
    addCartArticleEvents: function(ca) {
        var inst = this;

        ca.addEvent('remove', function() {
            inst.removeArticle(ca);
        });
        
        ca.addEvent('increment', function() {
            inst.incrementArticle(ca);
        });
        
        ca.addEvent('decrement', function() {
            inst.decrementArticle(ca);
        });
        
    },
    
    incrementArticle: function(cartArticle) {
        this.fireEvent('articleIncrement', [cartArticle]);
        if (cartArticle.optionsId) {
            var additional = '&id['+cartArticle.optionsId+']='+cartArticle.optionsValueId;
        }
        this.sendAddCartRequest(cartArticle.id, 'increment', additional);
    },
    
    decrementArticle: function(cartArticle) {
        this.fireEvent('articleDecrement', [cartArticle]);
        if (cartArticle.optionsId) {
            var additional = '&id['+cartArticle.optionsId+']='+cartArticle.optionsValueId;
        }
        this.sendAddCartRequest(cartArticle.id, 'decrement', additional);        
    },
    
    removeArticle: function(cartArticle) {
        this.fireEvent('cartItemBeforeRemove', [cartArticle]);
        var additional = '';
        if (cartArticle.optionsId) {
            additional = '{'+cartArticle.optionsId+'}'+cartArticle.optionsValueId;
        }
        this.sendRemoveCartRequest('' + cartArticle.id + additional);
        cartArticle.remove.delay(500, cartArticle);
        this.cartArticleList.erase(cartArticle);
        cartArticle = null;
        this.fireEvent('cartItemRemoved');
    },
    
    loadRemovedArticle: function() {
        var removedArticle = this.findRemovedArticle();
        var inst = this;
        removedArticle.each(function(item, index) {
            inst.removeArticle(item);
        });
    },
    
    isInCartArticleList: function(id) {
        var cal = this.cartArticleList;
        for (var i = 0; i < cal.length; i++) {
            if (id == cal[i].id) {
                return i;
            }
        }
        return false;
    },
    
    isInLastCart: function(id) {
        var products = this.lastCart.products;
        for (var i = 0; i < products.length; i++) {
            if (id == products[i].id) {
                return true;
            }
        }
        return false;
    },
    
    findRemovedArticle: function() {
        var inst = this;
        var result = new Array();
        this.cartArticleList.each(function(item, index) {
            if (!inst.isInLastCart(item.id)) {
                result.push(item);
            }
        });
        return result;
    }
    
    
});

// CartArticle
var CartArticle = new Class({
    
    Implements: [Events, Options],
    
    options: {
        'imagePath': '/images/product_images/thumbnail_images/',
        'type': 'article'
    },
    
    initialize: function(serverArticle, options) {
        this.internalId = CartArticle.instances();
        this.id = serverArticle.id;
        
        this.setOptions(options);
        this.serverArticle = serverArticle;
        
        this.load();
    },
    
    load: function() {
        this.loadAttributes();
        this.createCartElements();
        this.loadProperties();
        this.loadEvents();
    },
    
    loadAttributes: function() {
        if (this.serverArticle.attributes) {
            for (key in this.serverArticle.attributes) {
                this.optionsId = key;
                this.optionsValueId = this.serverArticle.attributes[key];
            }
        }
    },
    
    createCartElements: function() {
        this.container = new Element('li');
        this.name = new Element('p', {'id': 'cname' + this.internalId, 'class': 'cartname'});
        this.image = new Element('img', {'width': '40', 'height': '38'});
        this.price = new Element('p', {'class': 'cartprice'});
        this.removeButton = new Element('span', {'text': 'remove', 'class': 'cartremove'});
        this.incButton = new Element('span', {'text': 'ein artikel mehr','class': 'incbutton'});
        this.decButton = new Element('span', {'text': 'ein artikel weniger','class': 'decbutton'});
        
        this.name.inject(this.container);
        this.image.inject(this.container);
        this.price.inject(this.container);
        this.removeButton.inject(this.container);
        this.incButton.inject(this.container);
        this.decButton.inject(this.container);
    },
    
    loadProperties: function() {
        var unitPrice = '';
        var finalPrice = this.serverArticle.final_price;
        if (1 < this.serverArticle.quantity) {
            finalPrice = (this.serverArticle.final_price * this.serverArticle.quantity).numberFormat();
            unitPrice = '<span class="unitprice">je ' + this.serverArticle.final_price + '<span class="ueur">EUR</span></span>';
        }
    
        this.name.setProperties({'html': this.serverArticle.name + '<span class="fade">...</span>'});
        this.image.setProperties({'src': this.options.imagePath + this.serverArticle.image});
        this.price.setProperties({'html':  finalPrice + '<span class="eur">EUR</span><br/><span class="cartquantity">'+this.serverArticle.quantity + ' Stück</span>' + unitPrice});
        this.removeButton.setProperties({'class': 'remove', 'text': 'remove'});
    },
    
    loadEvents: function() {
        var inst = this;
        this.removeButton.addEvent('mousedown', function(e) {
            inst.fireEvent('remove');
        });
        
        this.incButton.addEvent('mousedown', function(e) {
            inst.fireEvent('increment');
            inst.serverArticle.quantity++;
            inst.loadProperties();
        });
        
        this.decButton.addEvent('mousedown', function(e) {
            inst.fireEvent('decrement');
            if (1 < inst.serverArticle.quantity) {
                inst.serverArticle.quantity--;
                inst.loadProperties();
            }
        });
        
    },
    
    setServerArticle: function(serverArticle) {
        this.serverArticle = serverArticle;
        this.loadProperties();
    },
    
    toElement: function() {
        return this.container;
    },
    
    inject: function(dest) {
        this.container.inject(dest);
    },
    
    remove: function() {
        this.container.destroy();
    }

});

//Static
CartArticle.instances = function() {
    if (typeof CartArticle.count == 'undefined') {
        CartArticle.count = 0;
    }
    return ++CartArticle.count;
}

//ArticleCartEffects
var ArticleCartEffects = new Class({
    
    Implements: [Options],
    
    options: {
        'oce': $('baskethl'),
        'cartContainer': $('basketfooter'),
        'cartSlider': $('cartslider'),
        'arrowElements': $$('.cartsliderleft', '.cartsliderright', '.cartsliderleft span', '.cartsliderright span'),
        'cartItems': $('cartitems'),
        'cartPos': 'closed',
        'showOnFirstTime': false
    },
    
    slidePosition: 0,
    firstTime: true,

    initialize: function(cartController, options) {
        this.cartController = cartController;
        this.setOptions(options);
        this.loadEvents();
    },
    
    loadEvents: function() {
        var inst = this;
        this.cartController.addEvents({
            'dragBegin': function(element) {inst.dragBegin(element);},
            'dragEnterCart': function(element) {inst.dragEnterCart(element);},
            'dragLeaveCart': function(element) {inst.dragLeaveCart(element);},
            'droppedOnCart': function(element) {inst.dragDroppedOnCart(element);},
            'droppedAnywhere': function(element) {inst.droppedAnywhere(element);},
            'cartItemAdded': function(cartItem) {inst.cartItemAdded(cartItem);},
            'cartItemBeforeRemove': function(cartItem) {inst.cartItemBeforeRemove(cartItem);},
            'cartItemRemoved': function() {inst.cartItemRemoved();},
            'articleIncrement': function(cartItem, newQuantity) {inst.articleIncrement(cartItem, newQuantity);},
            'articleDecrement': function(cartItem) {inst.articleDecrement(cartItem);},
            'preItemBeforeAdd': function(preItem) {inst.preItemBeforeAdd(preItem);},
            'preItemAdded': function(preItem) {inst.preItemAdded(preItem);},
            'preItemBeforeRemove': function(preItem) {inst.preItemBeforeRemove(preItem);},
            'preItemRemoved': function() {inst.preItemRemoved();},
            'beforeShowErrorMsg': function(element) {inst.beforeShowErrorMsg(element);},
            'showErrorMsg': function(element) {inst.showErrorMsg(element);},
            'preItemToArticle': function(item) {inst.preItemToArticle(item);},
            'newArticle': function(article) {inst.newArticle(article);},
            'highlightArticle': function(article) {inst.highlightArticle(article);},
            'unHighlightArticle': function(article) {inst.unHighlightArticle(article);},
            'hoverBuyButton': function() {inst.hoverBuyButton();},
            'leaveBuyButton': function() {inst.leaveBuyButton();}
        });

        this.options.oce.addEvent('mousedown', function() {
            inst.toggleCart();
        });
    },
    
    hoverBuyButton: function() {
        this.openCart(0, true);
    },
    
    leaveBuyButton: function() {
        this.closeCart();
    },
    
    toggleCart: function() {
        if (this.options.cartPos == 'closed') {
            this.showEver = true;
            this.openCart(0, true);
        } else if (this.options.cartPos == 'opened') {
            this.showEver = false;
            this.closeCart();
        }
    },
    
    openCart: function(plus, force) {
        var cartArticleList = this.cartController.cartArticleList;
        
        if (!plus) {
            plus = 0;
        }
        
        if (!cartArticleList) {
            cartArticleList = new Array();
        }
        
        if (0 == cartArticleList.length + plus) {
            this.slideOutCartLink();
        } else {
            this.slideInCartLink();
        }
        
        
        if (!this.options.showOnFirstTime && this.firstTime && !force) {
            var inst = this;
            (function() {inst.firstTime = false;}).delay(250);
            return;
        }
        
        this.options.cartPos = 'opened';
        if (4 >= (cartArticleList.length + plus)) {
            this.options.cartContainer.morph('.basketfooteropened');
            this.options.cartSlider.morph('.cartslidersmall');
        }
        if (4 < (cartArticleList.length + plus)) {
            this.options.cartContainer.morph('.basketcontainerdouble');
            this.options.cartSlider.morph('.cartsliderbig');
        }
        
    },
    
    reloadCartSpace: function(plus, noArrowAction) {
        if (!plus) {
            plus = 0;
        }
        
        var cartArticleList = this.cartController.cartArticleList;
        var length = cartArticleList.length + plus;
        
        if (9 == length && !noArrowAction) {
            this.loadArrowEvents();
            this.showArrows();
        }
        if (8 > length && !noArrowAction) {
            this.removeArrowEvents();
            this.hideArrows();
        }

        if (1 == length % 2 && 7 <= length) {
            this.options.cartItems.setStyle('width', (length / 2).ceil() * 213);
        }
    },
    
    slideInCartLink: function() {
        $('cartcheckout').morph('.cartcheckoutin');    
    },

    slideOutCartLink: function() {
        $('cartcheckout').morph('.cartcheckout');
    },
    
    showArrows: function() {
        $$(this.options.arrowElements).morph('.cartsliderarrowsactive');
        $('cartarrowright').fade(1);
        $('cartarrowleft').fade(1);
    },
    
    hideArrows: function() {
        $$(this.options.arrowElements).morph('.cartsliderarrowsstandard');
        $('cartarrowright').fade(0);
        $('cartarrowleft').fade(0);
    },
    
    loadArrowEvents: function() {
        var inst = this;
        $$('.cartsliderleft', '.cartsliderleft span').addEvent('mousedown', function() {
            inst.slideLeft();
        });
        
        $$('.cartsliderright', '.cartsliderright span').addEvent('mousedown', function() {
            inst.slideRight();
        });
        
    },
    
    removeArrowEvents: function() {
        $$('.cartsliderleft', '.cartsliderleft span', '.cartsliderright', '.cartsliderright span').removeEvents();
    },
    
    slideLeft: function() {
        if (this.slidePosition != 0) {
            this.slideToPosition(this.slidePosition - 1);
        }
    },
    
    slideRight: function() {
        var rows = ((this.cartController.cartArticleList.length / 2).ceil() - 4);
        if (this.slidePosition < rows) {
            this.slideToPosition(this.slidePosition + 1);
        }
    },
    
    slideToEnd: function() {
        var rows = ((this.cartController.cartArticleList.length / 2).ceil() - 4);
        if (0 <= rows) {
            this.slideToPosition(rows);
        }
    },
    
    slideToPosition: function(position) {
        this.slidePosition = position;
        this.options.cartItems.morph({'left': (this.slidePosition * 213) * -1});
    },

    closeCart: function() {
        var cartArticleList = this.cartController.cartArticleList;
        
        if (!cartArticleList) {
            cartArticleList = new Array();
        }
        
        var length = cartArticleList.length;
        if (!this.showEver || length == 0) {
            this.options.cartPos = 'closed';
            this.options.cartContainer.morph('.basketfooterclosed');
        }
    },
    
    dragBegin: function(element) {
        this.lastCartPos = this.options.cartPos;
        this.openCart(0, true);
        $$(this.options.arrowElements).morph('.cartsliderarrowshover');
    },
    
    dragEnterCart: function(element) {
        $$(this.options.arrowElements).morph('.cartsliderarrowsenter');
    },
    
    dragLeaveCart: function(element) {
        $$(this.options.arrowElements).morph('.cartsliderarrowsleave');
    },
    
    dragDroppedOnCart: function(element) {
        $$(this.options.arrowElements).morph('.cartsliderarrowsstandard');
    },
    
    droppedAnywhere: function(element) {
        $$(this.options.arrowElements).morph('.cartsliderarrowsstandard');
        if (this.lastCartPos == 'closed') {
            this.closeCart();
        }
    },
    
    cartItemAdded: function(cartItem) {
        this.openCart(1);
        this.reloadCartSpace(1);
        if('article' == cartItem.options.type) {
            cartItem.container.setStyles({'opacity': 0});
        }
        
        cartItem.container.morph({'opacity': 1});
    },
    
    cartItemBeforeRemove: function(cartItem) {
        cartItem.container.fade(0);
    },
    
    cartItemRemoved: function() {
        if (this.cartController.cartArticleList == 0) {
            this.closeCart();
            this.slideOutCartLink();
        } else {
            this.openCart();
        }
        this.slideToEnd();
        this.reloadCartSpace(-1);
    },
    
    articleIncrement: function(cartItem, newQuantity) {
        var addT = 1;
        if (newQuantity) {
            addT = newQuantity.toInt() - cartItem.serverArticle.quantity.toInt();
        }
        var cord = cartItem.container.getCoordinates();
        var bubble = new Element('p', {'class': 'artcountbubble', 'text': '+'+addT});
        bubble.setStyles({'left': cord.right - 150, 'top': cord.top -5, 'opacity': 0});
        bubble.inject(document.body);
        bubble.morph({'top': cord.top + 30, 'opacity': 1});
        bubble.destroy.delay(500, bubble);
    },
    
    articleDecrement: function(cartItem) {
        if (cartItem.serverArticle.quantity == 1) {
            return;
        }
        var cord = cartItem.container.getCoordinates();
        var bubble = new Element('p', {'class': 'artcountbubble', 'text': '-1'});
        bubble.setStyles({'left': cord.right - 150, 'top': cord.top + 30});
        bubble.inject(document.body);
        bubble.morph({'top': cord.top - 5, 'opacity': 0});
        bubble.destroy.delay(500, bubble);
    },
    
    preItemBeforeAdd: function(preItem) {
        this.openCart(1);
        this.reloadCartSpace(1, true);
        preItem.container.setStyle('opacity', 0);
    },
    
    preItemAdded: function(preItem) {
        this.openCart(1);
        this.reloadCartSpace(1, true);
        preItem.container.fade(0.5);
    },
    
    preItemBeforeRemove: function(preItem) {
        preItem.container.fade(0);
    },
    
    preItemRemoved: function() {
        this.openCart();
        this.reloadCartSpace(-1, true);
    },
    
    beforeShowErrorMsg: function(element) {
        element.inject(document.body);
        var cord = $('cartslider').getCoordinates();
        element.setStyles({'opacity': 0, 'display': 'block', 'left': cord.left + 114, 'top': cord.top + 25});
    },
    
    showErrorMsg: function(element) {
        element.fade(1);
        (function() {element.fade(0);}).delay(5000);
        (function() {element.setStyle('display', 'none');}).delay(5050);
    },
    
    preItemToArticle: function(item) {
        this.openCart(1);
    },
    
    newArticle: function(article) {
    },
    
    highlightArticle: function(article) {
        article.container.morph('.cartitemhighlight');
    },
    
    unHighlightArticle: function(article) {
        article.toElement().morph('#cartitems li');
    }
    
});


Class.Singleton = new Class({

	initialize: function(classDefinition, classOptions){
		this.singletonClass = new Class(classDefinition);
		this.classOptions = classOptions;
	},

	getInstance: function() {
		return this.instance || new this.singletonClass(this.classOptions);
	}

});


// ScrollObserver
var ScrollObserver = new Class.Singleton({
    
    observer: new Array(),
    
    initialize: function() {
        this.loadEvents();
    },
    
    loadEvents: function() {
        var inst = this;
        window.addEvent('scroll', function(event) {
            inst.scroll(event);
        });
    },
    
    scroll: function(event) {
        this.checkObserver();
    },
    
    checkObserver: function() {
        var inst = this;
        this.observer.each(function(item, index) {
            var events = inst.checkPosition(item);
            inst.runMethods(item, events);
        });
    },
    
    runMethods: function(item, events) {
        if (!item.lastEvents.contains(events[0])
            && typeof item[events[0]] != 'undefined') {
            
            item[events[0]].run();
        }

        if (!item.lastEvents.contains(events[1]) 
            && typeof item[events[1]] != 'undefined') {
            
            item[events[1]].run();
        }
        
        item.lastEvents = events;
    },
    
    checkPosition: function(pos) {
        var result = new Array();
        var scrollPos = window.getScroll();
        
        if(scrollPos.x < pos.x) {
            result.push('beforeX');
        } else {
            result.push('afterX');
        }
        
        if(scrollPos.y < pos.y) {
            result.push('beforeY');
        } else {
            result.push('afterY');
        }
        
        return result;
    },
    
    add: function(options) {
        options.lastEvents = new Array();
        this.observer.include(options);
        this.checkObserver();
    }
    
});

Number.implement({
	numberFormat : function(decimals, dec_point, thousands_sep) {
		decimals = Math.abs(decimals) + 1 ? decimals : 2;
		dec_point = dec_point || ',';
		thousands_sep = thousands_sep || '.';
 
		var matches = /(-)?(\d+)(\.\d+)?/.exec((isNaN(this) ? 0 : this) + '');
		var remainder = matches[2].length > 3 ? matches[2].length % 3 : 0;
		return (matches[1] ? matches[1] : '') + (remainder ? matches[2].substr(0, remainder) + thousands_sep : '') + matches[2].substr(remainder).replace(/(\d{3})(?=\d)/g, "$1" + thousands_sep) + 
				(decimals ? dec_point + (+matches[3] || 0).toFixed(decimals).substr(2) : '');
	}
});


// FitsToModels
var FitsToModels = new Class({
    Implements: [Options],
    options: {
        'button': $('models'),
        'layer': $$('.modelspasst')[0]
    },
    
    showedLayer: false,
    
    initialize: function() {
        if (this.options.button) {
            this.options.layer.setStyles({'opacity': 0});
            this.loadEvents();
        }
    },
    
    loadEvents: function() {
        var inst = this;
        this.options.button.addEvent('mouseenter', function(event) {
            inst.mouseEnter(event);
        });
        
        this.options.button.addEvent('mouseleave', function(event) {
            inst.mouseLeave(event);
        });
        
        this.options.button.addEvent('click', function(event) {
            inst.mouseDown(event);
        });
    },
    
    mouseEnter: function(event) {
        if (!this.showedLayer) {
            this.showLayer(0.7);
        }
    },
    
    mouseLeave: function(event) {
        if (!this.showedLayer) {
            this.hideLayer();
        }
    },
    
    mouseDown: function(event) {
        event.stop();
        this.toggleLayer();
    },
    
    showLayer: function(ft) {
        if (!ft) {
            ft = 1;
        }
        this.options.layer.setStyles({'display': 'block'});
        this.options.layer.fade(ft);
    },
    
    hideLayer: function() {
        var inst = this;
        this.options.layer.set('tween', {'complete': function() {inst.options.layer.setStyle('display', 'none');}});
        this.options.layer.tween('opacity', 0);
    },
    
    toggleLayer: function() {
        if (this.showedLayer) {
            this.showedLayer = false;
            this.options.button.morph('#models');
            this.hideLayer();
        } else {
            this.options.button.morph('#models:active');
            this.showedLayer = true;
            this.showLayer();
        }
    }
    
});


var InfoBubblesManager = new Class({

    Implements: [Options],
    options: {
        'injectDest': $('topbar'),
        'injectPos': 'top'
    },
    
    bubbleList: new Array(),
    
    initialize: function() {
        this.loadBubbles();
        this.loadSwitch();
    },
    
    loadBubbles: function() {
        //Productlisting
        if ($('categoriedesc')) {
            var coord = $$('.artikclelistitem')[0].getCoordinates($$('.wrapper')[0]);
            this.addBubble(new InfoBubble({
                'position': {'x': coord.right - 32, 'y': coord.top + 3},
                'text': 'Du kannst Artikel auch einfach über Drag&Drop in den Warenkorb legen. Probier es einfach mal aus!'}));
        }
        
        if($('models')) {
            var coord = $('models').getCoordinates($$('.wrapper')[0]);
            this.addBubble(new InfoBubble({
                'position': {'x': coord.left + 12, 'y': coord.top - 25},
                'text': 'Schaue hier schnell nach auf welche Modelle dieser Artikel passt. Mit einem Klick fixierst du die Liste.'}));
        }
        
        if($('attributeslink')) {
            var coord = $('attributeslink').getCoordinates($$('.wrapper')[0]);
            this.addBubble(new InfoBubble({
                'position': {'x': coord.left + 12, 'y': coord.top - 25},
                'text': 'Zu diesem Artikel sind Varianten verfügbar. Bitte wähle unten in der Liste deine gewünschte Variante aus'}));
        }
        
    },
    
    addBubble: function(bubble) {
        this.bubbleList.include(bubble);
        this.loadBubbleInfoEvents(bubble);
    },
    
    loadSwitch: function() {
        var inst = this;
        this.switchBubble = new InfoBubble({'position': {'x': 4, 'y': 4}, 'text': '...'});
        var bubble = this.switchBubble.getBubble();
        bubble.inject(this.options.injectDest, this.options.injectPos);
        
        bubble.addEvent('click', function() {
            inst.toggleSwitch();
        });
        
        bubble.store('tip:title', 'Info-Bubbles');
        bubble.store('tip:text', 'Hier kannst du die Infobubbles global deaktivieren und wieder aktivieren');
        var myTips = new Tips(bubble, {
        	timeOut: 200,
        	maxTitleChars: 50,
        	maxOpacity: .9
        });
    },
    
    toggleSwitch: function() {
        var bubble = this.switchBubble.getBubble();
        bubble.toggleClass('infobubbledisabled');
        if (bubble.hasClass('infobubbledisabled')) {
            this.hideAllBubbles();
        } else {
            this.showAllBubbles();
        }
    },
       
    loadBubbleInfoEvents: function(bubble) {
        var inst = this;
        var bubbleEl = bubble.getBubble();
        bubbleEl.addEvent('mouseenter', function() {
            inst.mouseEnter(bubble);
        });
        
        bubbleEl.addEvent('mouseleave', function() {
            inst.mouseLeave(bubble);
        });
        return bubble;
    },
    
    mouseEnter: function(bubble) {
        bubble.getBubble().setStyle('z-index', 9999);
        this.showInfo(bubble);
    },
    
    mouseLeave: function(bubble) {
        bubble.getBubble().setStyle('z-index', 997);
        this.hideInfo();
    },
    
    showInfo: function(bubble) {
        var info = this.getInfo();
        info.getElement('p').setProperty('text', bubble.getText());
        var coords = bubble.getBubble().getCoordinates($$('.wrapper')[0]);
        info.setStyles({'position': 'absolute', 'left': (coords.left -68) + 'px', 'top': (coords.top - 81) + 'px', 'display': 'block', 'opacity': 0});
        info.morph({'top': (coords.top - 101) + 'px', 'opacity': 1});
    },
    
    getInfo: function() {
        return this.info ? this.info : (this.info = new Element('div', {'class': 'infobubbletext', 'html': '<p id="ibt"></p>'}).inject($$('.wrapper')[0]));
    },
    
    hideInfo: function() {
        this.getInfo().setStyle('display', 'none');
    },
    
    hideAllBubbles: function() {
        this.bubbleList.each(function(item, index) {
            item.hide();
        });
    },
    
    showAllBubbles: function() {
        this.bubbleList.each(function(item, index) {
            item.show();
        });
    }

});

var InfoBubble = new Class({
    
    Implements: [Options],
    options: {
        'position': {'x': 0, 'y': 0},
        'text': 'Dies ist ein Demotext'
    },
    
    initialize: function(options) {
        this.setOptions(options);
        this.loadBubble();
    },
    
    loadBubble: function() {
        this.createElements();
    },
    
    createElements: function() {
        this.bubble = new Element('a', {'class': 'infobubble'});
        this.bubble.setStyles({'position': 'absolute', 'left': this.options.position.x + 'px', 'top': this.options.position.y + 'px'});
        this.bubble.inject($$('.wrapper')[0]);
    },
    
    hide: function() {
        this.bubble.setStyle('display', 'none');
    },
    
    show: function() {
        this.bubble.setStyle('display', 'block');
    },
    
    getBubble: function() {
        return this.bubble;
    },
    
    getText: function() {
        return this.options.text;
    }
    
});


var Callback = new Class({
    
    initialize: function() {
        var inst = this;
        $('callback').addEvent('click', function() {
            inst.injectLayer();
        });
    },
    
    injectLayer: function() {
        var layer = new Element('div', {'class': 'layer', 'html': '<div class="callbackform"><div class="greybox"><p class="callusback"></p><p class="callusback_text"></p><span class="close">X</span><form id="contact_us" action="/callbackform.php" method="post"><label for="cynname" id="cyourname">Dein Name:</label><input type="text" name="name" id="cynname" class="cyname" /><label for="cmail" class="cyourmail" id="cyourmaillabel">Deine Telefonnummer</label><input type="text" name="telnr" id="cmail" class="cyinputyourmail" /><label for="message_body" class="cmessagebody">Dein Text an uns...</label><textarea id="message_body" name="message_body">Dein Text an uns...</textarea><input type="submit" value="Absenden" class="cusubmit" /></form><div class="greyfooter"></div></div></div>', 'styles': {'opacity': 0}});
        var bg = new Element('div', {'class': 'darkbg', 'styles': {'opacity': 0}});
        layer.inject(document.body);
        layer.fade(1);
        bg.inject(layer, 'top');
        bg.fade(0.8);
        
        new InputLabelEffect(layer.getElement('#cynname'), layer.getElement('#cyourname'));
        new InputLabelEffect(layer.getElement('#cmail'), layer.getElement('#cyourmaillabel'));
        
        bg.addEvent('click', function() {
            layer.destroy();
        });
        
        layer.getElement('.close').addEvent('click', function() {
            layer.destroy();
        });
        
        var form = layer.getElement('form');
        
        form.addEvent('submit', function(event) {
            event.stop();
            form.send();
            new Notification('Deine CallBack Anfrage wurde versendet', 'Der nächste Freie Mitarbeiter ruft dich wärend der Geschäftszeiten zurück.');
            layer.getElement('.callbackform').destroy();
            (function() {layer.destroy()}).delay(3000);
        });
        
    }
    
});

var Notification = new Class({
    
    initialize: function(text1, text2) {
        var notification = new Element('p', {'class': 'showchoosemodel', 'html': text1 + '<span>'+text2+'</span>', 'styles': {'position': 'fixed', 'left': '50%', 'margin-left': '-281px', 'top': '50px', 'z-index': '99999'}}).inject(document.body);
        (function() {notification.destroy()}).delay(3000);
    }
    
});


var SqueezeBox = {

	presets: {
		onOpen: $empty,
		onClose: $empty,
		onUpdate: $empty,
		onResize: $empty,
		onMove: $empty,
		onShow: $empty,
		onHide: $empty,
		size: {x: 600, y: 450},
		sizeLoading: {x: 200, y: 150},
		marginInner: {x: 20, y: 20},
		marginImage: {x: 50, y: 75},
		handler: false,
		target: null,
		closable: true,
		closeBtn: true,
		zIndex: 65555,
		overlayOpacity: 0.7,
		classWindow: '',
		classOverlay: '',
		overlayFx: {},
		resizeFx: {},
		contentFx: {},
		parse: false, // 'rel'
		parseSecure: false,
		shadow: true,
		document: null,
		ajaxOptions: {}
	},

	initialize: function(presets) {
		if (this.options) return this;

		this.presets = $merge(this.presets, presets);
		this.doc = this.presets.document || document;
		this.options = {};
		this.setOptions(this.presets).build();
		this.bound = {
			window: this.reposition.bind(this, [null]),
			scroll: this.checkTarget.bind(this),
			close: this.close.bind(this),
			key: this.onKey.bind(this)
		};
		this.isOpen = this.isLoading = false;
		return this;
	},

	build: function() {
		this.overlay = new Element('div', {
			id: 'sbox-overlay',
			styles: {display: 'none', zIndex: this.options.zIndex}
		});
		this.win = new Element('div', {
			id: 'sbox-window',
			styles: {display: 'none', zIndex: this.options.zIndex + 2}
		});
		if (this.options.shadow) {
			if (Browser.Engine.webkit420) {
				this.win.setStyle('-webkit-box-shadow', '0 0 10px rgba(0, 0, 0, 0.7)');
			} else if (!Browser.Engine.trident4) {
				var shadow = new Element('div', {'class': 'sbox-bg-wrap'}).inject(this.win);
				var relay = function(e) {
					this.overlay.fireEvent('click', [e]);
				}.bind(this);
				['n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'].each(function(dir) {
					new Element('div', {'class': 'sbox-bg sbox-bg-' + dir}).inject(shadow).addEvent('click', relay);
				});
			}
		}
		this.content = new Element('div', {id: 'sbox-content'}).inject(this.win);
		this.closeBtn = new Element('a', {id: 'sbox-btn-close', href: '#'}).inject(this.win);
		this.fx = {
			overlay: new Fx.Tween(this.overlay, $merge({
				property: 'opacity',
				onStart: Events.prototype.clearChain,
				duration: 250,
				link: 'cancel'
			}, this.options.overlayFx)).set(0),
			win: new Fx.Morph(this.win, $merge({
				onStart: Events.prototype.clearChain,
				unit: 'px',
				duration: 750,
				transition: Fx.Transitions.Quint.easeOut,
				link: 'cancel',
				unit: 'px'
			}, this.options.resizeFx)),
			content: new Fx.Tween(this.content, $merge({
				property: 'opacity',
				duration: 250,
				link: 'cancel'
			}, this.options.contentFx)).set(0)
		};
		$(this.doc.body).adopt(this.overlay, this.win);
	},

	assign: function(to, options) {
		return ($(to) || $$(to)).addEvent('click', function() {
			return !SqueezeBox.fromElement(this, options);
		});
	},
	
	open: function(subject, options) {
		this.initialize();

		if (this.element != null) this.trash();
		this.element = $(subject) || false;
		
		this.setOptions($merge(this.presets, options || {}));
		
		if (this.element && this.options.parse) {
			var obj = this.element.getProperty(this.options.parse);
			if (obj && (obj = JSON.decode(obj, this.options.parseSecure))) this.setOptions(obj);
		}
		this.url = ((this.element) ? (this.element.get('href')) : subject) || this.options.url || '';

		this.assignOptions();
		
		var handler = handler || this.options.handler;
		if (handler) return this.setContent(handler, this.parsers[handler].call(this, true));
		var ret = false;
		return this.parsers.some(function(parser, key) {
			var content = parser.call(this);
			if (content) {
				ret = this.setContent(key, content);
				return true;
			}
			return false;
		}, this);
	},
	
	fromElement: function(from, options) {
		return this.open(from, options);
	},

	assignOptions: function() {
		this.overlay.set('class', this.options.classOverlay);
		this.win.set('class', this.options.classWindow);
		if (Browser.Engine.trident4) this.win.addClass('sbox-window-ie6');
	},

	close: function(e) {
		var stoppable = ($type(e) == 'event');
		if (stoppable) e.stop();
		if (!this.isOpen || (stoppable && !$lambda(this.options.closable).call(this, e))) return this;
		this.fx.overlay.start(0).chain(this.toggleOverlay.bind(this));
		this.win.setStyle('display', 'none');
		this.fireEvent('onClose', [this.content]);
		this.trash();
		this.toggleListeners();
		this.isOpen = false;
		return this;
	},

	trash: function() {
		this.element = this.asset = null;
		this.content.empty();
		this.options = {};
		this.removeEvents().setOptions(this.presets).callChain();
	},

	onError: function() {
		this.asset = null;
		this.setContent('string', this.options.errorMsg || 'An error occurred');
	},

	setContent: function(handler, content) {
		if (!this.handlers[handler]) return false;
		this.content.className = 'sbox-content-' + handler;
		this.applyTimer = this.applyContent.delay(this.fx.overlay.options.duration, this, this.handlers[handler].call(this, content));
		if (this.overlay.retrieve('opacity')) return this;
		this.toggleOverlay(true);
		this.fx.overlay.start(this.options.overlayOpacity);
		return this.reposition();
	},

	applyContent: function(content, size) {
		if (!this.isOpen && !this.applyTimer) return;
		this.applyTimer = $clear(this.applyTimer);
		this.hideContent();
		if (!content) {
			this.toggleLoading(true);
		} else {
			if (this.isLoading) this.toggleLoading(false);
			this.fireEvent('onUpdate', [this.content], 20);
		}
		if (content) {
			if (['string', 'array'].contains($type(content))) this.content.set('html', content);
			else if (!this.content.hasChild(content)) this.content.adopt(content);
		}
		this.callChain();
		if (!this.isOpen) {
			this.toggleListeners(true);
			this.resize(size, true);
			this.isOpen = true;
			this.fireEvent('onOpen', [this.content]);
		} else {
			this.resize(size);
		}
	},

	resize: function(size, instantly) {
		this.showTimer = $clear(this.showTimer || null);
		var box = this.doc.getSize(), scroll = this.doc.getScroll();
		this.size = $merge((this.isLoading) ? this.options.sizeLoading : this.options.size, size);
		var to = {
			width: this.size.x,
			height: this.size.y,
			left: (scroll.x + (box.x - this.size.x - this.options.marginInner.x) / 2).toInt(),
			top: (scroll.y + (box.y - this.size.y - this.options.marginInner.y) / 2).toInt()
		};
		this.hideContent();
		if (!instantly) {
			this.fx.win.start(to).chain(this.showContent.bind(this));
		} else {
			this.win.setStyles(to).setStyle('display', '');
			this.showTimer = this.showContent.delay(50, this);
		}
		return this.reposition();
	},

	toggleListeners: function(state) {
		var fn = (state) ? 'addEvent' : 'removeEvent';
		this.closeBtn[fn]('click', this.bound.close);
		this.overlay[fn]('click', this.bound.close);
		this.doc[fn]('keydown', this.bound.key)[fn]('mousewheel', this.bound.scroll);
		this.doc.getWindow()[fn]('resize', this.bound.window)[fn]('scroll', this.bound.window);
	},

	toggleLoading: function(state) {
		this.isLoading = state;
		this.win[(state) ? 'addClass' : 'removeClass']('sbox-loading');
		if (state) this.fireEvent('onLoading', [this.win]);
	},

	toggleOverlay: function(state) {
		var full = this.doc.getSize().x;
		this.overlay.setStyle('display', (state) ? '' : 'none');
		this.doc.body[(state) ? 'addClass' : 'removeClass']('body-overlayed');
		if (state) {
			this.scrollOffset = this.doc.getWindow().getSize().x - full;
			this.doc.body.setStyle('margin-right', this.scrollOffset);
		} else {
			this.doc.body.setStyle('margin-right', '');
		}
	},

	showContent: function() {
		if (this.content.get('opacity')) this.fireEvent('onShow', [this.win]);
		this.fx.content.start(1);
	},

	hideContent: function() {
		if (!this.content.get('opacity')) this.fireEvent('onHide', [this.win]);
		this.fx.content.cancel().set(0);
	},

	onKey: function(e) {
		switch (e.key) {
			case 'esc': this.close(e);
			case 'up': case 'down': return false;
		}
	},

	checkTarget: function(e) {
		return this.content.hasChild(e.target);
	},

	reposition: function() {
		var size = this.doc.getSize(), scroll = this.doc.getScroll(), ssize = this.doc.getScrollSize();
		this.overlay.setStyles({
			width: ssize.x + 'px',
			height: ssize.y + 'px'
		});
		this.win.setStyles({
			left: (scroll.x + (size.x - this.win.offsetWidth) / 2 - this.scrollOffset).toInt() + 'px',
			top: (scroll.y + (size.y - this.win.offsetHeight) / 2).toInt() + 'px'
		});
		return this.fireEvent('onMove', [this.overlay, this.win]);
	},

	removeEvents: function(type){
		if (!this.$events) return this;
		if (!type) this.$events = null;
		else if (this.$events[type]) this.$events[type] = null;
		return this;
	},

	extend: function(properties) {
		return $extend(this, properties);
	},

	handlers: new Hash(),

	parsers: new Hash()

};

SqueezeBox.extend(new Events($empty)).extend(new Options($empty)).extend(new Chain($empty));

SqueezeBox.parsers.extend({

	image: function(preset) {
		return (preset || (/\.(?:jpg|png|gif)$/i).test(this.url)) ? this.url : false;
	},

	clone: function(preset) {
		if ($(this.options.target)) return $(this.options.target);
		if (this.element && !this.element.parentNode) return this.element;
		var bits = this.url.match(/#([\w-]+)$/);
		return (bits) ? $(bits[1]) : (preset ? this.element : false);
	},

	ajax: function(preset) {
		return (preset || (this.url && !(/^(?:javascript|#)/i).test(this.url))) ? this.url : false;
	},

	iframe: function(preset) {
		return (preset || this.url) ? this.url : false;
	},

	string: function(preset) {
		return true;
	}
});

SqueezeBox.handlers.extend({

	image: function(url) {
		var size, tmp = new Image();
		this.asset = null;
		tmp.onload = tmp.onabort = tmp.onerror = (function() {
			tmp.onload = tmp.onabort = tmp.onerror = null;
			if (!tmp.width) {
				this.onError.delay(10, this);
				return;
			}
			var box = this.doc.getSize();
			box.x -= this.options.marginImage.x;
			box.y -= this.options.marginImage.y;
			size = {x: tmp.width, y: tmp.height};
			for (var i = 2; i--;) {
				if (size.x > box.x) {
					size.y *= box.x / size.x;
					size.x = box.x;
				} else if (size.y > box.y) {
					size.x *= box.y / size.y;
					size.y = box.y;
				}
			}
			size.x = size.x.toInt();
			size.y = size.y.toInt();
			this.asset = $(tmp);
			tmp = null;
			this.asset.width = size.x;
			this.asset.height = size.y;
			this.applyContent(this.asset, size);
		}).bind(this);
		tmp.src = url;
		if (tmp && tmp.onload && tmp.complete) tmp.onload();
		return (this.asset) ? [this.asset, size] : null;
	},

	clone: function(el) {
		if (el) return el.clone();
		return this.onError();
	},

	adopt: function(el) {
		if (el) return el;
		return this.onError();
	},

	ajax: function(url) {
		var options = this.options.ajaxOptions || {};
		this.asset = new Request.HTML($merge({
			method: 'get',
			evalScripts: false
		}, this.options.ajaxOptions)).addEvents({
			onSuccess: function(resp) {
				this.applyContent(resp);
				if (options.evalScripts !== null && !options.evalScripts) $exec(this.asset.response.javascript);
				this.fireEvent('onAjax', [resp, this.asset]);
				this.asset = null;
			}.bind(this),
			onFailure: this.onError.bind(this)
		});
		this.asset.send.delay(10, this.asset, [{url: url}]);
	},

	iframe: function(url) {
		this.asset = new Element('iframe', $merge({
			src: url,
			frameBorder: 0,
			width: this.options.size.x,
			height: this.options.size.y
		}, this.options.iframeOptions));
		if (this.options.iframePreload) {
			this.asset.addEvent('load', function() {
				this.applyContent(this.asset.setStyle('display', ''));
			}.bind(this));
			this.asset.setStyle('display', 'none').inject(this.content);
			return false;
		}
		return this.asset;
	},

	string: function(str) {
		return str;
	}

});

SqueezeBox.handlers.url = SqueezeBox.handlers.ajax;
SqueezeBox.parsers.url = SqueezeBox.parsers.ajax;
SqueezeBox.parsers.adopt = SqueezeBox.parsers.clone;

//initEvents();