// Name: Image Viewer
// Programmer: Michael Bursill

var classAttribute = 'class';
initialize();

function initialize()
{
    var browser=navigator.appName
    
    if (browser=="Microsoft Internet Explorer") {
        classAttribute = 'className';
    } else { 
        classAttribute = 'class';
    }
}

function ImageViewer(containerID)
{
    var images = [];
    var captions = [];
    var mainBoxType = '';
    var thumbnailBoxType = '';
    var defaultImage = '';
    var container = document.getElementById(containerID);
    var thumbnailImagePath = '';
    var largeImagePath = '';
    var selectedIndex = -1;
    var previousButton = '';
    var previousButtonHover = '';
    var nextButton = '';
    var nextButtonHover = '';
    var thumbLocation = '';
    var thumbsPerRow = 3;
    var showCaption = true;
    
    // box factory
    var boxFactory = new BoxFactory();

    // properties to change the look of the viewer
    var showThumbs = true;
    var useThumbnailsForMainImage = false;

    // objects for the different parts to the viewer
    var mainImageCreator = new MainImageCreator();
    var thumbnailCreator = new ThumbnailCreator();

    this.addImage = addImage;
    this.setThumbnailImagePath = setThumbnailImagePath;
    this.setLargeImagePath = setLargeImagePath;
    this.setThumbnailsForMainImage = setThumbnailsForMainImage;
    this.setThumbsVisible = setThumbsVisible;
    this.setMainBoxType = setMainBoxType;
    this.setThumbnailBoxType = setThumbnailBoxType;
    this.setPreviousButton = setPreviousButton;
    this.setPreviousButtonHover = setPreviousButtonHover;
    this.setNextButton = setNextButton;
    this.setNextButtonHover = setNextButtonHover;
    this.setDefaultImage = setDefaultImage;
    this.setThumbnailLocation = setThumbnailLocation;
    this.setThumbnailsPerRow = setThumbnailsPerRow;
    this.setCaptionVisible = setCaptionVisible;
    this.draw = draw;

    function setThumbnailImagePath(value)
    {
        thumbnailImagePath = value;
    }

    function setLargeImagePath(value)
    {
        largeImagePath = value;
    }

    function setThumbsVisible(value)
    {
        showThumbs = value;
    }

    // set the box type used by the BoxFactory object
    function setThumbnailBoxType(value)
    {
        thumbnailBoxType = value;
    }

    // set the box type used by the BoxFactory object
    function setMainBoxType(value)
    {
        mainBoxType = value;
    }
    
    function setThumbnailsForMainImage(value)
    {
        useThumbnailsForMainImage = value;
    }

    function setDefaultImage(value)
    {
        defaultImage = value;
    }
    
    function setPreviousButton(value)
    {
        previousButton = value;
    }
    
    function setPreviousButtonHover(value)
    {
        previousButtonHover = value;
    }
    
    function setNextButton(value)
    {
        nextButton = value;
    }
    
    function setNextButtonHover(value)
    {
        nextButtonHover = value;
    }
    
    function setThumbnailLocation(value)
    {
        thumbLocation = value;
    }
    
    function setThumbnailsPerRow(value)
    {
        thumbsPerRow = value;
    }
    
    function setCaptionVisible(value)
    {
        showCaption = value;
    }
    
    // add an image to the image viewer
    // becomes the selected image if the imageName matches the value set in defaultImage
    function addImage(imageName, captionText)
    {
        if (captionText === undefined) {
            captionText = '';
        }
    
        var imageIndex = images.length;
       
        // add the image and caption to the lists
        images[imageIndex] = imageName;
        captions[imageIndex] = captionText;
        
        // add the image to the thumbnail creator
        // thumbnailCreator.addImage(imageIndex, false);
        
        // if this is the default image select it
        if (imageName === defaultImage) {
            setSelected(imageIndex);
        }
        
        // if no image is selected select this one
        if (selectedIndex == -1) {
            setSelected(imageIndex);
        }

        // update the image text on the main image
        mainImageCreator.updateImageText();
    }
    
    function draw()
    {
        var imageViewerTable = document.createElement('table');
        
        var topRow = imageViewerTable.insertRow(0);
        var middleRow = imageViewerTable.insertRow(1);
        var bottomRow = imageViewerTable.insertRow(2);
        
        var topLeftLeftCell = document.createElement('td');
        var topMiddleCell = document.createElement('td');
        var topRightCell = document.createElement('td');
        
        var middleLeftCell = document.createElement('td');
        var middleCell = document.createElement('td');
        var middleRightCell = document.createElement('td');
        
        var bottomLeftCell = document.createElement('td');
        var bottomMiddleCell = document.createElement('td');
        var bottomRightCell = document.createElement('td');
        
        topRow.appendChild(topLeftLeftCell);
        topRow.appendChild(topMiddleCell);
        topRow.appendChild(topRightCell);
        
        middleRow.appendChild(middleLeftCell);
        middleRow.appendChild(middleCell);
        middleRow.appendChild(middleRightCell);
        
        bottomRow.appendChild(bottomLeftCell);
        bottomRow.appendChild(bottomMiddleCell);
        bottomRow.appendChild(bottomRightCell);
           
        // get the main image table and append it to the middle
        var mainImageTable = mainImageCreator.getImageTable();
        middleCell.appendChild(mainImageTable);
        
        // if thumbnails are visible, get the table and append it at the correct location
        if (showThumbs) {
            var thumbnailTable = thumbnailCreator.getThumbnailTable();
            
            switch (thumbLocation)
            {
                case ('Top'):
                    topMiddleCell.appendChild(thumbnailTable);
                    break;

                case ('Left'):
                    middleLeftCell.appendChild(thumbnailTable);
                    break;
                    
                case ('Right'):
                    middleRightCell.appendChild(thumbnailTable);
                    break;
                
                case ('Bottom'):
                    bottomMiddleCell.appendChild(thumbnailTable);
                    break;
                
                default:
                    bottomMiddleCell.appendChild(thumbnailTable);
                    break;
            }
        }
        
        // set the selected item
        setSelected(selectedIndex);
        
        if (container != null) {
            container.appendChild(imageViewerTable);
        }
    }
    
    function setSelected(imageIndex)
    {
        mainImageCreator.setSelectedImage(imageIndex);
        thumbnailCreator.setSelectedThumbnail(imageIndex);
        
        selectedIndex = imageIndex;
        
        mainImageCreator.updateImageText();
    }

    // nested class for handling the main image table
    function MainImageCreator()
    {
        this.getImageTable = getImageTable;
        this.setSelectedImage = setSelectedImage;
        this.updateImageText = updateImageText;
        
        var created = false;
        
        var imageTable = document.createElement('table');
        var mainImage = document.createElement('img');
        var imageCountText = document.createTextNode(''); 
        var imageCaptionText = document.createTextNode(''); 

        function createImageTable()
        {
            imageTable.setAttribute('border', '0');
            imageTable.setAttribute('cellspacing', '0');
            imageTable.setAttribute('cellpadding', '5');

            // create the row used by this table
            var mainRow = imageTable.insertRow(0);
            
            // create the cells
            var leftNavigationCell = document.createElement('td');
            var rightNavigationCell = document.createElement('td');
            var mainImageCell = document.createElement('td');
            
            // create the image for the navgation buttons
            var leftNavigationImg = document.createElement('img');
            var rightNavigationImg = document.createElement('img');
                      
            // set the rollover attributes
            leftNavigationImg.setAttribute('src', previousButton);
            leftNavigationImg.onmouseout = function() {
                leftNavigationImg.setAttribute('src', previousButton);
            }
            leftNavigationImg.onmouseover = function() {
                leftNavigationImg.setAttribute('src', previousButtonHover);
            }

            rightNavigationImg.setAttribute('src', nextButton);
            rightNavigationImg.onmouseout = function() {
                rightNavigationImg.setAttribute('src', nextButton);
            }
            rightNavigationImg.onmouseover = function() {
                rightNavigationImg.setAttribute('src', nextButtonHover);
            }
            
            // set the event handlers
            leftNavigationImg.onclick = movePrevious;
            rightNavigationImg.onclick = moveNext;

            // create the box object used for the main image table
            var boxObj = boxFactory.getBox(mainBoxType, false); 
            
            // create a nested table for storing the text (caption & image count)
            var textTable = document.createElement('table');
            
            textTable.setAttribute('border', '0');
            textTable.setAttribute('width', '100%');
            textTable.setAttribute('cellspacing', '0');
            textTable.setAttribute('cellpadding', '0');
            
            // create the text row
            var innerTextRow = textTable.insertRow(0);
            
            // set attributes on the row
            innerTextRow.setAttribute('valign', 'top');

            // create the two text cells
            var imageCaptionCell = document.createElement('td');
            var imageCountCell = document.createElement('td');
            
            // set attributes on the cells
            imageCaptionCell.setAttribute('align', 'left');
            imageCountCell.setAttribute('align', 'right');
            
            // create the two cells
            innerTextRow.appendChild(imageCaptionCell);
            innerTextRow.appendChild(imageCountCell);
            
            // add the text content
            imageCaptionCell.appendChild(imageCaptionText);
            imageCountCell.appendChild(imageCountText);            

            // create the main image table
            var mainImageTable = document.createElement('table');
            
            mainImageTable.setAttribute('border', '0');
            mainImageTable.setAttribute('cellspacing', '0');
            mainImageTable.setAttribute('cellpadding', '0');

            var imageRow = mainImageTable.insertRow(0);
            var textRow = mainImageTable.insertRow(1);

            // create the cells
            var imageCell = document.createElement('td');
            var textCell = document.createElement('td');

            // add the cells to the rows
            imageRow.appendChild(imageCell);
            textRow.appendChild(textCell);
            
            // add the content to the cells
            imageCell.appendChild(mainImage);
            textCell.appendChild(textTable);
            
            // add the image table to the box
            boxObj.addContent(mainImageTable);

            // add the elements to the cells
            leftNavigationCell.appendChild(leftNavigationImg);
            rightNavigationCell.appendChild(rightNavigationImg);
            mainImageCell.appendChild(boxObj.getElement());
            
            // add the cell to the row
            if (images.length > 1) {
                mainRow.appendChild(leftNavigationCell);
            }
            
            mainRow.appendChild(mainImageCell);
            
            if (images.length > 1) {
                mainRow.appendChild(rightNavigationCell);
            }
            
            // set the flag to indicate the the table has been created
            created = true;
        }

        function movePrevious()
        {
            if ((selectedIndex - 1) === -1) {
                setSelected(images.length - 1);
            } else {
                setSelected(selectedIndex - 1);
            }
        }
        
        function moveNext()
        {
            if ((selectedIndex + 1) === images.length) {
                setSelected(0);
            } else {
                setSelected(selectedIndex + 1);
            }
        }

        function setSelectedImage(imageIndex)
        {
            var newImagePath;
            
            if (!useThumbnailsForMainImage) {
                newImagePath = largeImagePath + images[imageIndex];
            } else {
                newImagePath = thumbnailImagePath + images[imageIndex];
            }

            // get the container of the main image
            var mainImageContainer = mainImage.parentNode;

            // create a new image element and set the src attribute
            newMainImage = document.createElement('img');
            newMainImage.setAttribute('src', newImagePath);
            
            // if the container was not null, replace the existing image in the container
            if (mainImageContainer !== null) {
                mainImageContainer.replaceChild(newMainImage, mainImage);
            }
            
            // reassign the mainImage var
            mainImage = newMainImage;
        }

        function updateImageText()
        {
            var currentImage = selectedIndex + 1;
            var totalImage = images.length;
                        
            imageCountText.data = currentImage.toString() + "/" + totalImage.toString();
            
            if (showCaption === true) {
                imageCaptionText.data = captions[selectedIndex];
            }
        }

        function getImageTable()
        {
            if (created === false) {
                if (images.length == 0) {
                    return document.createTextNode('No Image');
                } else {
                    createImageTable();
               }
            }
        
            return imageTable;
        }
    }
     
    // nested class for handling the thumbs table
    function ThumbnailCreator()
    {  
        this.getThumbnailTable = getThumbnailTable;
        this.addImage = addImage;
        this.setSelectedThumbnail = setSelectedThumbnail;

        var imagesTable = document.createElement('table');

        imagesTable.setAttribute('border', '0');
        imagesTable.setAttribute('cellspacing', '0');
        imagesTable.setAttribute('cellpadding', '5');

        var currentRow = imagesTable.insertRow(imagesTable.rows.length);

        var boxes = [];

        function createTable()
        {
            for (var imageIndex = 0; imageIndex < images.length; imageIndex++) {
              
                var currentCell = document.createElement('td');
                var thumbID = containerID + "_thumb" + imageIndex;
                          
                // get a box for this thumb
                var selected = (imageIndex === selectedIndex);
                var boxObj = boxFactory.getBox(thumbnailBoxType, selected);
                
                // add the new box to the boxes array
                boxes[boxes.length] = boxObj;
               
                // create the image element
                var currentImage = document.createElement('img');
                currentImage.setAttribute('src', thumbnailImagePath + images[imageIndex]);
                currentImage.setAttribute('id', thumbID);

                // setup the event hander (cross browser) for clicking a thumbnail image
                currentImage.onclick = thumbClicked;

                // add the image element to the thumbnail continer
                boxObj.addContent(currentImage);
                
                // get the element of the box object and add it to the cell
                currentCell.appendChild(boxObj.getElement());

                // add the cell to the row
                currentRow.appendChild(currentCell);
                
                // X images to a row
                if (((imageIndex + 1) % thumbsPerRow) === 0) {
                   currentRow = imagesTable.insertRow(imagesTable.rows.length);
                }
            }           
        }
        
        function setSelectedThumbnail(imageIndex)
        {
            // if the table doesnt exist, dont select it
            if (showThumbs === false)
                return;
                
            // if the index is out of bounds don't continue
            if (imageIndex > (boxes.length - 1))
                return;
        
            // if the selection didn't change, don't do anything
            if (selectedIndex === imageIndex)
                return;
            
            // check for previous selection
            if (selectedIndex > -1)
            {
                // set the section on the previous box to false
                boxes[selectedIndex].setSelected(false);
            }

            // set the section on the new index to true
            boxes[imageIndex].setSelected(true);
        }

        function thumbClicked()
        {
            var thumbID = this.getAttribute("id");        

            var imageIndexStart = thumbID.indexOf('_thumb') + 6;
            var imageIndex = parseInt(thumbID.slice(imageIndexStart));
            
            setSelected(imageIndex);
        }
       
        function getThumbnailTable()
        {
            // make the table
            createTable();

            // return the images table
            return imagesTable;
        }
        
    }

}

//box factory
function BoxFactory()
{
    this.getBox = getBox;
   
    function getBox(boxType, selected)
    {
        var newBox;
    
        switch (boxType)
        {
            case ('ShadowBox'):
                newBox = new ShadowBox(selected);
                break;
                
            case ('SimpleBox'):
                newBox = new SimpleBox();
                break;
        
            default:
                newBox = new SimpleBox();
                break;
        }
        
        return newBox;
    }   
}


// object for a box with a drop shadow
// the selected attirbute sets the styles/color of the shadow
function ShadowBox(boxSelected)
{
    this.getElement = getElement;
    this.setSelected = setSelected;
    this.addContent = addContent;
    
    var selected = boxSelected;
    
    // make the box
    var innerThumbsContainer = document.createElement('div');
    var outerThumbsContainer = document.createElement('div');
    innerThumbsContainer.setAttribute(classAttribute, 'innerbox');
    outerThumbsContainer.appendChild(innerThumbsContainer);
    
    // when creating the object set the selected style
    setSelected(boxSelected);

    // global function for returning the a nested div styled to show a dropshadow
    function getElement()
    {
        return outerThumbsContainer;
    }

    // global function for setting the selected attribute (modifies the styles)    
    function setSelected(boxSelected)
    {
        selected = boxSelected;
        
        if (selected) {
            outerThumbsContainer.setAttribute(classAttribute, 'dropshadowSelected');
        } else {
            outerThumbsContainer.setAttribute(classAttribute, 'dropshadow');
        }
    }
    
    function addContent(insideElement)
    {
        innerThumbsContainer.appendChild(insideElement);
    }
}

function SimpleBox(boxSelected)
{
    this.getElement = getElement;
    this.setSelected = setSelected;
    this.addContent = addContent;
    
    var selected = boxSelected;
    
    // make the box
    var container = document.createElement('div');
    
    // when creating the object set the selected style
    setSelected(boxSelected);

    // global function for returning the a nested div styled to show a dropshadow
    function getElement()
    {
        return container;
    }

    // global function for setting the selected attribute (modifies the styles)    
    function setSelected(boxSelected)
    {
        selected = boxSelected;
        
        if (selected) {
            //container.setAttribute('class', 'dropshadowSelected');
        } else {
            //container.setAttribute('class', 'dropshadowSelected');
        }
    }
    
    function addContent(insideElement)
    {
        container.appendChild(insideElement);
    }
}
