// TODO: Load this dynamically
var thumbsPath = 'img/gallery/thumbs/';
var picsPath = 'img/gallery/pictures/';
var imgExt = 'jpg';
var imgArray = [];//'i0000', 'i0001']; // filenames w/o extensions
var allImg = [];//'i0000', 'i0001', 'i0002', 'i0003', 'i0004', 'i0005', 'i0006'];
var buffer = 10;
var thumbWidth = 152; // px
var imgPad = 16;
// Set the currently-selected image
var curImg = 0;

// For swipe navigation
var dragging = false;
var mouseDown = false;
var lastMouseState = false;
var mouseStart = null;
var streamStart = null;

/*
TODO:
+Keyboard-repeat on hold
+Photo categories!
- Click names to load ALLIMG, flush IMGARRAY, and updateBuffer()
*/

var imageLists = {
    'demo': ['IMG_1613'],
    'caseyandjackie': ['IMG_9619', 'IMG_9627', 'IMG_9637', 'IMG_9646', 'IMG_9658',
                       'IMG_9670', 'IMG_9682', 'IMG_9693', 'IMG_9702', 'IMG_9703',
                       'IMG_9712', 'IMG_9717', 'IMG_9774', 'IMG_9789', 'IMG_9792',
                       'IMG_9822', 'IMG_9831', 'IMG_9840', 'IMG_9841', 'IMG_9851',
                       'IMG_9854', 'IMG_9858', 'IMG_9863', 'IMG_9872', 'IMG_9877',
                       'IMG_9880', 'IMG_9888', 'IMG_9898', 'IMG_9920', 'IMG_9921',
                       'IMG_9929', 'IMG_9931', 'IMG_9936', 'IMG_9953', 'IMG_9959',
                       'IMG_9964', 'IMG_9970', 'IMG_9973', 'IMG_9984', 'IMG_9989',
                       'IMG_9997', 'IMG_0005', 'IMG_0036', 'IMG_0042'],
    'engagement': ['IMG_5492', 'IMG_9959', 'IMG_3745', 'IMG_0036', 'IMG_5573',
                   'IMG_8920', 'IMG_3750', 'IMG_9841', 'IMG_4147', 'IMG_9921',
                   'IMG_9020', 'IMG_9953', 'IMG_8953'],
    'portraits':[],
    'willandjennifer': ['IMG_8769', 'IMG_8834', 'IMG_8920', 'IMG_8953', 'IMG_8957',
                        'IMG_8981', 'IMG_8992', 'IMG_9001', 'IMG_9003', 'IMG_9009',
                        'IMG_9020', 'IMG_9049', 'IMG_9069', 'IMG_9082', 'IMG_9086',
                        'IMG_9092', 'IMG_9095', 'IMG_9211'],
    'nature': ['IMG_7270', 'IMG_7282', 'IMG_1613', 'IMG_7411', 'IMG_10330', 'IMG_6116'],
    'interesting': ['IMG_1338', 'IMG_11913', 'IMG_9339', 'IMG_7561', 'IMG_3641', 'IMG_4161', 'IMG_1361', 'IMG_7408']
};


window.onload = function() {
    var C = $('streamInner');
    if (C != null) {
        // Get proper image array based on querystring
        var QS = window.location.search.substring(1).split('&');
        if (QS == undefined) {
            allImg = imageLists['interesting'];
        } else if (imageLists[QS[0]] != undefined) {
            allImg = imageLists[QS[0]];
            if (allImg.length == 0) {
                allImg = imageLists['interesting'];
            }
        } else {
            allImg = imageLists['interesting'];
        }
        // Setup imgArray
        for (var i = 0; i < buffer; i++) {
            if (i < allImg.length)
                imgArray.push(allImg[i]);
        }
        // Load images
        loadStream();
        // Set initial position
        placeStream(false);
        updateBuffer();
    }
    var PI = $('prevImg');
    var NI = $('nextImg');
    if (PI != null) { PI.onclick = function() { changeImage(-1); } }
    if (NI != null) { NI.onclick = function() { changeImage(1); } }
    var PU = $('popup');
    if (PU != null) {
        PU.onmouseover = function() { showClose(); }
        PU.onmouseout = function() { hideClose(); }
    }
    var Closer = $('close');
    if (Closer != null) {
        Closer.onclick = closeModal;
    }
    placeContent();
    /*var N = $('nav');
    if (N != null) {
    var ch = N.childNodes;
    for (var i = 0; i < ch.length; i++) {
    if (ch[i].nodeName == "A") {
    ch[i].onmouseover = function(e) {
    e.returnValue = true;
    //return true;
    }
    }
    }
    }*/
}

function placeContent() {
    var assumedHeight = 310;
    var bottom = -75;
    var C = $('content');
    if (C != null) {
        C.style.paddingTop = (document.body.offsetHeight - assumedHeight + bottom)/2 + "px";
    }
}

function placeStream(animate) {
    var C = $('streamInner');
    if (C != null) {
        var imgWidth = curImg * (thumbWidth + imgPad);
        var startLeft = C.style.left;
        var endLeft = (document.body.offsetWidth - thumbWidth - imgPad) / 2 - imgWidth;
        //C.style.left = (document.body.offsetWidth - thumbWidth - imgPad) / 2 - imgWidth + "px";
        if (animate) {
            doSplineStyle('streamInner', 'left', startLeft, endLeft, "px", 0.2);
        } else {
            C.style.left = endLeft + "px";
        }
        clearThumbClasses(curImg);
    }
}

function loadStream() {
    // Todo: load enough images to fill two screens, and keep this number maintined
    var C = $('streamInner');
    if (C != null) {
        C.style.width = imgArray.length * (imgPad + thumbWidth) + "px";
        var I;
        for (var i = 0; i < imgArray.length; i++) {
            loadImg(imgArray[i]);
        }
    }
}

function updateBuffer() {
    // curImg could be anything. We want imgArray.length to be curImg+buffer
    //debug(' updating buffer. imgArray.length=' + imgArray.length + ', curImg=' + curImg+', buffer='+buffer, true);
    while (imgArray.length < curImg + buffer) {
        if (allImg.length > imgArray.length) {
            var I = allImg[imgArray.length];
            //debug('I=' + I, false);
            imgArray = imgArray.concat(I);
            loadImg(I);
            var C = $('streamInner');
            C.style.width = imgArray.length * (imgPad + thumbWidth) + "px";
        } else if (buffer > allImg.length) { break } else { break; }
    }
}

function loadImg(source) {
    var C = $('streamInner');
    if (C != null) {
        I = document.createElement('img');
        I.setAttribute('src', thumbsPath + source + '.' + imgExt);
        setOpacity(I, 1.0);
        I.onload = function(e) { }
        I.onclick = function() {
            if (!dragging) {
                curImg = findInArray(imgArray, extractName(this.getAttribute('src')));
                launchModal();
                placeStream(true);
                updateBuffer();
            }
        }
        I.onmouseover = function(e) {
            clearThumbClasses(-1);
        }
        I.onmouseout = function(e) {
            clearThumbClasses(curImg);
        }
        I.onmousedown = function(e) {
            mouseDown = true;
            var E = e || window.event;
            mouseStart = mouseCoords(E).x;
            streamStart = parseInt(C.style.left);
            E.preventDefault();
        }
        C.onmousedown = function(e) {
            mouseDown = true;
            var E = e || window.event;
            mouseStart = mouseCoords(E).x;
            streamStart = parseInt(C.style.left);
            E.preventDefault();
        }
        C.appendChild(I);
    }
}
var lastClicked = '';

function changeImages(newSet, linkElement) {
    remClass(lastClicked, 'current');
    addClass(linkElement, 'current');
    lastClicked = linkElement;
    var L = imageLists[newSet];
    if (L != undefined) {
        if (L.length > 0) {
            // Bring Stream back to start [0.2s]
            curImg = 0;
            placeStream(true);
            // Setup data structures
            allImg = L;
            imgArray = [];
            for (var i = 0; i < buffer; i++) {
                if (i < allImg.length)
                    imgArray.push(allImg[i]);
            }
            // Animate it.
            var SI = $('streamInner');
            window.setTimeout(function() {
                var W = SI.offsetWidth;
                doSplineStyle(SI, 'width', W, 0, "px", 0.35);
                window.setTimeout(function() {
                    clear('streamInner');
                    // New width: 
                    var W = imgArray.length * (imgPad + thumbWidth) + 5;
                    // Load images
                    loadStream();
                    placeStream(false);
                    doSplineStyle(SI, 'width', 0, W, "px", 0.35);
                    window.setTimeout(function() {
                        updateBuffer();
                    }, 450);
                }, 550);
            }, 300);
        }
    }
    return false;
}

function findInArray(arr, item) {
    for (var i = 0; i < arr.length; i++) {
        if(arr[i] == item) return(i);
    }
    return(-1);
}

function clearThumbClasses(except) {
    var curImgSrc = '';
    if(except > -1 && except < imgArray.length)
        curImgSrc = thumbsPath + imgArray[curImg] + '.' + imgExt;
    var C = $('streamInner');
    if (C != null) {
        for (var i = 0; i < C.childNodes.length; i++) {
            if (C.childNodes[i].nodeName == 'IMG') {
                if (C.childNodes[i].getAttribute('src') == curImgSrc) {
                    addClass(C.childNodes[i], 'sel');
                } else {
                    remClass(C.childNodes[i], 'sel');
                }
            }
        }
    }
}

function extractName(src) {
    var N = '';
    // Want string between last '/' and '.ext'
    N = src;
    N = N.replace('.' + imgExt, '');
    N = N.slice(N.lastIndexOf("/") + 1);
    /*
    N = src.replace(thumbsPath, '');
    N = N.replace(picsPath, '');
    N = N.replace('.' + imgExt, '');
    */
    return N;
}

window.onresize = function() {
    var M = $('modal');
    if (M != null) {
        if (M.style.visibility == 'visible') {
            launchModal();
        }
    }
    placeStream(false);
    placeContent();
}

var ctrl = false;
var alt = false;
var shift = false;

document.onkeydown = function(e) {
    // To catch auxiliary keys
    var K = Key(e);
    //debug('Down: ' + K + ' ', false);
    switch (K) {
        case 16: // Shift key
            shift = true; break;
        case 17: // Ctrl key
            ctrl = true; break;
        case 18: // Alt key
            alt = true; break;
    }
}
document.onkeyup = function(e) {
    var M = $('modal');
    var modal = false;
    if (M != null) {
        if (M.style.visibility == 'visible') {
            modal = true;
        }
    }
    var K = Key(e);
    //debug('Up: ' + K + ' ', false);

    switch (K) {
        // Launch Modal 
        case 38: // up
            if (!modal) launchModal();
            break;
        case 13: // enter
            if (modal) closeModal(); // close if open
            else launchModal(); // open if closed
            break;
        // Close Modal 
        case 27: // esc
        case 40: // down
            closeModal();
            break;
        // Next Image 
        case 39: // right
            if (!ctrl) changeImage(1);
            else changeImage(5);
            break;
        // Prev Image 
        case 37: // left
            if (!ctrl) changeImage(-1);
            else changeImage(-5);
            break;
        // Jumps 
        case 9: // tab
            break;
        // Reset auxiliary keys 
        case 16: // Shift key
            shift = false; break;
        case 17: // Ctrl key
            ctrl = false; break;
        case 18: // Alt key
            alt = false; break;
    }

}

document.onmousedown = function(e) {
    //mouseDown = true; // <- set in I.onmousedown only
    
}

document.onmouseup = function(e) {
    mouseDown = false;
    //dragging = false;
    //lastMouseState = false;
    streamStart = null;
    // Spline move image stream to closest whole image
    var C = $('streamInner');
    if (C != null) {
        var leftBound = parseInt(C.style.left);
        var rightBound = parseInt(C.style.left) + imgArray.length * (thumbWidth + imgPad);
        var center = 640;
        //debug('Bounds: [' + leftBound + ', ' + rightBound + '] ', true);
        if (document.body.offsetWidth) {
            center = document.body.offsetWidth / 2;
        }
        if (rightBound < center) {
            curImg = imgArray.length - 1;
        } else if (leftBound > center) {
            curImg = 0;
        } else {
            //debug('C-L: ' + (center - leftBound) + ' T+P: ' + (thumbWidth + imgPad), true);
            curImg = parseInt((center - leftBound) / parseFloat(thumbWidth + imgPad));
        }
        placeStream(true);
        updateBuffer();
    }
}

document.onmousemove = function(e) {
    var E = e || window.event;
    if (mouseDown && !lastMouseState) {
        // Starting Drag
        //debug('Starting drag. ', true);
        dragging = true;
    } else if (mouseDown && lastMouseState) {
        // During drag
        //debug('Dragging. ', false);
        var offset = mouseCoords(E).x - mouseStart;
        //debug('Mouse start: ' + mouseStart + ' Offset: ' + offset + '. Stream start: ' + streamStart + '. Location: ' + (mouseStart + offset), true);
        var C = $('streamInner');
        if (C != null) {
            C.style.left = (streamStart + offset) + "px";
        }
    } else if (!mouseDown && lastMouseState) {
        dragging = false;
        //debug('Ending drag. ', false);
    } else { dragging = false; }
    lastMouseState = mouseDown;
}

function mouseCoords(e) {
    if (e.pageX || e.pageY) {
        return { x: e.pageX, y: e.pageY };
    }
    return {
        x: e.clientX + document.body.scrollLeft - document.body.clientLeft,
        y: e.clientY + document.body.scrollTop - document.body.clientTop
    };
}

function changeImage(count) {
    curImg += count;
    updateBuffer();
    if (curImg >= imgArray.length) {
        curImg = imgArray.length - 1;
        closeModal();
    }
    else if (curImg < 0) {
        curImg = 0;
        closeModal();
    } else {
        var M = $('modal');
        if (M != null) {
            if(M.style.visibility == 'visible')
                launchModal();
        }
    }
    placeStream(true);
}

function launchModal() {
    var M = $('modal');
    var P = $('popup');
    var PI = $('prevImg');
    var NI = $('nextImg');
    var imgSrc = picsPath + imgArray[curImg] + '.' + imgExt;
    if (M != null && P != null) {
        var I = document.createElement('img');
        I.onload = function() {
            // Size the image for the browser window
            var W = this.width;
            var H = this.height;
            var proportion = W / (H * 1.0);
            if (document.body.offsetHeight * 0.9 < H) {
                H = document.body.offsetHeight * 0.9;
                W = H * proportion;
                this.width = W;
                this.height = H;
            }
            if (document.body.offsetWidth * 0.9 < W) {
                W = document.body.offsetWidth * 0.9;
                H = W / proportion;
                this.width = W;
                this.height = H;
            }
            P.style.width = this.width + "px";
            P.style.height = this.height + "px";

            P.style.marginLeft = -this.width / 2 + "px";
            if (document.body.offsetHeight) {
                try {
                    P.style.top = 4 * (document.body.offsetHeight - I.height) / 10 + "px";
                } catch (e) {
                    P.style.top = '25px';
                }
            } else { P.style.top = '25px'; }
            if (P.firstChild.nodeName == 'IMG') {
                P.replaceChild(this, P.firstChild);
            } else {
                P.insertBefore(this, P.firstChild);
            }
            M.style.visibility = 'visible';
            if (PI != null) { PI.style.visibility = 'visible'; }
            if (NI != null) { NI.style.visibility = 'visible'; }
        }
        I.onerror = closeModal;
        // Do it.
        I.setAttribute('src', imgSrc);
    } else { debug('Error: nulls in launchModal()', false); }
    var BG = $('matte');
    if (BG != null) {
        BG.onclick = closeModal;
    }
}

function closeModal() {
    var M = $('modal');
    var PI = $('prevImg');
    var NI = $('nextImg');
    //lastImage = '';
    if (M != null) M.style.visibility = 'hidden';
    if (PI != null) PI.style.visibility = 'hidden';
    if (NI != null) NI.style.visibility = 'hidden';
    hideClose();
}

var clOpID = -1;
function showClose() {
    var C = $('close');
    if (C != null) {
        if (clOpID != -1) { window.clearTimeout(clOpID); }
        C.style.visibility = 'visible';
        doSplineStyle('close', 'opacity', 0.0, 1.0, '', 0.2);
    }
}
function hideClose() {
    var C = $('close');
    if (C != null) {
        doSplineStyle('close', 'opacity', 1.0, 0.0, '', 0.2);
        clOpID = window.setTimeout(function() { C.style.visibility = 'hidden'; }, 300);
    }
}

function setOpacity(elID, opVal) {
    /* opVal given in [0,1] interval */
    var E = $(elID);
    if (E != null) {
        E.style.filter = 'alpha(opacity=' + opVal * 100 + ')';
        E.style.opacity = opVal;
        E.style.MsFilter = 'progid:DXImageTransform.Microsoft.Alpha(Opacity=' + opVal*100 + ')';
    }
}

var splineID = -1;
function doSplineStyle(el, elStyle, start, end, units, transitionTime) {
    var E = $(el);
    start = parseInt(start, 10);
    var Range = end - start;
    var Step = 0;
    var Delay = 15;      // ms before next call
    var Steps = transitionTime / (Delay / 1000.0);     // Total steps durint transitionTime (s)
    //debug('Spline from ' + start + ' to ' + end + ' in ' + Steps + ' steps.',true);

    if (splineID != -1) window.clearInterval(splineID);

    var ID = window.setInterval(
        function() {
            var S = 0;  // eval('E.style.' + elStyle);
            S = (start + Range * splineValue(Step / Steps.toPrecision(1)));
            //debug(S + ' ',false)
            if (elStyle == 'opacity') {
                setOpacity(el, S);
            } else {
                E.style[elStyle] = S.toString() + units;
            }
            //debug(E.style[elStyle] + ' ', false);
            Step++;
            if (Step >= Steps) {
                window.clearInterval(ID);
                // Set a cookie for the proper width of the article
                //alertSize();
            }
        }
    , Delay);
    splineID = ID;
}

function splineValue(percent) {
    // Generate the value of a spline at a certain percent in the range [0,1]
    var x = percent;
    var f = 0.0;
    if (x >= 0 && x <= 1) {
        f = 6 * Math.pow(x, 5) - 15 * Math.pow(x, 4) + 10 * Math.pow(x, 3);
    }
    if (x >= 1) f = 1;
    return (f);
}

function Key(evt) {
    if (!evt) { if (window.event) evt = window.event; else return; }
    if (typeof(evt.keyCode) == 'number')
        return (evt.keyCode);
    else if (typeof (evt.which) == 'number')
        return (evt.which);
    else if (typeof (evt.charCode) == 'number')
        return (evt.charCode);
}

/*function Pad(str, width, fillChar) {
    if (str.length < width) {
        var S = '';
        while (S.length < width - str.length) {
            S = S + fillChar;
        }
        S = S + str;
        return S;
    } else { return str };
}*/

function $() {
    var elements = new Array();
    for (var i = 0; i < arguments.length; i++) {
        var element = arguments[i];
        if (typeof element == 'string')
            element = document.getElementById(element);
        if (arguments.length == 1)
            return element;
        elements.push(element);
    }
    return elements;
}

function debug(text,replace) {
    var D = $('debug');
    if(D != null) {
        if (replace) {
            clear(D);
        }
        D.appendChild(document.createTextNode(text));
    }
}
   
function clear(el) {
    var E = $(el);
    while (E.hasChildNodes())
        E.removeChild(E.firstChild);
    return (false);
}

function addClass(E, clName) {
    // Add the class label CLNAME to the element E
    var C = $(E).className;
    if (typeof C != undefined) {
        if (C.indexOf(clName) >= 0) return;
        $(E).className = C + " " + clName;
    }
}
function remClass(E, clName) {
    var C = $(E);
    if (C != null) C = C.className;
    else return;
    if (typeof C != undefined) {
        if (C.indexOf(clName) < 0) return;
        var newC = '';
        C = C.split(' ');
        for (var i = 0; i < C.length; i++) {
            if (C[i] != clName) {
                newC = newC + C[i] + " ";
            }
        }
        $(E).className = newC;
    }
}
