﻿function CoverFlow() {
    var _this = this;
    var _pointer = null;
    var _items = [];
    var _overlays = [];
    var _frameSize = { 'width': 0, 'height': 0 };
    var _scaleFactor = 0.4;
    var _imagesLoaded = 0;
    var _globalOffset = 0;
    var _speed = 12;
    var _spacing = 135;
    var _perspective = 80;
    var _isMouseDown = false;
    var _isDragging = false;
    var _dragMode = 0;
    var _trayElement, _trackElement;
    var _currentIndex = 0;
    var _isAnimating = false;
    var _isFullScreen = false;
    var _isDisplayOnly = false;
    var _startupIndex = -1;

    this.$$ = function(id) {
        return document.getElementById(id);
    }
    this.PublicReference = function(name) {
        _pointer = name;
    }
    this.FrameSize = function(width, height) {
        _frameSize.width = width;
        _frameSize.height = height;
    }
    this.AddItem = function(obj) {
        _items.push(obj);
    }
    this.AddOverlay = function(obj) {
        _overlays.push(obj);
    }
    this.DragMode = function(mode) {
        _dragMode = mode;
    }
    this.CellWidth = function(width) {
        _spacing = width;
    }
    this.ScaleFactor = function(scale) {
        _scaleFactor = scale;
    }
    this.Perspective = function(value) {
        _perspective = value;
    }
    this.Speed = function(value) {
        _speed = value;
    }
    this.DisplayOnly = function() {
        _isDisplayOnly = true;
    }
    this.StartingIndex = function(index) {
        _startupIndex = index;
    }
    this.ProcessLoadedImage = function(item, index) {
        _imagesLoaded++;
        var bar = _this.$$('_FlowLoadingBar_' + _pointer);
        bar.style.width = ((_imagesLoaded / _items.length) * 100) + '%';

        if (index != null && item != null) {
            _items[index].totalWidth = item.width;
            _items[index].totalHeight = item.height;
        }
        if (_imagesLoaded == (_items.length + _overlays.length)) {
            var offset = 0;
            for (var i = 0; i < _items.length; i++) {
                _this.$$('_FlowItem_' + _pointer + '_' + i).style.marginLeft = offset + 'px';
                _items[i].left = offset;
                _items[i].top = 0;
                _items[i].scale = 1;
                offset += _spacing;
            }

            setTimeout(
                function() {
                    _this.Slide(_startupIndex);
                    _this.$$('_FlowLoadingBarRegion_' + _pointer).style.display = 'none';

                    if (!_isDisplayOnly) {
                        _this.$$('_FlowItemBox_' + _pointer).style.visibility = 'visible';
                    }
                }
            , 100);
        }
    }
    this.GetPosition = function(index) {
        return -(_spacing * index) - ((_items[0].width * _scaleFactor) / 2) + (_frameSize.width / 2) + (_spacing / 2);
    }
    this.Refresh = function() {
        var center = (_frameSize.width / 2);

        for (var i = 0; i < _items.length; i++) {
            var position = (_spacing * i) + _globalOffset;
            var item = _this.$$('_FlowItem_' + _pointer + '_' + i);
            var scale = 1;

            if (position < center) {
                scale = (position / center);
            } else if (position > center) {
                scale = (1 - ((position - center) / center));
            }

            if (scale < _scaleFactor) scale = _scaleFactor;
            if (scale == _items[i].scale) continue;

            var height = Math.floor(_items[i].totalHeight * scale);
            item.style.height = height + 'px';

            item.style.zIndex = Math.ceil(height + 10);

            var fromCenter = _items[i].left - (item.width / 2);
            item.style.marginLeft = fromCenter + 'px';
            item.style.marginTop = (_perspective * (1 - scale)) + 'px'
            _items[i].scale = scale;
        }
    }
    this.DragCoverFlow = function(mode, e) {
        if (!_isMouseDown && mode == 'down') {
            _isMouseDown = true;
            return;
        } else if (_isMouseDown && mode == 'move') {
            var posx = 0;
            var center = (_frameSize.width / 2);

            if (!e) var e = window.event;

            if (e.pageX)
                posx = e.pageX;
            else if (e.clientX)
                posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;

            _globalOffset = ((-posx / _frameSize.width) * _items[_items.length - 1].left) + _items[_items.length - 1].width;

            window.status = _globalOffset;

            if (_dragMode == 1) _trayElement.style.marginLeft = _globalOffset + 'px';
            

            _this.Refresh();

        } else if (mode == 'up') {
            _isMouseDown = false;
            return;
        }
    }
    this.Slide = function(targetIndex) {
        var from = _globalOffset;
        var to = _this.GetPosition(targetIndex);
        var direction = ((from > to) ? 'left' : 'right');
        var offSet = _speed;

        if (from == to) return;
        _isAnimating = true;
        _timer = setInterval(
            function() {
                if (direction == 'right') {
                    if (from + offSet > to) {
                        clearInterval(_timer);
                        _isAnimating = false;
                        _currentIndex = targetIndex;
                        from = to;
                    } else {
                        from += offSet;
                    }
                } else {
                    if (from - offSet < to) {
                        clearInterval(_timer);
                        _isAnimating = false;
                        _currentIndex = targetIndex;
                        from = to;
                    } else {
                        from -= offSet;
                    }
                }
                _globalOffset = from;
                if (_dragMode == 1) _trayElement.style.marginLeft = _globalOffset + 'px';
                _this.Refresh();
            }
        , 1);
    }
    this.SelectItem = function(index) {
        if (_isAnimating) return;
        if (_currentIndex != index) {
            _this.Slide(index);
        } else {
            if (!_isDisplayOnly) {
                _this.ShowScreenshot(index);
            }
        }
    }
    this.ShowScreenshot = function(index) {
        _isFullScreen = true;
        var _index = index;
        var top = _items[index].top;
        var item = _this.$$('_FlowItem_' + _pointer + '_' + index);
        var width = 1;
        var height = 1;
        var maxWidth = (_items[index].full_width + 10);
        var maxHeight = (_items[index].full_height + 40);
        var ratio = maxHeight / maxWidth;
        var growAmount = 65;

        var html = document.getElementsByTagName('HTML')[0];
        var mask = document.createElement('DIV');
        var div = document.createElement('DIV');
        var img = document.createElement('IMG');
        var status = document.createElement('DIV');
        var close = document.createElement('IMG');
        var previous = document.createElement('IMG');
        var next = document.createElement('IMG');

        div.style.overflow = 'hidden';
        div.style.zIndex = 100000;
        div.style.position = 'absolute';
        div.style.width = '0px';
        div.style.height = '0px';
        div.style.left = ((html.clientWidth / 2) - (maxWidth / 2)) + 'px';
        div.style.top = ((html.clientHeight / 2) - (maxHeight / 2)) + 'px';
        div.style.border = 'solid 1px #006479';
        div.style.backgroundColor = '#000000';

        close.onclick = function() {
            var grow = setInterval(
                function() {
                    if (width - growAmount < 0) {
                        width = 0;
                        clearInterval(grow);
                    } else {
                        width -= growAmount;
                        div.style.width = width + 'px';
                        div.style.height = Math.ceil(width * ratio) + 'px';
                    }
                    if (width == 0) {
                        div.style.height = 0 + 'px';
                        clearInterval(grow);
                        document.body.removeChild(div);
                        document.body.removeChild(mask);
                        document.body.style.overflow = 'visible';
                        _isFullScreen = false;
                    }
                }
            , 1);
        };
        close.src = 'res/images/spacer.gif';
        close.className = 'CoverFlow_CloseBtn';
        div.appendChild(close);

        previous.onclick = function() {
            if (_index - 1 >= 0 && !_isAnimating) {
                _index -= 1;
                status.innerHTML = 'Screen ' + (_index + 1) + ' of ' + _items.length;
                img.style.visibility = 'hidden';
                img.onload = function() { img.style.visibility = 'visible'; };
                img.style.width = _items[_index].full_width + 'px';
                img.style.height = _items[_index].full_height + 'px';
                img.src = _items[_index].large;
                _this.SelectItem(_index);
            }
        };
        previous.src = 'res/images/spacer.gif';
        previous.className = 'CoverFlow_PreviousBtn';
        div.appendChild(previous);

        next.onclick = function() {
            if (_index + 1 < _items.length && !_isAnimating) {
                _index += 1;
                status.innerHTML = 'Screen ' + (_index + 1) + ' of ' + _items.length;
                img.style.visibility = 'hidden';
                img.onload = function() { img.style.visibility = 'visible'; };
                img.style.width = _items[_index].full_width + 'px';
                img.style.height = _items[_index].full_height + 'px';
                img.src = _items[_index].large;
                _this.SelectItem(_index);
            }
        };
        next.src = 'res/images/spacer.gif';
        next.className = 'CoverFlow_NextBtn';
        div.appendChild(next);

        img.style.position = 'absolute';
        img.width = _items[index].full_width;
        img.height = _items[index].full_height;
        img.src = _items[index].large;
        img.style.display = 'none';
        img.style.zIndex = 100001;
        img.style.marginTop = '5px';
        img.style.marginLeft = '5px';
        img.onclick = function() {
            var grow = setInterval(
                function() {
                    if (width - growAmount < 0) {
                        width = 0;
                        clearInterval(grow);
                    } else {
                        width -= growAmount;
                        div.style.width = width + 'px';
                        div.style.height = Math.ceil(width * ratio) + 'px';
                    }
                    if (width == 0) {
                        div.style.height = 0 + 'px';
                        clearInterval(grow);
                        document.body.removeChild(div);
                        document.body.removeChild(mask);
                        document.body.style.overflow = 'visible';
                        _isFullScreen = false;
                    }
                }
            , 1);
        }
        img.onload = function() { img.style.display = ''; };
        div.appendChild(img);

        status.id = 'CoverFlow_Status_' + _pointer;
        status.className = 'CoverFlow_Status';
        status.innerHTML = 'Screen ' + (_currentIndex + 1) + ' of ' + _items.length;
        div.appendChild(status);

        mask.className = 'CoverFlow_Mask';

        document.body.insertBefore(mask, document.body.firstChild);
        document.body.insertBefore(div, document.body.firstChild);
        document.body.style.overflow = 'hidden';

        setTimeout(
            function() {
                img.style.display = '';
                var grow = setInterval(
                    function() {
                        if (width + growAmount >= maxWidth) {
                            width = maxWidth;
                            clearInterval(grow);
                        } else {
                            width += growAmount;
                            div.style.width = width + 'px';
                            div.style.height = Math.ceil(width * ratio) + 'px';
                        }
                        if (width == maxWidth) {
                            div.style.height = maxHeight + 'px';
                            div.style.width = maxWidth + 'px';
                            clearInterval(grow);
                        }
                    }
                , 1);
            }
        , 100)

    }
    this.SetElements = function() {
        _trayElement = _this.$$('_FlowItemTray_' + _pointer);
        if (_dragMode == 1) _trayElement.style.marginLeft = _globalOffset + 'px';

        document.onkeyup = function(e) {
            e = (e) ? e : ((window.event) ? event : null);
            if (e) {
                switch (e.keyCode) {
                    case 37:
                        if (_currentIndex - 1 >= 0) _this.SelectItem(_currentIndex - 1);
                        break;
                    case 39:
                        if (_currentIndex + 1 < _items.length) _this.SelectItem(_currentIndex + 1);
                        break;
                }

            }
        }

        if (_startupIndex == -1) {
            _startupIndex = Math.floor(_items.length / 2);
        }
    }
    this.Init = function() {
        var str = '';
        var events = '';
        var ie6 = false;

        if (navigator.appName == 'Microsoft Internet Explorer' && navigator.userAgent.indexOf('Opera', 0) == -1) {
            var key = 'MSIE ', _userAgent = navigator.userAgent, _rightSide = _userAgent.substring(_userAgent.indexOf(key) + key.length), _versionNumber = _rightSide.substring(0, _rightSide.indexOf('.'));
            if (_versionNumber <= 6) ie6 = true;
        }

        //events += ' onmouseover="' + _pointer + '.DragCoverFlow(\'down\',event);" ';
        //events += ' onmousemove="' + _pointer + '.DragCoverFlow(\'move\',event);" ';
        //events += ' onmouseout="' + _pointer + '.DragCoverFlow(\'down\',event);" ';

        str += '<div style="width: ' + _frameSize.width + 'px; height: ' + _frameSize.height + 'px; overflow: hidden;" ' + events + '>';
        str += '<div style="margin-top: ' + ((_frameSize.height / 2) - 10) + 'px; height: 10px; width: ' + (_frameSize.width - 2) + 'px; overflow: hidden; border: solid 1px #FFFFFF;" id="_FlowLoadingBarRegion_' + _pointer + '"><div style="height: 10px; width: 0px; background-color: #FFFFFF;" id="_FlowLoadingBar_' + _pointer + '"></div></div>';

        str += '<div style="position: absolute; visibility: hidden; overflow: hidden; width: ' + _frameSize.width + 'px; height: ' + _frameSize.height + 'px;" ' + events + ' id="_FlowItemBox_' + _pointer + '">';

        for (var i = 0; i < _overlays.length; i++) {
            str += '<div style="position: absolute; z-index: ' + _overlays[i].z + '; margin-left: ' + _overlays[i].x + 'px; margin-top: ' + _overlays[i].y + 'px; background-repeat: no-repeat; background-position: left top; width: ' + _overlays[i].width + 'px; height: ' + _overlays[i].height + 'px; ';
            if (ie6) {
                str += 'filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + _overlays[i].url + '\', sizingMethod=\'crop\'); ';
            } else {
                str += 'background-image: url(' + _overlays[i].url + '); ';
            }
            str += '"></div>';

            //setup to allow for pre-loading.
            str += '<img src="' + _overlays[i].url + '" style="position: absolute; visibility: hidden;" onload="' + _pointer + '.ProcessLoadedImage(null,null);" onerror="' + _pointer + '.ProcessLoadedImage(null,null);" />'
        }

        str += '   <div style="overflow: hidden; width: ' + _frameSize.width + 'px; height: ' + _frameSize.height + 'px;">';
        str += '      <div style="position: absolute;" id="_FlowItemTray_' + _pointer + '">';

        for (var i = 0; i < _items.length; i++) {
            str += '      <img id="_FlowItem_' + _pointer + '_' + i + '" ';
            if (ie6) {
                str += 'src="res/images/spacer.gif" style="position: absolute; cursor: pointer; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + _items[i].small + '\', sizingMethod=\'scale\'); width: 318px; height: 526px;" ';


            } else {
                str += 'src="' + _items[i].small + '" style="position: absolute; cursor: pointer;" ';
            }
            str += 'onerror="' + _pointer + '.ProcessLoadedImage(this,' + i + ');" ';
            str += 'onload="' + _pointer + '.ProcessLoadedImage(this,' + i + ');" ';
            str += 'onclick="' + _pointer + '.SelectItem(' + i + ');" ';
            str += ' />';
        }

        str += '      </div>';
        str += '   </div>';
        str += '</div>';

        str += '</div>';

        document.write(str);

        _this.SetElements();
    }
}