var ThumbManager = function(thumbW, thumbH, stripSize, stripOverlap,
                            thumblistPrefix, previewPrefix, origPrefix,
                            filenames, captions, dates) {
    var _this = this;
    
    _this.selected        = -1;
    _this.thumbW          = thumbW;
    _this.thumbH          = thumbH;
    _this.stripSize       = stripSize;
    _this.stripOverlap    = stripOverlap;
    _this.thumblistPrefix = thumblistPrefix;
    _this.previewPrefix   = previewPrefix;
    _this.origPrefix      = origPrefix;
    _this.filenames       = filenames;
    _this.captions        = captions;   
    _this.dates           = dates;   
    _this.picOffset       = Math.round(_this.stripOverlap/2-0.5);
    _this.yOffset         = _this.picOffset * _this.thumbH;
    
    _this.node = document.getElementById("picture-selector");
    
    // build the selector
    _this.clearNode(_this.node);

    var leftArrow = document.createElement("a");
    leftArrow.innerHTML = "&#160;";
    leftArrow.href      = "javascript:;";
    leftArrow.className = "left-arrow";
    leftArrow.title     = "go back one picture";
    leftArrow.onmouseup = function() {
        // FIXME: leaky leaky
        _this.addSelected(-1);
    };

    var rightArrow = document.createElement("a");
    rightArrow.innerHTML = "&#160;";
    rightArrow.href      = "javascript:;";
    rightArrow.className = "right-arrow";
    rightArrow.title     = "next picture";
    rightArrow.onmouseup = function() {
        // FIXME: leaky leaky
        _this.addSelected(1);
    };
    
    var posButtons = document.createElement("div");
    posButtons.className = "cmd-button-area";
    posButtons.innerHTML = "" +
        "<a class=\"first-button\" title=\"first picture\" " +
        "href=\"javascript:;\" onclick=\"thumbManager.setSelected(0);\">&#160;</a>" +
    
        "<a class=\"prev-20-button\" title=\"go back 20 pictures\" " +
        "href=\"javascript:;\" onclick=\"thumbManager.addSelected(-20);\">&#160;</a>" +
        "<a class=\"last-button\" title=\"last picture\" " +
        "href=\"javascript:;\" onclick=\"thumbManager.setSelected(100000000000);\">&#160;</a>" +
        "<a class=\"next-20-button\" title=\"go forward 20 pictures\" " +
        "href=\"javascript:;\" onclick=\"thumbManager.addSelected(+20);\">&#160;</a>";
    
    _this.viewer = document.createElement("div");
    _this.viewer.className = "viewer";
    _this.viewer.onclick = function(evt) {
        _this.handlePictureClick(evt != null ? evt : window.event);
    }
    
    // build the cursor.  FIXME: Hard-coded positions
    var cursor = document.createElement("div");
    cursor.className = "cursor";
    cursor.style.position = "absolute";
    cursor.style.left   = "-5px";
    cursor.style.top    = ""+(17+_this.yOffset)+"px";
    cursor.style.zIndex = "100";
    cursor.style.width  = "" + (_this.thumbW+4) + "px";
    cursor.style.height = "" + (_this.thumbH+4) + "px";
    _this.node.appendChild(cursor);

    _this.className = "thumbs";
    _this.viewer.style.width  = ""+thumbW+"px";
    _this.viewer.style.height = ""+(thumbH*stripOverlap)+"px";
    window.onkeydown = function(evt) {
        // This is for FF and Safari... sigh.
        if (!evt) {
            return; // this is IE
        } else if (evt.keyCode == 37 || evt.keyCode == 38) {
            _this.addSelected(-1);
            if (evt.preventDefault) { evt.preventDefault(); }
            if (evt.stopPropagation) { evt.stopPropagation(); }
        } else if (evt.keyCode == 39 || evt.keyCode == 40) {
            _this.addSelected(1);
            if (evt.preventDefault) { evt.preventDefault(); }
            if (evt.stopPropagation) { evt.stopPropagation(); }
        }
    };
    document.body.onkeydown = function(evt) {
        if (!evt) {
            // This is for IE only
            evt = window.event;
        } else {
            return; // this is FF
        }
            
        if (evt.keyCode == 37 || evt.keyCode == 38) {
            _this.addSelected(-1);
            if (evt.preventDefault) { evt.preventDefault(); }
            if (evt.stopPropagation) { evt.stopPropagation(); }
        } else if (evt.keyCode == 39 || evt.keyCode == 40) {
            _this.addSelected(1);
            if (evt.preventDefault) { evt.preventDefault(); }
            if (evt.stopPropagation) { evt.stopPropagation(); }
        }
    };

    _this.node.appendChild(leftArrow);
    _this.node.appendChild(_this.viewer);
    _this.node.appendChild(rightArrow);
    _this.node.appendChild(posButtons);
    
    // check the hash part of the href, to use for fixing the back
    // button
    if (location.hash != null && location.hash != "") {
        _this.setSelectedImage(location.hash.substring(1));
        
    } else {
        // go to the first image
        _this.setSelected(0);
    }
}



// Erases all of the children under the given node
ThumbManager.prototype.clearNode = function(node) {
    var _this = this;
    
    while (node.firstChild) {
        node.removeChild(node.firstChild);
    }
}



// Scrolls to the given image by filename
ThumbManager.prototype.setSelectedImage = function(imgFilename) {
    var _this = this;
    
    for (var i = 0; i < _this.filenames.length; ++i) {
        if (_this.filenames[i] == imgFilename) {
            _this.setSelected(i);
            return;
        }
    }
    _this.setSelected(0);
}



// Scrolls to the given image by position
ThumbManager.prototype.setSelected = function(imgPos) {
    var _this = this;
    var DELAY = 10;
    if (imgPos < 0) {
        imgPos = 0;
    } else if (imgPos >= _this.filenames.length) {
        imgPos = _this.filenames.length - 1;
    }

    if (imgPos == _this.selected) {
        return; // feh
    }

    // animate to the position that this thumb would be at
    var oldIdx  = (_this.selected%(_this.stripSize - _this.stripOverlap));
    if (_this.selected > _this.picOffset && oldIdx < _this.picOffset) {
        oldIdx += (_this.stripSize - _this.stripOverlap);
    }
    var oldYPos = -oldIdx*_this.thumbH + _this.yOffset;
    var movePx  = (_this.selected - imgPos)*_this.thumbH;

    // set up the background image and color
    _this.selected = imgPos;
    var imgIdx = (_this.selected%(_this.stripSize - _this.stripOverlap));
    if (_this.selected > _this.picOffset && imgIdx < _this.picOffset) {
        imgIdx += (_this.stripSize - _this.stripOverlap);
    }
    var lStart = _this.selected - imgIdx;
    var lEnd   = Math.min(lStart + _this.stripSize - 1, _this.filenames.length - 1);
    var bgURL  = "url("+_this.thumblistPrefix+lStart+"-"+lEnd+".jpg)";

    // animate the display
    _this.viewer.style.backgroundPosition = "0px " + (oldYPos + movePx/4) + "px";
    setTimeout (function() {
        _this.viewer.style.backgroundPosition = "0px " + (oldYPos + movePx/2) + "px";
        setTimeout (function() {
            _this.viewer.style.backgroundPosition = "0px " + (oldYPos + 3*movePx/4) + "px";
            setTimeout (function() {
                _this.viewer.style.backgroundPosition = "0px " + (oldYPos + 7*movePx/8) + "px";
                setTimeout (function() {

                    // now that we're done with our little animation, see
                    // if we even need to display this image, or if we have
                    // moved on
                    if (imgPos == _this.selected) {
                        if (_this.viewer.style.backgroundImage != bgURL) {
                            _this.viewer.style.backgroundImage = bgURL;
                        }
                        _this.viewer.style.backgroundPosition = "0px " + (-imgIdx*_this.thumbH + _this.yOffset) + "px";
                        _this.viewer.style.backgroundRepeat = "no-repeat";
	
                        // install the preview
                        _this.displayPreview(imgPos);
                        
                        location.hash = _this.filenames[imgPos];
                        
                        //msg("" + _this.selected + " ==> " + imgIdx + " / " + (-imgIdx*_this.thumbH) +
                        //    " in " + _this.viewer.style.backgroundImage);
                    }
                }, DELAY);
            }, DELAY);
        }, DELAY);
    }, DELAY);
}



// Displays the image and the caption in the picture area
ThumbManager.prototype.displayPreview = function(imgPos) {
    var _this = this;

    var captionHTML = "";
    if (_this.captions[imgPos]) {
        captionHTML = "<div class=\"caption\">" + _this.captions[imgPos] + "</div>";
    }
    
    var pic = document.getElementById("picture-area");
    pic.innerHTML = "<img src=\"" + _this.previewPrefix + _this.filenames[imgPos] + "\" />" +
        "<div class=\"info\"><span class=\"date\">" + _this.dates[imgPos] + 
        "</span>: <span class=\"filename\">" + _this.filenames[imgPos] + 
        "</span> ("+(imgPos+1)+" of "+_this.filenames.length+")</div>" + captionHTML;
}



// Displays the image and the caption in the picture area
ThumbManager.prototype.handlePictureClick = function(evt) {
    var _this = this;

    var dst = (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0);
    var dsl = (window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0);

    // FIXME: Hard coded image positioning crap is bad
    var VIEW_X = 20-dsl;
    var VIEW_Y = 75+22-dst;

    if (evt.clientX < VIEW_X ||
        evt.clientY < VIEW_Y ||
        VIEW_X+_this.thumbW <= evt.clientX || 
        VIEW_Y+(_this.thumbH*_this.stripOverlap) <= evt.clientY)
        return; // out of range
    
    var picOff = Math.round((evt.clientY - VIEW_Y - _this.yOffset)/_this.thumbH - 0.5);
    _this.addSelected(picOff);
}



// Adds the given number to the currently selected item
ThumbManager.prototype.addSelected = function(amount) {
    var _this = this;
    _this.setSelected(_this.selected + amount);
}



function msg(str) {
    var DBGOUT = document.getElementById("DBGOUT");
    if (DBGOUT == null) {
        DBGOUT = document.createElement("textarea");
        DBGOUT.id = "DBGOUT";
        DBGOUT.style.width = "500px";
        DBGOUT.style.height = "200px";
        document.body.appendChild(DBGOUT);
    }
    DBGOUT.value = str + "\n" + DBGOUT.value;
}
