if(!UI)
{
    var UI = {};
}

// ----------------------------
// ------ WIDGET ABSTRACT -----
// ----------------------------

UI.WidgetAbstract = Class.create(
{
    debug:  false,

    initialize: function(options)
    {
        this.author  = 'Vincent Louvet <vincent@e-spiration.com>';
        this.version = 0;

        this.uid     = null;
        this.errors  = $H();

        var config   = {};

        this.options = Object.extend(config, options || {});

		this.debug = this.options.debug || false;
    },

    getWidgetUniqId: function(id)
    {
        var cpt = 0;
        var id  = id || 'UI-Widget';
        var uid = id + cpt;

        if(null == this.uid)
        {
            while($(uid))
            {
                cpt = cpt + 1;
                uid = id + cpt
            }

            this.uid = uid;
        }

        return this.uid;
    },

    raiseError: function(errorCode)
    {
        if(this.debug)
        {
            var errorMsg = this.errors[errorCode] || 'Erreur non spécifiée (' + errorCode + ')';

            alert(errorMsg);
        }
    }
});

// ----------------------------


// ----------------------------
// ------ SLIDE PANEL ---------
// ----------------------------

UI.SlidePanel = Class.create(UI.WidgetAbstract,
{
    initialize: function($super, options)
    {
        var config = {
            container: 'slider',
            panel    : null,
            pageItems: 1,
            controls : {},
            duration : 0.5,
    		fps      : 18
        };

        this.playlist  = [];
        this.selected  = 0;
    	this.pages     = 0;
    	this.rendering = false;

		$super(Object.extend(config, options || {}));

        if(!$(this.options.container))
        {
            this.raiseError('CONTAINER_NOT_FOUND');

            return false;
        }

		this.onBtnPrevClickedAction = this.onBtnPrevClicked.bindAsEventListener(this);
		this.onBtnNextClickedAction = this.onBtnNextClicked.bindAsEventListener(this);

		this.initContainer();
		this.loadPlaylist();
		this.initControls();
		this.renderSlides();
    },

    onBtnPrevClicked: function(event)
	{
		event.stop();

		if(!this.rendering)
		{
			if(this.selected > 0)
			{
				new Effect.Move(
					this.options.panel,
					{
						x          : this.width,
						y          : 0,
						mode       : 'relative',
						duration   : this.options.duration,
						fps        : this.options.fps,
						queue      : {position: 'front', scope: 'slider'},
						beforeStart: function(){
							this.rendering = true;
						}.bind(this),
						afterFinish: function(){
							this.selected  = this.selected - 1;

							if(this.selected == 0)
							{
								this.options.controls.btnPrev.setStyle({
									opacity: 0.5,
									cursor : 'default'
								});
							}

							this.options.controls.btnNext.setStyle({
								opacity: 1,
								cursor : 'pointer'
							});

							this.rendering = false;
						}.bind(this)
					}
				);
			}
		}
	},

	onBtnNextClicked: function(event)
	{
		event.stop();

		if(!this.rendering)
		{
			if(this.selected < this.pages-1)
			{
				new Effect.Move(
					this.options.panel,
					{
						x          : -this.width,
						y          : 0,
						mode       : 'relative',
						duration   : this.options.duration,
						fps        : this.options.fps,
						queue      : {position: 'front', scope: 'slider'},
						beforeStart: function(){
							this.rendering = true;
						}.bind(this),
						afterFinish: function(){
							this.selected  = this.selected + 1;

							if(this.selected == this.pages - 1)
							{
								this.options.controls.btnNext.setStyle({
									opacity: 0.5,
									cursor : 'default'
								});
							}

							this.options.controls.btnPrev.setStyle({
								opacity: 1.0,
								cursor : 'pointer'
							});

							this.rendering = false;
						}.bind(this)
					}
				);
			}
		}
	},

    loadPlaylist: function()
	{
		var length = 0;
		var slides = $(this.options.container.id + '-playlist').hide().select('dl');

		slides.each(function(slide, pos){

			var data = slide.cleanWhitespace().childElements();

			this.playlist.push({
				position: pos,
				category: data[3].innerHTML,
				cat     : data[3].className,
				poster  : data[2].select('img')[0].src,
				title   : data[0].innerHTML,
				author  : data[1].innerHTML,
				links   : data[4].select('a')
			});

		}.bind(this));

		length = slides.length;

		if(length%3 == 0)
		{
			this.pages = length/this.options.pageItems;
		}
		else
		{
			this.pages = Math.floor(length/this.options.pageItems) + 1;
		}
	},

    initContainer: function()
	{
		var opts          = this.options;
		var panelTemplate = new Template('<div id="#{container}-panel">' +
			'<div id="#{container}-panel-btn-prev-container" class="panel-btn-prev-container">' +
				'<a href="#" id="#{container}-btn-prev" class="btn-prev" title="Pr&eacute;c&eacute;dent">&lt;</a>' +
			'</div>' +
			'<div id="#{container}-panel-slides-container" class="panel-slides-container">' +
				'<div id="#{container}-slides" class="slides"></div>' +
			'</div>' +
			'<div id="#{container}-panel-btn-next-container" class="panel-btn-next-container">' +
				'<a href="#" id="#{container}-btn-next" class="btn-next" title="Suivant">&gt;</a>' +
			'</div>' +
		'</div>');

		opts.container = $(opts.container);
		opts.container.insert({bottom: panelTemplate.evaluate({container: opts.container.id})});

		this.options.panel            = $(opts.container.id + '-slides');
		this.options.controls.btnPrev = $(opts.container.id + '-btn-prev');
		this.options.controls.btnNext = $(opts.container.id + '-btn-next');

        this.width = opts.width || $(opts.container.parentNode).getWidth() - (this.options.controls.btnPrev.getWidth() + this.options.controls.btnNext.getWidth());

        $(opts.container.id + '-panel-slides-container').setStyle({ width: this.width + 'px' });
	},

    initControls: function()
	{
		var controls = this.options.controls;

		controls.btnPrev.setOpacity(0.5);

        if(2 > this.pages)
        {
            controls.btnNext.setOpacity(0.5);
        }

		controls.btnPrev.observe('click', this.onBtnPrevClickedAction);
		controls.btnNext.observe('click', this.onBtnNextClickedAction);
	},

	renderSlides: function()
	{
		var html          = '';
		var container     = this.options.container;

		var slideTemplate = new Template('<div id="#{container}-slide-container-#{position}" class="slide">' +
			'<div>' +
				'<strong class="slide-title">#{title}</strong>' +
				'<span class="slide-author">#{author}</span>' +
			'</div>' +
			'<div>' +
				'<div class="slide-poster">' +
					'<a href="#{more}" title="D&eacute;couvrir"><img src="#{poster}" alt="#{alt}" /></a>' +
				'</div>' +
				'<div class="slide-links">' +
                    '<table cellpadding="0" cellspacing="0" border="0" width="100%">' +
                        '<tbody>' +
                            '<tr>' +
                                '<td class="slide-category #{cat}">#{category}</td>' +
                            '</tr>' +
                            '<tr>' +
                                '<td>' +
                					'<ul>' +
                						'<li><a href="#{more}" title="D&eacute;couvrir" class="slide-btn-more">&bull; D&eacute;couvrir</a></li>' +
                						'<li><a href="#{more}" id="slide-btn-buy-#{position}" title="Acheter" class="slide-btn-buy btn-buy-widget">&bull; Acheter</a></li>' +
                                        '<li><a href="#{buy_amazon}" title="Acheter" class="slide-btn-buy btn-buy-widget btn-amazon">&bull; Acheter</a></li>' +
                                        '<li><a href="#{buy_fnac}" title="Acheter" class="slide-btn-buy btn-buy-widget btn-fnac">&bull; Acheter</a></li>' +
                                        '<li><a href="#{buy_alapage}" title="Acheter" class="slide-btn-buy btn-buy-widget btn-alapage">&bull; Acheter</a></li>' +
                					'</ul>' +
                                '</td>' +
                            '</tr>' +
                        '</tbody>' +
                     '</table>' +
				'</div>' +
			'</div>' +
		'</div>');

        for(var i=0; i<this.pages; i++)
        {
            $(container.id + '-slides').insert('<div class="slide-page"></div>');
        }

        var pages = $(container.id + '-slides').cleanWhitespace().childElements();
        var p     = -1;
        var max   = this.options.pageItems;

		this.playlist.each(function(slide, pos){

            if(pos % max == 0)
            {
                p = p + 1;
            }

			html = slideTemplate.evaluate({
				container  : container.id,
				position   : slide.position,
				category   : slide.category,
				cat        : slide.cat,
				title      : slide.title,
				alt        : slide.title.stripTags(),
				author     : slide.author,
				poster     : slide.poster,
				more       : slide.links[0].readAttribute('href') || '#',
				buy_amazon : slide.links[1].readAttribute('href') || '#',
                buy_fnac   : slide.links[2].readAttribute('href') || '#',
                buy_alapage: slide.links[3].readAttribute('href') || '#'
			});

            pages[p].insert(html);
		});
	}
});


// ----------------------------

// ----------------------------
// ------ SCROLL PANEL --------
// ----------------------------

UI.ScrollPanel = Class.create(UI.WidgetAbstract,
{
    initialize: function($super, options)
    {
        this.templateHTML = '<div id="#{panel_id}" class="scroll-panel">' +
            '<div id="#{panel_id}-panel-content" class="scroll-panel-content"></div>' +
            '<div id="#{panel_id}-scrollbar" class="scroll-panel-scrollbar">' +
                '<div class="btn-scroll-container">' +
                    '<a href="#" id="#{panel_id}-btn-scroll-prev" class="scroll-panel-btn-scroll-prev" title="monter">Monter</a>' +
                '</div>' +
                '<div id="#{panel_id}-track" class="scroll-panel-scrollbar-track">' +
                    '<div id="#{panel_id}-handle" class="scroll-panel-scrollbar-handle"></div>' +
                '</div>' +
                '<div class="btn-scroll-container">' +
                    '<a href="#" id="#{panel_id}-btn-scroll-next" class="scroll-panel-btn-scroll-next" title="descendre">Descendre</a>' +
                '</div>' +
            '</div>' +
        '</div>';

        var config = {
            containerName: null,
            maxHeight    : 0,
            minHeight    : 0
        };

        this.scroll= null;
        this.loop  = null;
        this.timer = null;

        this.height = 0;

        $super(Object.extend(config, options || {}));

        this.widgetContainer = $(this.options.containerName);

        if(this.widgetContainer && !this.widgetContainer.hasClassName('scroll-panel-container'))
        {
            if(this.needsScrollBar())
            {
                this.height = this.widgetContainer.getHeight();

                this.addWheelEvent();

                this.render();
                this.activate();
            }
            else
            {
                if(0 < this.options.minHeight)
                {
                    this.widgetContainer.setStyle({ height: this.options.minHeight + 'px'});
                }
            }
        }
        else
        {
            this.raiseError('EMPTY_CONTAINER');
        }
    },

    wheelScroll: function(event)
    {
		this.scroll.setValueBy(-Event.wheel(event)*36);
	},

	scrollVertical: function(value)
    {
		var el = this.contentContainer;

		el.scrollTop = Math.round(value/this.scroll.maximum*(el.scrollHeight-el.offsetHeight));
	},

	startScrollUp: function(event)
    {
		event.stop();

		this.scroll.setValueBy(-24);
		this.timer = setTimeout(this.scrollUp.bind(this), 500);
		this.loop  = true;
	},

	scrollUp: function()
    {
		var v = this.scroll.value - 14;

		if(v<0)
        {
			v = 0;

			this.loop = false;
		}

		this.scroll.setValue(v);

		if(this.loop)
        {
			this.timer = setTimeout(this.scrollUp.bind(this), 18);
		}
	},

	startScrollDown: function(event)
    {

		event.stop();

		this.scroll.setValueBy(24);
		this.timer = setTimeout(this.scrollDown.bind(this), 500);
		this.loop  = true;
	},

	scrollDown: function()
    {
		var v   = this.scroll.value + 14;
		var max = this.scroll.maximum;

		if(v>max){
			v = max;
			this.loop = false;
		}

		this.scroll.setValue(v);

		if(this.loop){
			this.timer = setTimeout(this.scrollDown.bind(this), 18);
		}
	},

	stopScroll: function(event)
    {
		event.stop();
		this.loop = false;
		clearTimeout(this.timer);
	},

    addWheelEvent: function()
    {
        if(!Event.wheel)
		{
			Object.extend(Event, {
				wheel:function(event){

					var delta = 0;

					if(!event)
                    {
                        event = window.event;
                    }

					if(event.wheelDelta)
                    {
						delta = event.wheelDelta/120;

						if(window.opera)
                        {
                            delta = -delta;
                        }
					}
                    else if(event.detail)
                    {
                        delta = -event.detail/3;
                    }

					return Math.round(delta);
				}
			});
		}
    },

    needsScrollBar: function()
    {
        var maxHeight = this.options.maxHeight || 0;

        if(0 < maxHeight && this.widgetContainer.getHeight() > maxHeight)
        {
            return true;
        }

        return false;
    },

    render: function()
    {
        var template        = new Template(this.templateHTML);
        var scrollPanelHTML = template.evaluate({ panel_id: this.getWidgetUniqId() });
        var contentHTML     = this.widgetContainer.innerHTML;

        this.widgetContainer.update(scrollPanelHTML);
        this.widgetContainer.addClassName('scroll-panel-container');

        this.contentContainer = $(this.getWidgetUniqId() + '-panel-content');
        this.scrollTrack      = $(this.getWidgetUniqId() + '-track');
        this.scrollHandle     = $(this.getWidgetUniqId() + '-handle');
        this.btnPrev          = $(this.getWidgetUniqId() + '-btn-scroll-prev');
        this.btnNext          = $(this.getWidgetUniqId() + '-btn-scroll-next');

        this.contentContainer.update(contentHTML);
        this.contentContainer.setStyle({ width: this.widgetContainer.getWidth()-12 + 'px' });
        this.contentContainer.setStyle({ height: this.options.maxHeight + 'px', overflow: 'hidden' }).addClassName('scroll-panel-container');

        this.scrollTrack.setStyle({ height: this.options.maxHeight - 40 + 'px' });
    },

    activate: function()
    {
        this.scroll = new Control.Slider(this.scrollHandle, this.scrollTrack, {
			axis:     'vertical',
			range:    $R(0, this.height),
			onSlide:  function(v){ this.scrollVertical(v); }.bind(this),
			onChange: function(v){ this.scrollVertical(v); }.bind(this)
		});

		this.btnPrev.observe("mousedown", this.startScrollUp.bindAsEventListener(this));
		this.btnPrev.observe("mouseup",   this.stopScroll.bindAsEventListener(this));
		this.btnPrev.observe("click",     this.stopScroll.bindAsEventListener(this));
		this.btnPrev.observe("mouseout",  this.stopScroll.bindAsEventListener(this));

		this.btnNext.observe("mousedown", this.startScrollDown.bindAsEventListener(this));
		this.btnNext.observe("mouseup",   this.stopScroll.bindAsEventListener(this));
		this.btnNext.observe("click",     this.stopScroll.bindAsEventListener(this));
		this.btnNext.observe("mouseout",  this.stopScroll.bindAsEventListener(this));

		this.contentContainer.observe("mousewheel", this.wheelScroll.bindAsEventListener(this), false);
		this.contentContainer.observe("DOMMouseScroll", this.wheelScroll.bindAsEventListener(this), false);
    }
});

// ----------------------------


// ----------------------------
// ------ TAB PANEL -----------
// ----------------------------

UI.TabPanel = Class.create(UI.WidgetAbstract,
{
    initialize: function($super, options)
    {
        this.widgetContainer = null;
        this.tabsContainer  = null;
        this.panelsContainer = null;

        this.templateHTML = '<div id="#{tabpanel_id}" class="tab-panel">' +
            '<div id="#{tabpanel_id}-tabs-container" class="tab-panel-tabs-container">' +
                '<ul id="#{tabpanel_id}-tabs-list" class="tab-panel-tabs-list"></ul>' +
            '</div>' +
            '<div id="#{tabpanel_id}-panels-container" class="tab-panel-panels-container"></div>' +
        '</div>';
        this.rendering = false;

        this.tabs   = $A();
        this.panels = $A();

        this.tabsData   = $A();
        this.panelsData = $A();

        this.selected = 0;

        var config = {
            containerName: null,
            duration     : .25,
            maxHeight    : null
        };

        $super(Object.extend(config, options || {}));

        this.widgetContainer = $(this.options.containerName);

        if(this.widgetContainer)
        {
            this.loadDataFromHTML(this.widgetContainer);
            this.render();
            this.activate();
        }
        else
        {
            this.raiseError('EMPTY_CONTAINER');
        }
    },

    onTabClick: function(event, pos)
    {
        event.stop();

        if(!this.rendering && pos != this.selected)
        {
            this.selectTab(pos);
        }
    },

    selectTab: function(pos, effect)
    {
        pos = Math.abs(pos);

        if('undefined' == typeof effect)
        {
            effect = true;
        }

        if(this.tabs[pos] && this.panels[pos])
        {
            if(effect)
            {
                new Effect.Fade(
                    this.panels[this.selected],{
                        duration: this.options.duration,
        				queue   : {
        					position: 'front',
        					scope   : this.getWidgetUniqId() + '-tab-panel',
        					limit   : 2
        				},
                        beforeStart: function(){

                            this.rendering = true;

                        }.bind(this),
                        afterFinish: function(){

                            this.tabs[this.selected].removeClassName('selected');
                            this.tabs[pos].addClassName('selected');

                            this.panels[this.selected].removeClassName('selected');
                            this.panels[pos].addClassName('selected');

                            new Effect.Appear(
                                this.panels[pos], {
                                    duration: this.options.duration,
                    				queue   : {
                    					position: 'end',
                    					scope   : this.getWidgetUniqId() + '-tab-panel',
                    					limit   : 2
                    				},
                                    afterFinish: function(){

                                        this.selected  = pos;
                                        this.rendering = false;

                                    }.bind(this)
                                }
                            );

                        }.bind(this)
                    }
                );
            }
            else
            {
                this.tabs.invoke('removeClassName', 'selected');
                this.panels.invoke('hide');

                this.tabs[pos].addClassName('selected');
                this.panels[pos].show();

                this.panels[this.selected].removeClassName('selected');
                this.panels[pos].addClassName('selected');

                this.selected = pos;
            }
        }
        else
        {
            this.raiseError('POS_OUT_OF_RANGE');
        }
    },

    loadDataFromHTML: function(container)
    {
        var tabs   = this.widgetContainer.select('.tab-panel-tab');
        var panels = this.widgetContainer.select('.tab-panel-panel');

        if(tabs.length && tabs.length == panels.length)
        {
            tabs.each(function(tab){
                this.tabsData.push(tab.innerHTML);
            }.bind(this));

            panels.each(function(panel){
                this.panelsData.push(panel.innerHTML);
            }.bind(this));
        }
        else
        {
            this.raiseError('TABS_PANELS_MISMATCH');
        }
    },

    render: function()
    {
        var template   = new Template(this.templateHTML);
        var tabsData   = this.tabsData;
        var panelsData = this.panelsData;

        var tabPanelHTML = template.evaluate({ tabpanel_id: this.getWidgetUniqId() });
        var tabsHTML     = '';
        var panelsHTML   = '';

        this.widgetContainer.update(tabPanelHTML);

		if(0 < this.options.minHeight)
		{
			this.widgetContainer.setStyle({ height: (this.options.minHeight + 33) + 'px'});
		}

        this.tabsContainer = $(this.getWidgetUniqId() + '-tabs-list');

        if(this.tabsContainer)
        {
            this.panelsContainer = $(this.getWidgetUniqId() + '-panels-container');

            if(this.panelsContainer)
            {
                for(var i=0, len = tabsData.length; i<len; i++)
                {
                    tabsHTML   += '<li>' + tabsData[i] + '</li>';
                    panelsHTML += '<div class="tab-panel">' + panelsData[i] + '</div>';
                }

                this.tabsContainer.update(tabsHTML);
                this.panelsContainer.update(panelsHTML);

                this.tabs = this.tabsContainer.select('a');

                if(0 < this.tabs.length)
                {
                    this.panels = this.panelsContainer.select('.tab-panel');

                    if(0 < this.panels.length)
                    {
                        this.panels.each(function(panel, i){

                            panel.id = this.getWidgetUniqId() + '-scroll-panel' + i;

                            new UI.ScrollPanel({ containerName: panel.id, maxHeight: this.options.maxHeight, minHeight: this.options.minHeight });

                        }.bind(this));

                        this.widgetContainer.insert({ bottom: '<div class="clearer"></div>' });

                        this.selectTab(this.selected, false);
                    }
                    else
                    {
                        this.raiseError('NO_PANELS');
                    }
                }
                else
                {
                    this.raiseError('NO_TABS');
                }
            }
            else
            {
                this.raiseError('PANELS_CONTAINER_NOT_FOUND');
            }
        }
        else
        {
            this.raiseError('TABS_CONTAINER_NOT_FOUND');
        }

        /*

        MUST set this.panelsContainer due to scroll option

        */
    },

    activate: function()
    {
        this.tabs.each(function(tab, pos){
            tab.observe('click', this.onTabClick.bindAsEventListener(this, pos));
        }.bind(this));
    },

    deactivate: function()
    {
        this.tabs.each(function(tab, pos){
            tab.stopObserving('click', this.onTabClick.bindAsEventListener(this, pos));
        }.bind(this));
    }
});

// ----------------------------


// ----------------------------
// ------ BOX -----------------
// ----------------------------


UI.Box = Class.create(UI.WidgetAbstract,
{
    initialize: function($super, options)
    {
        var config = {
            zIndex: 1100,
            bgColor: '#fff'
        };

        this.template = '<div class="box-container">' +
            '<div class="box-top">' +
                '<a href="#" class="btn-box-close" title="Fermer">X</a>' +
                '<div class="box-title"></div>' +
            '</div>' +
            '<div class="box-middle">' +
                '<div class="box-content"></div>' +
            '</div>' +
            '<div class="box-bottom"></div>' +
        '</div>';

        this.boxElement = null;
        this.btnClose   = null;

        $super(Object.extend(config, options || {}));

        this.onWindowResizeAction = this.onWindowResize.bind(this);
        this.onCloseAction        = this.onClose.bindAsEventListener(this);

        this.initBox();

        this.activate();

        this.loadModules();
    },

    onClose: function(event)
    {
        event.stop();

        this.hide();
    },

    onWindowResize: function()
    {
        this.center();
    },

    show: function()
    {
        this.getElement().show();
    },

    hide: function()
    {
        this.getElement().hide();
    },

    center: function()
    {
        var dims = document.viewport.getDimensions();
        var box  = this.getElement().getDimensions();

        this.getElement().setStyle({
            top : Math.round((dims.height-box.height)/2) + 'px',
            left: Math.round((dims.width-box.width)/2)   + 'px'
        });
    },

    resizeTo: function(width, height)
    {
        this.getElement().resizeTo(width, height);
    },

    updateContent: function(html)
    {
        this.content.update(html);
    },

    updateTitle: function(html)
    {
        this.title.update(html);
    },

    initBox: function()
    {
        var boxElement = new Element('div');

        boxElement.identify();
        boxElement.update(this.template);
        boxElement.setStyle({
        position: 'fixed',
        zIndex  : this.options.zIndex || 1100
        });

        $(document.body).insert({bottom: boxElement});

        this.boxElement = boxElement;
        this.title      = this.boxElement.select('.box-title')[0];
        this.content    = this.boxElement.select('.box-content')[0];
        this.btnClose   = this.boxElement.select('.box-top a.btn-box-close')[0];

        this.center();
        this.hide();
    },

    activate: function()
    {
        Event.observe(window, 'resize', this.onWindowResizeAction);

        this.btnClose.observe('click', this.onCloseAction);
    },

    getElement: function()
    {
        return this.boxElement;
    },

    loadModules: function()
    {}
});



// ----------------------------

// ----------------------------
// ------ LIGHTBOX ------------
// ----------------------------

UI.ModalBox = Class.create(UI.Box,
{
    initialize: function($super, options)
    {
        var config = {};

        this.layer = new UI.ModalLayer();

        $super(Object.extend(config, options || {}));

        this.activate();
    },

    onClose: function($super, event)
    {
        $super(event);

        this.hide();
    },

    show: function()
    {
        this.layer.show();
        this.getElement().show();
    },

    hide: function()
    {
        this.getElement().hide();
        this.layer.hide();
    },

    activate: function($super)
    {
        $super();

        //this.layer.getElement().observe('click', this.onCloseAction);
    }
});

// ----------------------------


// ----------------------------
// ------ PHOTO BOX -----------
// ----------------------------

UI.PhotoBox = Class.create(UI.ModalBox,
{
    initialize: function($super, options)
    {
        this.photos = $A();
        this.photo  = null;

        this.btnTemplate = '<div class="btn-#{btn_container}-#{btn_type}">' +
            '<a href="#" title="#{btn_label}">#{btn_label}</a>' +
        '</div>';

        this.infosTemplate = '<div class="btn-#{btn_container}">' +
        '</div>';

        $super(options);

        this.onPhotoSelectedAction  = this.onPhotoSelected.bindAsEventListener(this);
        this.onPhotoClickAction     = this.onPhotoClick.bindAsEventListener(this);
        this.onBtnPrevClickedAction = this.onBtnPrev.bindAsEventListener(this);
        this.onBtnNextClickedAction = this.onBtnNext.bindAsEventListener(this);

        this.initCommands();
        this.initPreviewLinks();
        this.initInfoPanel();

        this.activateModule();
    },

    onPhotoClick: function(event)
    {
        event.stop();

        var element = event.element();

        element.fire('photo:selected');
    },

    onPhotoSelected: function(event)
    {
        event.stop();

        var element = event.element();
        var tagName = element.tagName.toLowerCase();
        var link    = '';

        if('img' == element.tagName.toLowerCase())
        {
            link = $(element.parentNode).readAttribute('href');
        }
        else
        {
            link = element.readAttribute('href');
        }

        if(link)
        {
            var dims = this.content.getDimensions();

            this.updateContent('<div style="width:' + Math.round(dims.width/2) + 'px;height:' + Math.round(dims.height/2) + 'px;padding:' + Math.round((dims.height-31)/2) + 'px 0 0 ' + Math.round((dims.width-31)/2) + 'px;"><img src="/skins/MLP/default/images/loader.gif" alt="Chargement..."/></div>');
            this.infoPanel.update('');

            this.photo = element;

            var photo = new Element('img', {
                src: link + '?t=' + Math.floor(Math.random()*1001),
                'class': 'full-size'
            });

            photo.onload = this.onPhotoReady.bindAsEventListener(this, photo);
        }
    },

    onPhotoReady: function(event, photo)
    {
        var width  = photo.width;
        var height = photo.height;

        this.content.setStyle({
            width : width  + 'px',
            height: height + 'px'
        });

        this.center();

        this.updateContent(photo);
        this.updateInfos(photo);
        this.center();
        this.redrawCommands(width, height);
        this.show();
    },

    onBtnPrev: function(event)
    {
        event.stop();

        var prev = this.getPhotoPosition(this.photo) - 1;

        if(0 > prev)
        {
            prev = this.photos.length - 1;
        }

        this.photos[prev].fire('photo:selected');
    },

    onBtnNext: function(event)
    {
        event.stop();

        var next = this.getPhotoPosition(this.photo) + 1;

        if(this.photos.length <= next)
        {
            next = 0;
        }

        this.photos[next].fire('photo:selected');
    },

    getPhotoPosition: function(photo)
    {
        var pos  = 0;
        var href = '';

        if('img' == photo.tagName.toLowerCase())
        {
            if(photo.hasClassName('full-size'))
            {
                src = photo.src;
            }
            else
            {
                src = photo.up('a').href;
            }
        }
        else
        {
            src = photo.href;
        }

        if(src.indexOf('?'))
        {
            src = src.split('?')[0];
        }

        this.photos.each(function(item, i){

            if('img' == item.tagName.toLowerCase())
            {
                href = item.up('a').href;
            }
            else
            {
                href = item.href;
            }

            if(src == href)
            {
                pos = i;
            }
        });

        return pos;
    },

    updateInfos: function(photo)
    {
        var pos = this.getPhotoPosition(photo);

        this.infoPanel.update(this.photos[pos].up('.photo').select('.photo-description')[0].innerHTML);
        this.infoPanel.hide().setStyle({
            width: photo.width + 'px'
        });

        new Effect.Appear(this.infoPanel, {
            duration:.5
        });
    },

    redrawCommands: function(width, height)
    {
        this.btnClose.clonePosition($(this.content.parentNode), {setWidth: false, setHeight: false});
        this.btnClose.setStyle({left: (width + 30) + 'px', top: '0px'});

        this.btnPrev.clonePosition($(this.content.parentNode), {setWidth: false, setHeight: false});
        this.btnPrev.setStyle({left: '-35px', top: (height/2) + 'px'});

        this.btnNext.clonePosition($(this.content.parentNode), {setWidth: false, setHeight: false});
        this.btnNext.setStyle({left: (width + 30) + 'px', top: (height/2) + 'px'});
    },

    initPreviewLinks: function()
    {
        this.photos = $(this.options.containerName).select('.hd');
        this.zooms  = $(this.options.containerName).select('.btn-hd');
    },

    initCommands: function()
    {
        var element   = this.getElement().select('.box-content')[0];
        var template  = new Template(this.btnTemplate);
        var container = this.options.containerName;

        var prev = template.evaluate({
            btn_container: container,
            btn_type     : 'prev',
            btn_label    : 'Précédent'
        });

        var next = template.evaluate({
            btn_container: container,
            btn_type     : 'next',
            btn_label    : 'Suivant'
        });

        element.insert({
            before: prev,
            after : next + '<div class="clearer"></div>'
        });

        this.btnPrev = element.previousSiblings()[0].select('a')[0];
        this.btnNext = element.nextSiblings()[0].select('a')[0];

        this.redrawCommands(640, 480);
    },

    initInfoPanel: function()
    {
        var element = this.getElement().select('.box-middle')[0];

        element.insert({bottom: '<div class="box-info">Détails</div>'});

        this.infoPanel = element.select('.box-info')[0];
    },

    activateModule: function()
    {
        document.observe('photo:selected', this.onPhotoSelectedAction);

        this.photos.each(function(photo){
            photo.observe('click', this.onPhotoClickAction);
        }.bind(this));

        this.zooms.each(function(zoom){
            zoom.observe('click', this.onPhotoClickAction);
        }.bind(this));

        this.btnPrev.observe('click', this.onBtnPrevClickedAction);
        this.btnNext.observe('click', this.onBtnNextClickedAction);
    }
});

// ----------------------------

// ----------------------------
// ------ MODAL LAYER ---------
// ----------------------------

UI.ModalLayer = Class.create(
{
    initialize: function(options)
    {
        var config = {
            layerName: 'modalLayer',
            bgColor  : '#000',
            opacity  : .75,
            zIndex   : 1000
        };

        this.layerElement = null;

        this.options = Object.extend(config, options || {});

        this.onWindowResizeAction = this.onWindowResize.bind(this);

        this.initLayer();
        this.activate();
    },

    onWindowResize: function()
    {
        this.redraw();
    },

    initLayer: function()
    {
        var layer = new Element('div');

        layer.identify();

        layer.setStyle({
            position  : 'fixed',
            zIndex    : this.options.zIndex,
            top       : 0,
            left      : 0,
            background: this.options.bgColor,
            opacity   : this.options.opacity
        });

        $(document.body).insert({bottom: layer});

        this.layerElement = layer.hide();
    },

    getElement: function()
    {
        return this.layerElement;
    },

    show: function()
    {
        this.redraw();

        this.layerElement.show();
    },

    hide: function()
    {
        this.layerElement.hide();
    },

    redraw: function()
    {
        var dims = document.viewport.getDimensions();

        this.layerElement.setStyle({
            width : dims.width + 'px',
            height: dims.height + 'px'
        });
    },

    activate: function()
    {
        Event.observe(window, 'resize', this.onWindowResizeAction);
    },

    deactivate: function()
    {
        Event.stopObserving(window, 'resize', this.onWindowResizeAction);
    }
});


// ----------------------------


// ----------------------------
// ------ PAGINATED LIST ------
// ----------------------------

UI.PaginatedList = Class.create(UI.WidgetAbstract,
{
    initialize: function($super, options)
    {
        var config = {
            containerName: 'panel',
            itemsByPage  : 10
        };

        this.errors = {
            CONTAINER_NOT_FOUND: 'Le conteneur principal de la liste est introuvable',
            LIST_NOT_FOUND     : 'La liste d\'items introuvable.'
        };

        this.modules = $A();

        this.container        = null;
        this.panelsContainer  = null;
        this.topScrollBar     = null;
        this.topNavigation    = null;
        this.panels           = $A();
        this.bottomNavigation = null;
        this.bottomScrollBar  = null;
        this.items            = $A();
        this.pages            = 0;
        this.active           = 0;
        this.rendering        = true;

        $super(Object.extend(config, options || {}));

        this.container = $(this.options.containerName);

        if(this.container)
        {
			this.showLoader();

            this.initItems();
            this.initPanels();

            this.onGoToPage = this.onGoToPageAction.bindAsEventListener(this);

            this.initNavigations();
            this.initScrollbars();

            this.render();
            this.activate();

            this.loadModules();

			this.hideLoader();

			this.rendering = false;
        }
        else
        {
            this.raiseError('CONTAINER_NOT_FOUND');
        }
    },

    onGoToPageAction: function(event)
    {
        event.stop();

        if(false == this.rendering)
        {
            this.rendering = true;

            var active  = this.active;
            var element = event.element();
            var page    = element.className.split(' ')[0].substring(element.className.indexOf('-') + 1);

			if('prev' == page)
			{
				page = ((active - 1) > 0)? active - 1 : 0;
			}
			else if('next' == page)
			{
				page = ((active + 1) > this.pages - 1)? active : active + 1;
			}
			else if('prev-block' == page)
			{
				page = 	((active - 10) > 0)? active - 10 : 0;
			}
			else if('next-block' == page)
			{
				page = ((active + 10) > this.pages - 1)? this.pages - 1 : active + 10;
			}
			else
			{
				page = parseInt(page);
			}

            if(page != active)
            {
				Event.fire(element, 'scroll:synchronize', { page: page, active: active });

                this.container.select('.navigation-pages-list a').invoke('removeClassName', 'active');
                this.container.select('.navigation-pages-list a.page-' + page).invoke('addClassName', 'active');

                var diff  = active - page;
                var delta = Math.abs(diff) * this.container.getWidth();

                if(active < page)
                {
                    delta = -delta;
                }

                new Effect.Move(
                    this.panelsContainer,
                    {
                        x          : delta,
                        y          : 0,
                        mode       : 'relative',
                        duration   : .5,
						fps        : 60,
						transition : Effect.Transitions.sinoidal,
						queue      : { position: 'front', scope: 'paginatedlist', limit: 1 },
						beforeStart: function(){

						},
                        afterFinish: function(){

                            this.updateInfos(page);

                            this.active    = page;
                            this.rendering = false;

                        }.bind(this)
                    }
                );
            }
            else
            {
                this.rendering = false;
            }
        }
    },

	showLoader: function()
	{
		$(this.container.id + '-list').hide();

        var height  = Math.round((this.container.up('div#main-container').getHeight()-75)/2);
		var loaders = this.container.select('.loader');

		if(0 < loaders.length)
		{
			this.loader = loaders[0];

			this.loader.setStyle({
				height: height + 'px',
				padding: height + 'px 0 0'
			});
		}
        else
        {
            var loader = this.loader = new Element( 'div', { id: this.getWidgetUniqId()  + '-loader', 'class': 'loader', style: 'height:' + height + 'px;padding:' + height + 'px 0 0 0;' });

            loader.update('<img src="/skins/MLP/default/images/loader.gif" alt="Chargement..."/><br /><strong>Création de la liste...</strong>');

    		this.container.insert({	top: loader });
		}
	},

	hideLoader: function()
	{
		var loader = this.loader;

		if(loader)
		{
			loader.remove();
		}
	},

    initItems: function()
    {
        var list = $(this.options.containerName + '-list');

        if(list)
        {
            // overload with items node selection function
            alert('function initItem');
        }
        else
        {
            this.raiseError('LIST_NOT_FOUND');
        }
    },

    initPanels: function()
    {
        var total = this.items.length;
        var max   = this.options.itemsByPage || total;
        var pages = this.pages = Math.ceil(total / max);

        for(var i=0; i<pages; i++)
        {
            var items = [];

            for(j=0; j<max; j++)
            {
                if(this.items[i * max + j])
                {
                    items.push(this.items[i * max + j]);
                }
            }

            this.panels.push(new UI.PaginatedList.Panel(items, this.options.containerName + '-panel-' + i, i));
        }
    },

    initNavigations: function()
    {
		var pagesTotal = this.pages;

        if(pagesTotal > 1)
        {
            this.topNavigation    = new UI.PaginatedList.Navigation(this.container, pagesTotal);
            this.bottomNavigation = new UI.PaginatedList.Navigation(this.container, pagesTotal);
        }
    },

    initScrollbars: function()
    {
		var pagesTotal = this.pages;

        if(pagesTotal > 10)
        {
			this.topScrollBar    = new UI.PaginatedList.Scrollbar(this.container, pagesTotal);
			this.bottomScrollBar = new UI.PaginatedList.Scrollbar(this.container, pagesTotal);
        }
    },

    render: function()
    {
		if(this.topScrollBar)
		{
			this.container.insert(this.topScrollBar.getElement());
		}

		if(this.topNavigation)
		{
			this.container.insert(this.topNavigation.getElement());
		}

		this.container.insert(new Element('div', { id: this.options.containerName + '-infos' }));

		var panelsContainer = new Element('div', { id: this.options.containerName + '-panels-container' });

		var panels          = new Element('div', { id: this.options.containerName + '-panels' });

		this.panels.each(function(panel){

			panels.insert(panel.getElement());

        });

		panelsContainer.insert(panels);

		this.container.insert(panelsContainer);

		this.container.insert(new Element('div', { 'class': 'clearer' }));

		if(this.bottomNavigation)
		{
			this.container.insert(this.bottomNavigation.getElement());
		}

		if(this.bottomScrollBar)
		{
			this.container.insert(this.bottomScrollBar.getElement());
		}

        this.infosContainer  = $(this.options.containerName + '-infos');
        this.panelsContainer = $(this.options.containerName + '-panels');

        this.updateInfos(0);
    },

    activate: function()
    {
         var pages = this.container.select('.navigation-container a');

         pages.each(function(page){
             page.observe('click', this.onGoToPage);
         }.bind(this));

		 document.observe('page:selected', this.onGoToPage);
    },

    updateInfos: function(page)
    {
        if(0 < this.items.length)
        {
            var template = new Template('#{start} à #{end} sur #{total} au total');

            var start = page * this.options.itemsByPage + 1;
            var end   = (page == this.pages - 1)? ((this.items.length - page * this.options.itemsByPage) + ((page) * this.options.itemsByPage)) : start + this.options.itemsByPage - 1;

            this.infosContainer.update(template.evaluate({start: start, end: end, total: this.items.length}));
        }
        else
        {
            this.infosContainer.update('Aucun résultat...');
        }
    },

    loadModules: function()
    {}
});


// ------ NAVIGATION ------

UI.PaginatedList.Navigation = Class.create(UI.WidgetAbstract,
{
	initialize: function($super, container, totalPages)
	{
        this.container  = container;
		this.totalPages = totalPages;

		$super();

		this.widgetContainer = new Element('div', { id: this.getWidgetUniqId('navigation'), 'class': 'navigation-container' });

		this.render();

		this.activate();
	},

	refresh: function(event)
	{
		var page   = event.memo.page;
		var active = event.memo.active;
		var delta  = 0;

		var diff = Math.abs(page - active);

		if(page > 5 && page < this.totalPages-5)
		{
			delta = -21 *(page-5) + 1;

            new Effect.Move(this.pagesContainer, {
				x          : delta,
				y          : 0,
				duration   :.2,
				fps        : 10,
				transition : Effect.Transitions.linear,
				queue      : { position: 'front', scope: this.getWidgetUniqId() + 'queue', limit: 1 },
				mode: 'absolute'
			});
		}
		else
		{
            if(page <= 5)
            {
                if(page < active)
                {
                    this.pagesContainer.setStyle({ left: '0px' });
                }
            }

            if(page >= this.totalPages-5)
            {
                this.pagesContainer.absolutize().setStyle({ left: -(this.totalPages-11) * 21 + 'px' });
            }
		}
	},

	getElement: function()
	{
		return this.widgetContainer;
	},

	render: function()
	{
		var className    = '';
		var templateHTML = '<div class="navigation-container-block"><a href="#" class="page-0 first" title="Première page">|&lt;</a></div>' +
		'<div class="navigation-container-block"><a href="#" class="page-prev-block" title="Revenir de 10 pages">&lt;&lt;</a></div>' +
		'<div class="navigation-container-block"><a href="#" class="page-prev" title="Page précédente">&lt;</a></div>' +
		'<div class="navigation-container-block navigation-pages-list">' +
			'<ul>';

				for(var i=0; i<this.totalPages; i++)
				{
					if(0 == i)
					{
						className = 'page-0 active';
					}
					else
					{
						className = 'page-' + i;
					}

					templateHTML += '<li><a href="#" class="' + className + '" title="Se rendre à la page ' + (i+1) + '">' + (i+1) + '</a></li>';
				}

				templateHTML += '</ul>' +
		'</div>' +
		'<div class="navigation-container-block"><a href="#" class="page-next" title="Page suivante">&gt;</a></div>' +
		'<div class="navigation-container-block"><a href="#" class="page-next-block" title="Avancer de 10 pages">&gt;&gt;</a></div>' +
		'<div class="navigation-container-block"><a href="#" class="page-' + (this.totalPages-1) + ' last" title="Dernière page">&gt;|</a></div>' +
		'<div class="clearer"></div>';

        this.widgetContainer.update(templateHTML);

        this.container.insert(this.widgetContainer);

		var pieces = this.widgetContainer.childElements();

		this.btnFirstPage   = pieces[0].select('a')[0];
		this.btnPrevBlock   = pieces[1].select('a')[0];

		this.pagesContainer = pieces[3].select('ul')[0];

		this.btnNextBlock   = pieces[5].select('a')[0];
		this.btnLastPage    = pieces[6].select('a')[0];

		if(11 >= this.totalPages)
		{
			this.btnFirstPage.hide();
			this.btnPrevBlock.hide();
			this.btnNextBlock.hide();
			this.btnLastPage.hide();

			this.widgetContainer.addClassName('short');
		}

		if(11 >= this.totalPages)
		{
			this.btnFirstPage.hide();
			this.btnLastPage.hide();
		}
	},

	activate: function()
	{
        if(this.totalPages > 11)
        {
            document.observe('scroll:synchronize', this.refresh.bindAsEventListener(this));
        }
	}
});


// ------ SCROLLBAR ------

UI.PaginatedList.Scrollbar = Class.create(UI.WidgetAbstract,
{
    initialize: function($super, container, totalPages)
    {
		this.container  = container;
		this.totalPages = totalPages;

		this.onSlideAction  = this.onSlide.bind(this);
		this.onChangeAction = this.onChange.bind(this);

		$super();

		this.widgetContainer = new Element('div', { id: this.getWidgetUniqId('scrollbar'), 'class': 'scrollbar-container' });

		this.render();

		this.activate();
    },

	onSlide: function(h)
	{
		Event.fire(this.container.select('a.page-' + h)[0], 'page:selected', { page: h});
	},

	onChange: function(h)
	{
		Event.fire(this.container.select('a.page-' + h)[0], 'page:selected', { page: h});
	},

	getElement: function()
	{
		return this.widgetContainer;
	},

	render: function()
	{
		var templateHTML = '<div id="' + this.getWidgetUniqId() + '-navigation-scrollbar-container" class="navigation-scrollbar-container">' +
			'<div id="' + this.getWidgetUniqId() + '-navigation-scrollbar-track" class="navigation-scrollbar-track">' +
				'<div id="' + this.getWidgetUniqId() + '-navigation-scrollbar-handle" class="navigation-scrollbar-handle"></div>' +
			'</div>' +
		'</div>';

		this.widgetContainer.update(templateHTML);

		this.container.insert(this.widgetContainer);

		this.scrollTrack  = this.widgetContainer.select('.navigation-scrollbar-track')[0];
		this.scrollHandle = this.widgetContainer.select('.navigation-scrollbar-handle')[0];
	},

	activate: function()
	{
		this.scroll = new Control.Slider(this.getWidgetUniqId() + '-navigation-scrollbar-handle', this.getWidgetUniqId() + '-navigation-scrollbar-track', {
			axis     : 'horizontal',
			range    : $R(0, this.totalPages-1),
			values   : $R(0, this.totalPages-1),
			increment: 1,
			onSlide  : this.onSlide.bind(this),
			onChange : this.onChange.bind(this) //function(v){ this.onChangeAction(v); }.bind(this)
		});

		document.observe('scroll:synchronize', this.updateHandlePosition.bindAsEventListener(this));
	},

	updateHandlePosition: function(event)
	{
		var page = event.memo.page;

		if(page != this.scroll.value)
		{
			this.scroll.setValue(page);
		}
	}
});


// ------ PANEL ------

UI.PaginatedList.Panel = Class.create(UI.WidgetAbstract,
{
    initialize: function($super, items, id, pos)
    {
        this.id    = id;
        this.pos   = pos;
        this.items = items;

		$super();

		this.widgetContainer = new Element('div', { id: this.id, 'class': this.id.substr(0, this.id.indexOf('-')) + '-panel' });

		this.render();
    },

	getElement: function()
	{
		return this.widgetContainer;
	},

    render: function()
    {
        var html = '';

        this.items.each(function(item){
           html += item.render();
        });

        this.widgetContainer.update(html);
    }
});


// ------ ITEM ------

UI.PaginatedList.ListItem = Class.create( // Abstract Class
{
    data    : {},
    template: null,

    initialize: function(element)
    {
        if(this.template)
        {
            this.template = new Template(this.template);

            this.loadItemData(element);
        }
        else
        {
            UI.PaginatedList.raiseError('LIST_NOT_FOUND')
        }
    },

    loadItemData: function(element)
    {
        // overload with costum data processiong from DOM element
		alert('Extract data from HTML tags to feed the item template');
    },

    render: function()
    {
        var html = this.template.evaluate(this.data);

        return html;
    }
});


// ----------------------------
