
function ImageViewer(id, minWidth, minHeight) {
    
    this.element = document.createElement('div');
    this.element.id = id;
    
    this.element.slideInterval         = 7; // In Seconds
    this.element.minWidth              = minWidth;
    this.element.maxWidth              = '1900px';
    this.element.minHeight             = minHeight;
    this.element.maxHeight             = Math.round(1900 * .75) + 'px';
    this.element.style.display         = 'none';
    this.element.curImage              = null;
    this.element.curSlide              = 0;
    this.element.newImage              = null;
    this.element.slideTimeout          = null;
    this.element.transitionType        = 'none';
    this.element.imagesArray           = new Array();
    this.element.curLoad               = 0;

    this.element.imageHolder           = document.createElement('div');
    this.element.imageHolder.id        = id + 'ImageHolder';

    this.element.imageHolder.setDimensions(minWidth + 'px', minHeight + 'px');
    this.element.imageHolder.style.overflow = 'hidden';

    this.element.imageHolder.setViewerDimensions = function(minWidth, minHeight) {
        this.parentNode.minWidth = minWidth;
        this.parentNode.minHeight = minHeight;
        this.style.width = minWidth;
        this.style.height = minHeight;
    };

    this.element.appendChild(this.element.imageHolder);

    this.element.controls = new Array();
    
    this.element.controls['zoom']                       = new Element('div', id + 'ZoomControlsHolder');
    this.element.controls['zoom'].style.display         = 'none';
    this.element.controls['zoom'].style.width           = '24px';
    this.element.controls['zoom'].style.height          = '58px';
    this.element.controls['zoom'].style.left            = '10px';
    this.element.controls['zoom'].style.top             = '10px';

    this.element.controls['zoom'].zoomIn                = new Element('img', id + 'ZoomInControl');
    this.element.controls['zoom'].zoomIn.src            = 'images/graphics/zoom_in.png';
    this.element.controls['zoom'].zoomIn.style.left     = '0px';
    this.element.controls['zoom'].zoomIn.style.top      = '0px';
    this.element.controls['zoom'].zoomIn.style.cursor   = 'pointer';
    this.element.controls['zoom'].zoomIn.onmousedown    = function() {
        this.parentNode.parentNode.zoomIn(100, false);
    }
    this.element.controls['zoom'].zoomIn.onmouseup      = function() {
        this.parentNode.parentNode.stopZoom();
    }
    this.element.controls['zoom'].zoomIn.onmouseout     = function() {
        this.parentNode.parentNode.stopZoom();
    }
    this.element.controls['zoom'].zoomIn.ondblclick     = function() {
        this.parentNode.parentNode.zoomIn(0, true);
    }
    this.element.controls['zoom'].appendChild(this.element.controls['zoom'].zoomIn);

    this.element.controls['zoom'].zoomOut               = new Element('img', id + 'ZoomOutControl');
    this.element.controls['zoom'].zoomOut.src           = 'core/images/graphics/zoom_out.png';
    this.element.controls['zoom'].zoomOut.style.left    = '0px';
    this.element.controls['zoom'].zoomOut.style.top     = '34px';
    this.element.controls['zoom'].zoomOut.style.cursor  = 'pointer';
    this.element.controls['zoom'].zoomOut.style.display = 'none';
    this.element.controls['zoom'].zoomOut.onmousedown   = function() {
        this.parentNode.parentNode.zoomOut(100, false);
    }
    this.element.controls['zoom'].zoomOut.onmouseup     = function() {
        this.parentNode.parentNode.stopZoom();
    }
    this.element.controls['zoom'].zoomOut.onmouseout    = function() {
        this.parentNode.parentNode.stopZoom();
    }
    this.element.controls['zoom'].zoomOut.ondblclick    = function() {
        this.parentNode.parentNode.zoomOut(0, true);
    }
    this.element.controls['zoom'].appendChild(this.element.controls['zoom'].zoomOut);
    this.element.appendChild(this.element.controls['zoom']);

    this.element.controls['close'] = new Element('img', id + 'CloseControl');
    this.element.controls['close'].style.display = 'none';
    this.element.controls['close'].src = 'images/graphics/close.png';
    this.element.controls['close'].style.left = '0px';
    this.element.controls['close'].style.top = '0px';
    this.element.controls['close'].style.cursor = 'pointer';
    this.element.controls['close'].onmousedown = function() {
        this.parentNode.close();
    }
    this.element.controls['close'].style.left = ((parseInt(minWidth) + 88) - 34) + 'px';
    this.element.controls['close'].style.top = '10px';
    this.element.appendChild(this.element.controls['close']);

    this.element.controls['slide'] = new Element('div', id + 'SlideControls');
    this.element.controls['slide'].style.display = 'none';
    this.element.controls['slide'].prevSlide = new Element('img', id + 'PrevControl');
    this.element.controls['slide'].prevSlide.src = '';
    this.element.controls['slide'].prevSlide.onmousedown = function() {
        this.parentNode.parentNode.setImage("previous");
    }
    this.element.controls['slide'].pauseSlide = new Element('img', id + 'PauseControl');
    this.element.controls['slide'].pauseSlide.src = '';
    this.element.controls['slide'].pauseSlide.onmousedown = function() {
        this.parentNode.parentNode.pause();
    }
    this.element.controls['slide'].playSlide = new Element('img', id + 'PlayControl');
    this.element.controls['slide'].playSlide.src = '';
    this.element.controls['slide'].playSlide.onmousedown = function() {
        this.parentNode.parentNode.play();
    }
    this.element.controls['slide'].nextSlide = new Image();
    this.element.controls['slide'].nextSlide.id = id + 'NextControl';
    this.element.controls['slide'].nextSlide.src = '';
    this.element.controls['slide'].nextSlide.onmousedown = function() {
        this.parentNode.parentNode.setImage("next");
    }
    this.element.controls['slide'].appendChild(this.element.controls['slide'].prevSlide);
    this.element.controls['slide'].appendChild(this.element.controls['slide'].pauseSlide);
    this.element.controls['slide'].appendChild(this.element.controls['slide'].playSlide);
    this.element.controls['slide'].appendChild(this.element.controls['slide'].nextSlide);
    this.element.appendChild(this.element.controls['slide']);

    this.element.loadingContainer = new LoadingBar(id + 'LoadingContainer');
    this.element.loadingContainer.style.top = Math.round((parseInt(screenHeight) - 60) / 2) + 'px';
    this.element.loadingContainer.style.left = Math.round(((parseInt(minWidth) + 88) - 270) / 2) + 'px';
    this.element.appendChild(this.element.loadingContainer);

    this.element.tempContainer = new Element('div', id + 'TempContainer');
    this.element.tempContainer.style.display = 'none';
    this.element.appendChild(this.element.tempContainer);

    this.element.addImage = function(image) {
        this.newImage = image
        this.newImage.style.left = '0px';
        this.newImage.style.top = '0px';
        this.newImage.style.width = this.minWidth;
        this.newImage.style.height = this.minHeight;
        this.newImage.setOpacity(0);
        this.newImage.style.display = 'none';
        this.newImage.maxleftfollow = 0;
        this.newImage.maxtopfollow = 0;
        this.newImage.onmousedown = function() {
            this.parentNode.parentNode.pause();
            this.followLeft(((mouseX - parseInt(this.style.left)) * -1));
            this.followTop(((mouseY - parseInt(this.style.top)) * -1));
        }
        this.newImage.onmouseup = function() {
            clearTimeout(this.followTopTimeout);
            clearTimeout(this.followLeftTimeout);
        }
        this.newImage.followtopcond = function() {
            return mTarget.id == this.id;
        }
        this.newImage.followleftcond = function() {
            return mTarget.id == this.id;
        }
        this.imagesArray[this.imagesArray.length] = this.newImage;
        this.imageHolder.appendChild(this.newImage);
    }

    this.element.loadSlideShow = function(imagesArray) {
        if (imagesArray != null) {
            this.curLoad = 0;
            this.curImage = null;
            this.loadingContainer.style.display = 'block';
            this.imageHolder.style.display = 'none';
            this.namesArray = imagesArray;
            while (this.imageHolder.childNodes.length > 0) {
                this.imageHolder.removeChild(this.imageHolder.firstChild);
            }
        }
        loadPercent = Math.round((this.curLoad / this.namesArray.length) * 100) + '%';
        loadString = this.curLoad == this.namesArray.length ? 'Done Loading' : 'Loading Image ' + (this.curLoad + 1) + ' of ' + this.namesArray.length;
        this.loadingContainer.update(loadPercent, loadString);
        if (this.curLoad < this.namesArray.length) {
            this.newImage = new Element('img', this.id + 'SlideImage' + this.curLoad);
            this.newImage.style.display = 'none';
            this.tempContainer.appendChild(this.newImage);
            this.newImage.onload = function() {
                this.parentNode.parentNode.curLoad++;
                this.parentNode.parentNode.slideShowLoadTimeout = setTimeout("document.getElementById('" + this.parentNode.parentNode.id + "').loadSlideShow(null);", 50);
                this.parentNode.parentNode.addImage(this);
            }
            this.newImage.src = this.namesArray[this.curLoad];
        } else {
            if (!browserIs("MSIE")) {
                this.loadingContainer.onfade = function() {
                    this.style.display = 'none';
                    this.cleanUp();
                    this.setOpacity(100);
                }
                this.loadingContainer.fadeOpacity(0, 30);
            } else {
                this.loadingContainer.style.display = 'none';
                this.loadingContainer.cleanUp();
            }
            this.imageHolder.style.display = 'block';
            this.curLoad = 0;
            this.curSlide = 0;
            this.curImage = this.imageHolder.firstChild;
            this.curImage.setOpacity(100);
            this.curImage.style.display = 'block';
            this.play();
        }
    }

    this.element.setImage = function(imageIndex) {
        switch (imageIndex) {
            case 'next':
                imageIndex = (this.curSlide + 1) < this.imagesArray.length
                break;

            case 'previous':
                imageIndex = (this.curSlide - 1) >= 0 ? this.curSlide - 1 : this.curSlide.length - 1;
                break;

            case 'first':
                imageIndex = 0;
                break;

            case 'last':
                imageIndex = this.imagesArray.length - 1;
                break;

            default:
                imageIndex = imageIndex < this.imagesArray.length ? imageIndex : 0;
                imageIndex = imageIndex < 0 ? 0 : imageIndex;
                break;
        }
        if (this.curImage != null) {
            this.curImage.setOpacity(0);
            this.curImage.style.display = 'none';
        }
        this.curSlide = imageIndex;
        this.curImage = this.imagesArray[imageIndex];
        this.curImage.style.display = 'block';
        this.curImage.setOpacity(100);
    }

    this.element.clear = function() {
        this.imagesArray = new Array();
        this.curSlide = 0;
        this.curLoad = 0;
        this.curImage = null;
        while (this.imageHolder.childNodes.length < 0) {
            this.imageHolder.removeChild(this.imageHolder.firstChild);
        }
    }

    this.element.open = function(imageIndex) {
        this.setImage(imageIndex);
        this.style.display = 'block';
        if (this.onopen != null) {
            this.onopen();
        }
    }

    this.element.close = function() {
        this.pause();
        this.style.display = 'none';
        if (this.curImage != null) {
            this.curImage.setOpacity(0);
            this.curImage.style.display = 'none';
        }
        this.curImage = null;
        if (this.onclose != null) {
            this.onclose();
        }
        this.cleanUp();
    }

    this.element.cleanUp = function() {
        for (var i = 0; i < this.imagesArray.length; i++) {
            this.imagesArray[i].style.left = '0px';
            this.imagesArray[i].style.top = '0px';
            this.imagesArray[i].style.width = this.minWidth;
            this.imagesArray[i].style.height = this.minHeight;
            this.imagesArray[i].setOpacity(0);
            this.imagesArray[i].style.display = 'none';
            this.imagesArray[i].style.cursor = 'default';
            this.imagesArray[i].minleftfollow = 0;
            this.imagesArray[i].mintopfollow = 0;
        }
        this.controls['zoom'].zoomIn.style.display = 'block';
        this.controls['zoom'].zoomOut.style.display = 'none';
        if (this.oncleanup != null) {
            this.oncleanup();
        }
    }

    this.element.zoomIn = function(rate, max) {
        this.pause();
        this.controls['zoom'].zoomOut.style.display = 'block';
        this.curImage.style.cursor = 'move';
        if (!max) {
            newWidth = this.curImage.offsetWidth + 100 > parseInt(this.maxWidth) ? this.maxWidth : (this.curImage.offsetWidth + 100) + 'px';
            newHeight = Math.round(parseInt(newWidth) * .75) + 'px';
            this.curImage.style.width = newWidth;
            this.curImage.style.height = newHeight;
            if (newWidth != this.maxWidth && newHeight != this.maxHeight) {
                this.zoomOutTimeout = setTimeout("document.getElementById('" + this.id + "').zoomIn(" + rate + ", false);", rate);
            } else {
                this.controls['zoom'].zoomIn.style.display = 'none';
                if (this.onzoomin != null) {
                    this.onzoomin();
                }
            }
        } else {
            this.curImage.style.width = this.maxWidth;
            this.curImage.style.height = this.maxHeight;
            this.curImage.style.left = '0px';
            this.curImage.style.top = '0px';
            this.controls['zoom'].zoomIn.style.display = 'none';
            if (this.onzoomin != null) {
                this.onzoomin();
            }
        }
        this.curImage.minleftfollow = this.imageHolder.clientWidth - this.curImage.offsetWidth;
        this.curImage.mintopfollow = this.imageHolder.clientHeight - this.curImage.offsetHeight;
    }

    this.element.zoomOut = function(rate, max) {
        this.pause();
        this.controls['zoom'].zoomIn.style.display = 'block';
        if (!max) {
            newWidth = this.curImage.offsetWidth - 100 < parseInt(this.minWidth) ? this.minWidth : (this.curImage.offsetWidth - 100) + 'px';
            newHeight = Math.round(parseInt(newWidth) * .75) + 'px';
            this.curImage.style.width = newWidth;
            this.curImage.style.height = newHeight;
            if (this.curImage.getRight() < this.imageHolder.clientWidth) {
                this.curImage.style.left = (this.imageHolder.clientWidth - this.curImage.offsetWidth) + 'px';
            }
            if (this.curImage.getBottom() < this.imageHolder.clientHeight) {
                this.curImage.style.top = (this.imageHolder.clientHeight - this.curImage.offsetHeight) + 'px';
            }
            if (newWidth != this.minWidth && newHeight != this.minHeight) {
                this.zoomOutTimeout = setTimeout("document.getElementById('" + this.id + "').zoomOut(" + rate + ", false);", rate);
            } else {
                this.controls['zoom'].zoomOut.style.display = 'none';
                this.curImage.style.cursor = 'default';
                if (this.onzoomout != null) {
                    this.onzoomout();
                }
            }
        } else {
            this.curImage.style.width = this.minWidth;
            this.curImage.style.height = this.minHeight;
            this.curImage.style.left = '0px';
            this.curImage.style.top = '0px';
            this.controls['zoom'].zoomOut.style.display = 'none';
            this.curImage.style.cursor = 'default';
            if (this.onzoomout != null) {
                this.onzoomout();
            } 
        }
        this.curImage.minleftfollow = this.imageHolder.clientWidth - this.curImage.offsetWidth;
        this.curImage.mintopfollow = this.imageHolder.clientHeight - this.curImage.offsetHeight;
    }

    this.element.stopZoom = function() {
        clearTimeout(this.zoomOutTimeout);
        clearTimeout(this.zoomInTimeout);
        this.zoomInTimeout = null;
        this.zoomOutTimeout = null;
    }

    this.element.enableControls = function(controls, which) {
        if (controls == true) {
            for (control in this.controls) {
                alert(control);
            }
        } else {
            controls = controls.split(":");
            for (var i = 0; i < controls.length; i++) {
                this.controls[controls[i]].style.display = which ? 'block' : 'none';
            }
        }
    }

    this.element.play = function() {
        this.slideTimeout = setTimeout("document.getElementById('" + this.id + "').slide();", this.slideInterval * 1000);
    }

    this.element.pause = function() {
        clearTimeout(this.slideTimeout);
        this.controls['slide'].playSlide.style.display = 'block';
        this.controls['slide'].pauseSlide.style.display = 'none';
    }

    this.element.slide = function() {
        this.curImage.style.width = this.minWidth;
        this.curImage.style.height = this.minHeight;
        this.curImage.style.left = '0px';
        this.curImage.style.top = '0px';
        if (this.transitionType == 'none') {
            this.setImage(this.curSlide + 1);
            this.slideTimeout = setTimeout("document.getElementById('" + this.id + "').slide();", this.slideInterval * 1000);
        } else if (this.transitionType == 'crossfade') {
            this.curSlide = this.curSlide + 1 < this.imagesArray.length ? this.curSlide + 1 : 0;
            this.curImage.onfade = function() {
                this.style.display = 'none';
                this.onfade = null;
            }
            this.curImage.fadeOpacity(0, 10);
            this.curImage = this.imagesArray[this.curSlide];
            this.curImage.style.display = 'block';
            this.curImage.onfade = function() {
                this.parentNode.parentNode.slideTimeout = setTimeout("document.getElementById('" + this.parentNode.parentNode.id + "').slide();", this.parentNode.parentNode.slideInterval * 1000);
                this.onfade = null;
            }
            this.curImage.fadeOpacity(100, 10);
        }
    }

    this.element.setTransition = function(transition) {
        this.transitionType = transition;
    }

    this.onclose   = null;
    this.oncleanup = null;
    this.onopen    = null;
    this.onzoomin  = null;
    this.onzoomout = null;

    return this.element;

}
