Object.extend(

    document.viewport,

    {

        getPageSize : function()

        {

        var xScroll, yScroll, windowWidth, windowHeight, pageHeight, pageWidth;



            if (window.innerHeight && window.scrollMaxY) {

                xScroll = document.body.scrollWidth;

                yScroll = window.innerHeight + window.scrollMaxY;

            }

            else if (document.body.scrollHeight > document.body.offsetHeight) { //all but Explorer Mac

                xScroll = document.body.scrollWidth;

                yScroll = document.body.scrollHeight;

            }

            else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari

                xScroll = document.body.offsetWidth;

                yScroll = document.body.offsetHeight;

            }



            if (self.innerHeight) { // all except Explorer

                windowWidth = self.innerWidth;

                windowHeight = self.innerHeight;

            }

            else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode

                windowWidth = document.documentElement.clientWidth;

                windowHeight = document.documentElement.clientHeight;

            }

            else if (document.body) { // other Explorers

                windowWidth = document.body.clientWidth;

                windowHeight = document.body.clientHeight;

            }



            // for small pages with total w/h less then w/h of the viewport

            pageHeight = (yScroll < windowHeight) ? windowHeight : yScroll;

            pageWidth  = (xScroll < windowWidth)  ? windowWidth  : xScroll;



            return [

                pageWidth, pageHeight, windowWidth, windowHeight

            ];

        }

    }

);



var ProtoBox = Class.create();

ProtoBox.prototype = {

    initialize : function(options)

    {

        this.options = Object.extend(

            {

                hide_flash   : true,

                loading_img  : 'images/loading.gif',

                close_img    : 'images/closelabel.gif',

                rel          : 'lightbox',

                my_id        : 'lightbox',

                protect      : true,



                force_update : false,



                max_width    : 0,

                max_height   : 0,



                ring         : true,

                drag         : true,



                overlay      : null,

                overlay_id   : 'overlay',

                ovl_opacity  : 0.8,

                ovl_speed    : 0.2,



                animate      : true,

                speed        : 6

            },

            options || {}

        );



        this.listening_kd = false;

        this._keydown     = this._onKeyDown.bindAsEventListener(this);



        this.body    = $$('body')[0];

        this.overlay = $(this.options.overlay);

        if (null == this.overlay) {

            this.overlay = $(document.createElement('div'));

            this.overlay.setAttribute('id', this.options.overlay_id);

            this.overlay.style.display = 'none';

            this.body.appendChild(this.overlay);

        }



        this.overlay.observe('click', this._closeSelf.bindAsEventListener(this));



        if (false == this.options.animate) {

            this.resize_duration = 0;

        }

        else {

            if (this.options.speed > 10) {

                this.options.speed = 10;

            }



            if (this.options.speed < 1) {

                this.options.speed = 1;

            }



            this.resize_duration = 0.1 * (11 - this.options.speed);

        }



        this.act_rel = '';

        this.active  = -1;

        this.images  = {};

        this._buildLayout();

        this.updateImageList();

    },

    _buildLayout : function()

    {

        this.myself = $(Builder.node('div', { id : this.options.my_id }, [

            Builder.node('div', { 'class' : 'imageContainer' }, [

                Builder.node('img', { alt : '',  src : '' }),

                Builder.node('div', { 'class' : ((true == this.options.protect) ? 'protector' : '') }),

                Builder.node('a', { href : 'javascript:void(0)', 'class' : 'prevLink' }),

                Builder.node('a', { href : 'javascript:void(0)', 'class' : 'nextLink' }),

                Builder.node('div', { 'class' : 'loading' }, [

                    Builder.node('img', { alt : 'Loading...',  src : this.options.loading_img })

                ]),

            ]),

            Builder.node('div', { 'class' : 'imageDataContainer' }, [

                Builder.node('div', { 'class' : 'imageDetails' }, [

                    Builder.node('div', { 'class' : 'caption' }),

                    Builder.node('div', { 'class' : 'numberDisplay' })

                ]),

                Builder.node('img', { 'class' : 'bottomNavClose', alt : 'Close', src : this.options.close_img })

            ])

        ]));



        if (window.external && ('undefined' == typeof window.XMLHttpRequest) && document.all && -1 == navigator.userAgent.toLowerCase().indexOf('opera')) {

            var iframe = document.createElement('iframe');

            iframe.className = 'ie_iframe';

            iframe.frameBorder = 0;

            this.myself.appendChild(iframe);

        }



        this.myself.setStyle({ display : 'none' });

        if (false == this.options.drag) {

            this.myself.observe('click', this._closeSelf.bindAsEventListener(this));

        }



        this.body.appendChild(this.myself);



        this.imageContainer     = this.myself.down();

        this.imageDataContainer = this.imageContainer.next();

        this.the_image          = this.imageContainer.down();

        this.prevLink           = this.the_image.next().next();

        this.nextLink           = this.prevLink.next();

        this.loading            = this.nextLink.next();

        this.loadingLink        = this.loading.down();

        var imageDetails        = this.imageDataContainer.down();

        this.bottomNavClose     = imageDetails.next();

        this.caption            = imageDetails.down();

        this.numberDisplay      = this.caption.next();



        if (this.options.animate) {

            this.imageContainer.setStyle( { width : '250px', height : '250px' } );

            this.imageDataContainer.setStyle( { width : '250px' } );

        }

        else {

            this.imageContainer.setStyle( { width : '40px', height : '40px' } );

            this.imageDataContainer.setStyle( { width : '40px' } );

        }



        if (this.options.drag) {

            new Draggable(this.myself, { handle : this.imageContainer, onEnd : this._fixOverlay.bind(this) });

            this.imageContainer.style.cursor = 'move';

        }



        this.prevLink.observe('click', this._prev.bindAsEventListener(this));

        this.nextLink.observe('click', this._next.bindAsEventListener(this));



        [this.loadingLink, this.bottomNavClose].invoke('observe', 'click', this._closeSelf.bindAsEventListener(this));

    },

    _fixOverlay : function()

    {

        var ow = document.documentElement.offsetWidth;

        var oh = document.documentElement.offsetHeight;

        var sw = document.documentElement.scrollWidth;

        var sh = document.documentElement.scrollHeight;



        if (ow > sw) {

            sw = ow;

        }



        if (oh > sh) {

            sh = oh;

        }



        this.overlay.setStyle({ width : sw + 'px', height : sh + 'px' });

    },

    _closeSelf : function(e)

    {

        e.stop();

        this._end();

    },

    _startShow : function(e)

    {

        e.stop();

        if (true == this.options.force_update) {

            this.updateImageList();

        }



        this._start(e.findElement('a'));

    },

    updateImageList : function()

    {

        this.images  = [];

        this.active  = -1;

        this.act_rel = null;



        $$('a[rel^=' + this.options.rel + ']', 'area[rel^=' + this.options.rel + ']').each(

            function(node)

            {

                var rel   = node.getAttribute('rel') || this.options.rel;

                var href  = node.getAttribute('href') || '';

                var title = node.getAttribute('title') || '';



                if (-1 != rel.indexOf('[')) {

                    if ('undefined' == typeof this.images[rel]) {

                        this.images[rel] = [];

                    }



                    this.images[rel].push({ 'href' : href, 'title' : title });

                }



                if (!node.protoboxed) {

                    node.observe('click', this._startShow.bindAsEventListener(this));

                    node.protoboxed = true;

                }

            }.bind(this)

        );

    },

    _start : function(element)

    {

        this._hideFlash();



        var dims    = document.viewport.getDimensions();

        var scrolls = document.viewport.getScrollOffsets();



        new Effect.Appear(

            this.overlay,

            {

                duration : this.options.ovl_speed,

                from     : 0,

                to       : this.options.ovl_opacity

            }

        );



        var rel   = element.getAttribute('rel');

        this.href = element.getAttribute('href');

        var title = element.getAttribute('title');

        var idx   = -1;



        if (-1 != rel.indexOf('[')) {

            if ('undefined' == typeof this.images[rel]) {

                this.images[rel] = [{ 'href' : href, 'title' : title }];

            }

            else {

                var a = this.images[rel];

                var l = a.length;

                for (var i=0; i<l; ++i) {

                    if (a[i].href == this.href) {

                        idx = i;

                        break;

                    }

                }



                if (-1 == idx) {

                    idx = l;

                    a.push(this.href);

                }

            }

        }

        else {

            rel = title;

        }



        var top  = scrolls.top + dims.height / 15;

        var left = scrolls.left;



        this.myself.setStyle({ 'left' : left + 'px', 'top' : top + 'px' })

        this.myself.show();



        this._changeImage(rel, idx);

    },

    _end : function()

    {

        this._disableKeyboardNav();

        this.myself.hide();

        new Effect.Fade(this.overlay, { duration: this.options.ovl_speed });

        this._showFlash();

    },

    _changeImage : function(rel, idx)

    {

		this.imageContainer.setStyle( { width : '250px', height : '250px' } );

		this.imageDataContainer.setStyle( { width : '250px' } );

        this.act_rel = rel;

        this.active  = idx;

        if (this.options.animate) {

            this.loading.show();

        }



        [this.the_image, this.prevLink, this.nextLink, this.imageDataContainer, this.numberDisplay].invoke('hide');



        imgPreloader = new Image();



        imgPreloader.onload = function()

        {

            imgPreloader.onload = null;



            if (window.external && ('undefined' == typeof window.XMLHttpRequest) && document.all && -1 == navigator.userAgent.toLowerCase().indexOf('opera')) {

                $(this.the_image).onload = function()

                {

                    $(this.the_image).onload = null;

                    var w = imgPreloader.width;

                    var h = imgPreloader.height;

                    var r;



                    if (0 != this.options.max_width) {

                        r  = this.options.max_width/w;

                        w  = this.options.max_width;

                        h *= r;

                    }



                    if (0 != this.options.max_height) {

                        r  = this.options.max_height/h;

                        h  = this.options.max_height;

                        w *= r;

                    }



                    $(this.the_image).setStyle({ width : w + 'px', height : h + 'px' });

                    this._resizeImageContainer(w, h);

                }.bindAsEventListener(this);



                $(this.the_image).setAttribute('src', imgPreloader.src);

            }

            else {

                $(this.the_image).setAttribute('src', imgPreloader.src);



                var w = imgPreloader.width;

                var h = imgPreloader.height;

                var r;



                if (0 != this.options.max_width) {

                    r  = this.options.max_width/w;

                    w  = this.options.max_width;

                    h *= r;

                }



                if (0 != this.options.max_height) {

                    r  = this.options.max_height/h;

                    h  = this.options.max_height;

                    w *= r;

                }



                $(this.the_image).setStyle({ width : w + 'px', height : h + 'px' });

                this._resizeImageContainer(w, h);

            }

        }.bindAsEventListener(this);



        imgPreloader.setAttribute('src', ((this.active < 0) ? this.href : this.images[rel][idx].href));

    },

    _resizeImageContainer : function(w, h)

    {

		

        var width_current  = this.imageContainer.getWidth();

        var height_current = this.imageContainer.getHeight();

		



        var width_new  = w;

        var height_new = h;



        var x_scale = width_new / width_current * 100;

        var y_scale = height_new / height_current * 100;



        var w_diff = width_current - width_new;

        var h_diff = height_current - height_new;



        if (0 != h_diff) {

            new Effect.Scale(

                this.imageContainer,

                y_scale,

                {

                    scaleX   : false,

                    duration : this.resize_duration,

                    queue    : 'front'

                }

            );

        }



        if (0 != w_diff) {

            new Effect.Scale(

                this.imageContainer,

                x_scale,

                {

                    scaleY   : false,

                    duration : this.resize_duration,

                    delay    : this.resize_duration

                }

            );



            this.imageDataContainer.setStyle( { width : width_new + 'px' } );

        }



        if (0 == h_diff && 0 == w_diff) {

            this._pause(

                (-1 != navigator.appVersion.indexOf("MSIE")) ? 250 : 100

            );

        }



        this.prevLink.style.height = h + 'px';

        this.nextLink.style.height = h + 'px';

        this.imageDataContainer.style.width = w + 'px';

        this._showImage();

    },

    _showImage: function()

    {

        if (this.active >= 0) {

            if (this.images[this.act_rel].length - 1 > this.active) {

                var p_next = new Image();

                p_next.src = this.images[this.act_rel][this.active + 1].href;

            }



            if (this.active > 0) {

                var p_prev = new Image();

                p_prev.src = this.images[this.act_rel][this.active - 1].href;

            }

        }



        this.loading.hide();

        new Effect.Appear(

            this.the_image,

            {

                duration    : this.resize_duration,

                queue       : 'end',

                afterFinish : this._updateDetails.bind(this)

            }

        );

    },

    _updateDetails : function()

    {

        if (this.active >= 0) {

            var e = this.images[this.act_rel][this.active];

            if ('' != e.title){

                this.caption.update(e.title);

                this.caption.show();

            }



            if (this.images[this.act_rel].length && this.images[this.act_rel].length > 1) {

                this.numberDisplay.update("Image " + (this.active + 1) + " of " + this.images[this.act_rel].length);

                this.numberDisplay.show();

            }

        }

        else {

            if ('' != this.act_rel){

                this.caption.update(this.act_rel);

                this.caption.show();

            }

        }



        new Effect.Parallel(

            [

                new Effect.SlideDown(this.imageDataContainer, { sync: true, duration: this.resize_duration, from: 0.0, to: 1.0 }),

                new Effect.Appear(this.imageDataContainer, { sync: true, duration: this.resize_duration })

            ],

            {

                duration    : this.resize_duration,

                afterFinish : this._updateNav.bind(this)

            }

        );

    },

    _prev : function(e)

    {

        Event.stop(e);

        this.__prev();

    },

    __prev : function()

    {

        if (this.active > 0) {

            this._changeImage(this.act_rel, this.active - 1);

        }

        else if (true == this.options.ring && 0 == this.active) {

            this._changeImage(this.act_rel, this.images[this.act_rel].length - 1);

        }

    },

    _next : function(e)

    {

        Event.stop(e);

        this.__next();

    },

    __next : function()

    {

        if (this.active >= 0) {

            if (this.active != this.images[this.act_rel].length - 1) {

                this._changeImage(this.act_rel, this.active + 1);

            }

            else if (true == this.options.ring) {

                this._changeImage(this.act_rel, 0);

            }

        }

    },

    _updateNav: function()

    {

        if (this.active >= 0) {

            if (this.active > 0 || true == this.options.ring) {

                this.prevLink.show();

            }



            if (this.active != this.images[this.act_rel].length - 1 || true == this.options.ring) {

                this.nextLink.show();

            }

        }



        this._fixOverlay();

        this._enableKeyboardNav();

    },

    _enableKeyboardNav : function()

    {

        if (false == this.listening_kd) {

            this.listening_kd = true;

            Event.observe(document, 'keydown', this._keydown);

        }

    },

    _disableKeyboardNav : function()

    {

        if (true == this.listening_kd) {

            this.listening_kd = false;

            Event.stopObserving(document, 'keydown', this._keydown);

        }

    },

    _onKeyDown : function(e)

    {

        var keycode = e.keyCode;

        var key     = String.fromCharCode(keycode).toLowerCase();



        if ('x' == key || 'c' == key || 'o' == key || Event.KEY_ESC == keycode) {

            this._end();

        }

        else if ('p' == key || Event.KEY_LEFT == keycode) {

            this._disableKeyboardNav();

            this.__prev();

        }

        else if ('n' == key || Event.KEY_RIGHT == keycode) {

            this._disableKeyboardNav();

            this.__next();

        }

    },

    _hideFlash : function()

    {

        if (true == this.options.hide_flash) {

            this.all_flash = $$("object", "embed", "iframe").select(

                function(node)

                {

                    if ('visible' == node.getStyle('visibility')) {

                        node.style.visibility = 'hidden';

                        return true;

                    }

					var flashEmbeds = document.getElementsByTagName("object");

					for (i = 0; i < flashEmbeds.length; i++) {

						flashEmbeds[i].style.visibility = "hidden";

					}

					var iframeEmbeds = document.getElementsByTagName("iframe");

					for (i = 0; i < iframeEmbeds.length; i++) {

						iframeEmbeds[i].style.visibility = "hidden";

					}

                    return false;

                }

            ) || [];

        }

    },

    _showFlash : function()

    {

        if (true == this.options.hide_flash) {

            this.all_flash.invoke('setStyle', { visibility : 'visible' });

            this.all_flash = [];

			

			var flashEmbeds = document.getElementsByTagName("object");

			for (i = 0; i < flashEmbeds.length; i++) {

				flashEmbeds[i].style.visibility = "visible";

			}

			var iframeEmbeds = document.getElementsByTagName("iframe");

			for (i = 0; i < iframeEmbeds.length; i++) {

				iframeEmbeds[i].style.visibility = "visible";

			}

        }

    },

    _pause : function(ms)

    {

        var date    = new Date();

        var curDate = null;

        do {

            curDate = new Date();

        } while (curDate - date < ms);

    }

};



var myLightbox;



function initLightbox(options)

{

    myLightbox = new ProtoBox(options);

}

