function ImageRotator(currentImageId, imageListId, previousImageId, nextImageId, imageArray, timeout) {
    this._currentImage = $('#' + currentImageId);
    this._imageList = $('#' + imageListId);
    this._previousImage = $('#' + previousImageId);
    this._nextImage = $('#' + nextImageId);
    this._imageArray = imageArray;
    this._currentImageIndex = 0;
    this._timeout = timeout;
    this._timeoutId = 0;

    this._initialise();
}

ImageRotator.prototype = {
    _getElement: function (parent, selector, defaultElement) {
        var element = parent.children(selector);

        if (element.length == 0) {
            parent.append(element = defaultElement);
        }

        return element;
    },

    _buildImageList: function () {
        for (var i = 0; i < this._imageArray.length; i++) {
            var image = this._imageArray[i];
            this._imageList.append($('<a></a>').attr('href', image.imageFile).append($('<img />').attr('src', image.thumbnailFile).attr('title', image.title)));
        }
    },

    _initialise: function () {

        this._imageArray.sort(function () {
            return 0.5 - Math.random()
        });

        this.showCurrentImage();
        this._buildImageList();
        this._preloadImages();
        this.startRotator();

        var self = this;

        $(document).keydown(function (e) {
            if (e.which == 37) {
                self.stopRotator();
                self.showPreviousImage();

                return false;
            }
            else if (e.which == 39) {
                self.stopRotator();
                self.showNextImage();

                return false;
            }
        });

        this._previousImage.click(function () {
            self.stopRotator();
            self.showPreviousImage();

            return false;
        });

        this._nextImage.click(function () {
            self.stopRotator();
            self.showNextImage();

            return false;
        });

        this._imageList.find('a').click(function () {
            self.stopRotator();
            self._currentImageIndex = self._findImageIndex($(this).attr('href'));
            self.showCurrentImage();

            return false;
        });
    },

    _findImageIndex: function (fileName) {
        for (var i = 0; i < this._imageArray.length; i++) {
            if (this._imageArray[i].imageFile == fileName) {
                return i;
            }
        }
        return -1;
    },

    _preloadImages: function () {
        for (var i = 0; i < this._imageArray.length; i++) {
            $('<img />').attr('src', this._imageArray[i].imageFile);
        }
    },

    showImage: function (image) {

        var imageFile = image.imageFile;
        var title = image.title;
        var self = this;

        this._currentImage.fadeOut('slow', function () {

            self._currentImage.attr('src', imageFile);

            if (self._currentImage.width() > self._currentImage.height()) {
                self._currentImage.css('width', self._currentImage.parent().css('width'));
                self._currentImage.css('height', 'auto');
            }
            else {
                self._currentImage.css('width', 'auto');
                self._currentImage.css('height', self._currentImage.parent().css('height'));
            }

            self._currentImage.attr('alt', title);
            self._currentImage.fadeIn('slow');
        });
    },

    showCurrentImage: function () {
        this.showImage(this._imageArray[this._currentImageIndex]);
    },

    showPreviousImage: function () {
        this._currentImageIndex--;

        if (this._currentImageIndex < 0) {
            this._currentImageIndex = this._imageArray.length - 1;
        }

        this.showCurrentImage();
    },

    showNextImage: function () {
        this._currentImageIndex++;

        if (this._currentImageIndex >= this._imageArray.length) {
            this._currentImageIndex = 0;
        }

        this.showCurrentImage();
    },

    startRotator: function () {
        var self = this;

        this._timeoutId = setInterval(function () {
            self.showNextImage();
        }, this._timeout);
    },

    stopRotator: function () {
        clearInterval(this._timeoutId);
    }
}
