var viewer = null;
var zoomInteractiveThreshold = null;
var _interactiveMessage;
var _messageCloseText;
var _editUrl;
var _partnerChooserTitle;
var partnerChooser = null;
var partnerChooserActive = false;
var _unknownName;
var _tree;
var _width;
var _height;
var _verticalRatioInteractiveThreshold;
var _baseUrl;
var _node;
var _highlight;
var _horizontalNodePadding;
var _verticalNodePadding;
var _demoNodes;
var _currentDemoNode = 0;
document.write(unescape("%3Cscript src='http://seadragon.com/ajax/0.8/seadragon-min.js' type='text/javascript'%3E%3C/script%3E"));
function initVisualization(zoomIconsPath, interactiveMessage, messageCloseText, editUrl, editText, legend, partnerChooserTitle, unknownName, tree, width, height, verticalRatioInteractiveThreshold, baseUrl, node, highlight, horizontalNodePadding, verticalNodePadding, demoNodes) {
    Seadragon.Config.imagePath = zoomIconsPath;
    _interactiveMessage = $(interactiveMessage).hide();
    _messageCloseText = messageCloseText;
    _editUrl = editUrl;
    _partnerChooserTitle = partnerChooserTitle;
    _unknownName = unknownName;
    _tree = tree;
    _width = width;
    _height = height;
    _verticalRatioInteractiveThreshold = verticalRatioInteractiveThreshold;
    _baseUrl = baseUrl;
    _node = node;
    _highlight = highlight;
    _horizontalNodePadding = horizontalNodePadding;
    _verticalNodePadding = verticalNodePadding;
    _demoNodes = demoNodes;
    viewer = new Seadragon.Viewer("visualization");
    viewer.addEventListener("open", onOpen);
    viewer.addEventListener("animation", checkInteractiveMode);
    viewer.addEventListener("resize", checkInteractiveMode);
    viewer.addEventListener("resize", onViewerResize);
    viewer.addControl(_interactiveMessage[0], Seadragon.ControlAnchor.TOP_LEFT);
    var editButton = new Seadragon.Button(editText, zoomIconsPath + "edit_rest.png", zoomIconsPath + "edit_grouphover.png", zoomIconsPath + "edit_hover.png", zoomIconsPath + "edit_pressed.png", null, goEdit, null, null, null); 
    viewer.getNavControl().appendChild(editButton.elmt);
    viewer.addControl($(legend)[0], Seadragon.ControlAnchor.BOTTOM_LEFT);
    viewer.openDzi(baseUrl + "images/tree_" + tree + ".xml", '<Image TileSize="256" Overlap="1" Format="jpg" xmlns="http://schemas.microsoft.com/deepzoom/2008"><Size Width="' + width + '" Height="' + height + '"/></Image>');
}
function goEdit() {
    window.location.href = _editUrl;
}
function onOpen() {
    //var tracker = new Seadragon.MouseTracker(viewer.elmt);
    //tracker.clickHandler = function(tracker, position, quick, shift) {
    //    if (quick)
    //        checkNode(position);
    //};
    //tracker.setTracking(true);
    Seadragon.Utils.addEvent(viewer.elmt, "click", checkNode);
    zoomInteractiveThreshold = _verticalRatioInteractiveThreshold * _width / viewer.viewport.getContainerSize().x;
    if (_demoNodes.length > 0) {
        timerId = window.setTimeout(startDemoAnimation, 3000);
        Seadragon.Utils.addEvent(viewer.elmt, "click", stopDemoAnimation);
        Seadragon.Utils.addEvent(viewer.elmt, "mousewheel", stopDemoAnimation);
    } else if (_node != null) {
        navigateTo((_node.x + _node.width/2) / _width, (_node.y + _node.height/2) / _width, zoomInteractiveThreshold/2);
        if (_highlight) {
            var highlight = document.createElement("img");
            highlight.src = 'https://atimages.s3.amazonaws.com/highlight.png';
            viewer.drawer.addOverlay(highlight, new Seadragon.Rect((_node.x - _horizontalNodePadding)/_width, (_node.y - _verticalNodePadding)/_width, (_node.width + 2*_horizontalNodePadding)/_width, (_node.height + 2*_verticalNodePadding)/_width));
        }
    }
}
function onViewerResize(viewer) {
    if (viewer.isFullPage()) {
        var style = viewer.elmt.firstChild.style;
        style.backgroundColor = "white";
        style.color = "black";
    }
}
var _startTime;
var _startBounds;
var _targetBounds;
var _endTime;
var _timerId = 0;
var _newTransitionTimerId = 0;
var _p = 1.4;
var _c0, _c1, _cDiffX, _cDiffY, _u1, _r0, _r1, _S;
function startDemoAnimation() {
    _newTransitionTimerId = 0;
    var node = _demoNodes[_currentDemoNode];
    _currentDemoNode = (_currentDemoNode + 1) % _demoNodes.length;
    var targetWidth = 2 / zoomInteractiveThreshold;
    var targetHeight = targetWidth / viewer.viewport.getAspectRatio();
    transitionTo(new Seadragon.Rect((node.x + node.width/2) / _width - targetWidth/2, (node.y + node.height/2) / _width - targetHeight/2, targetWidth, targetHeight));
}
function stopDemoAnimation() {
    Seadragon.Utils.removeEvent(viewer.elmt, "click", stopDemoAnimation);
    Seadragon.Utils.removeEvent(viewer.elmt, "mousewheel", stopDemoAnimation);
    if (_timerId > 0)
        window.clearInterval(_timerId);
    if (_newTransitionTimerId > 0)
        window.clearTimeout(_newTransitionTimerId);
}
/**
 * Transitions smoothly to the given bounds.
 */
function transitionTo(bounds) {
    _startTime = new Date().getTime();
    _startBounds = viewer.viewport.getBounds();
    _targetBounds = bounds;
    _c0 = new Seadragon.Point(_startBounds.x + _startBounds.width/2, _startBounds.y + _startBounds.height/2);
    _c1 = new Seadragon.Point(_targetBounds.x + _targetBounds.width/2, _targetBounds.y + _targetBounds.height/2);
    _cDiffX = _c1.x - _c0.x;
    _cDiffY = _c1.y - _c0.y;
    _u1 = Math.sqrt(Math.pow(_cDiffX,2) + Math.pow(_cDiffY,2));
    _r0 = _r(_b0(_u1, _startBounds.width, _targetBounds.width));
    _r1 = _r(_b1(_u1, _startBounds.width, _targetBounds.width));
    _S = (_r1 - _r0) / _p;
    _endTime = _startTime + _S * 2000;//_startTime + 3000;
    _timerId = window.setInterval(updateTransition, 10);
}
/**
 * Updates the viewport based on the current state of the transition.
 */
function updateTransition() {
    var progress = (new Date().getTime() - _startTime) / (_endTime - _startTime);
    viewer.viewport.fitBounds(transform(progress), true);
    if (progress >= 1) {
        window.clearInterval(_timerId);
        _timerId = 0;
        _newTransitionTimerId = window.setTimeout(startDemoAnimation, 10000);
    }
}
function _b0(u1, startSize, endSize) {
    return (Math.pow(endSize,2) - Math.pow(startSize,2) + Math.pow(_p,4) * Math.pow(u1,2)) / (2 * startSize * Math.pow(_p,2) * u1);
}
function _b1(u1, startSize, endSize) {
    return (Math.pow(endSize,2) - Math.pow(startSize,2) - Math.pow(_p,4) * Math.pow(u1,2)) / (2 * endSize * Math.pow(_p,2) * u1);
}
function _r(b) {
    return Math.log(-b + Math.sqrt(Math.pow(b,2) + 1));
}
function _u(s, startSize, r0) {
    return (startSize/Math.pow(_p,2)) * (cosh(r0) * sinh(_p*s + r0) / cosh(_p*s + r0) - sinh(r0));
}
function _w(s, startSize, r0) {
    return startSize * cosh(r0) / cosh(_p*s + r0);
}
function cosh(x) {
    return (Math.exp(x) + Math.exp(-x)) / 2;
}
function sinh(x) {
    return (Math.exp(x) - Math.exp(-x)) / 2;
}
/**
 * Given a value between 0 and 1, returns the bounds the viewport should be at.
 */
function transform(progress) {
    if (progress <= 0)
        return _startBounds;
    else if (progress >= 1)
        return _targetBounds;
    var s = progress * _S;
    var u = _u(s, _startBounds.width, _r0);
    var w = _w(s, _startBounds.width, _r0);
    var h = w/(_startBounds.width/_startBounds.height);
    return new Seadragon.Rect(_c0.x + _cDiffX * u / _u1 - w/2, _c0.y + _cDiffY * u / _u1 - h/2, w, h);
}
function navigateTo(x, y, zoom) {
    removePartnerChooser();
    //    partnerChooser.dialog("destroy").remove();
    viewer.viewport.panTo(new Seadragon.Point(x, y), false);
    viewer.viewport.zoomTo(zoom, null, false);
}
function checkNode(event) {
    if (!partnerChooserActive && viewer.viewport.getZoom(true) >= zoomInteractiveThreshold) {
        var point = viewer.viewport.pointFromPixel(Seadragon.Utils.getMousePosition(event).minus(Seadragon.Utils.getElementPosition(viewer.elmt)));
        $.get("ajax/zoomable_tree_click.xml", {x: (point.x * viewer.source.dimensions.x).toFixed(0), y: (point.y * viewer.source.dimensions.x).toFixed(0), tree: _tree}, function(xml) {
            var nodeLinks = $("node-link", xml);
            if (nodeLinks.size() == 1)
                navigateTo((parseInt(nodeLinks.attr("x")) + nodeLinks.attr("width")/2) / _width, (parseInt(nodeLinks.attr("y")) + nodeLinks.attr("height")/2) / _width, zoomInteractiveThreshold/2);
            else if (nodeLinks.size() > 1)
                choosePartner(nodeLinks);
            else if ($("profile-id", xml).size() == 1)
                window.location.href = $("profile-id", xml).text();
        });
    }
}
function choosePartner(nodeLinks) {
    var links = $('<ul></ul>');
    nodeLinks.each(function(i) {
        var nextToPartner = nodeLinks.eq(i).attr("next-to-partner") == null ? _unknownName : nodeLinks.eq(i).attr("next-to-partner");
        links.append('<li><a href="javascript:navigateTo(' + (parseInt(nodeLinks.eq(i).attr("x")) + nodeLinks.eq(i).attr("width")/2) / _width + ',' + (parseInt(nodeLinks.eq(i).attr("y")) + nodeLinks.eq(i).attr("height")/2) / _width + ',' + zoomInteractiveThreshold/2 + ')">' + nextToPartner + '</a></li>');
    });
    var partnerChooserBox = $('<table class="message control"><tbody><tr><td class="top_left"></td><td class="top"></td><td class="top_right"></td></tr><tr><td class="left"></td><td class="center"><a href="javascript:removePartnerChooser();"><img src="' + _baseUrl + 'images/message_close.png" class="close" width="9" height="9" alt="' + _messageCloseText + '" title="' + _messageCloseText + '"/></a><h3>' + _partnerChooserTitle + '</h3><ul>' + links.html() + '</ul></td><td class="right"></td></tr><tr><td class="bottom_left"></td><td class="bottom"></td><td class="bottom_right"></td></tr></tbody></table>');
    var underlay = $('<div class="underlay"></div>');
    partnerChooser = $('<div class="partner_chooser"></div>').append(underlay).append(partnerChooserBox);
    partnerChooserActive = true;
    underlay.click(removePartnerChooser);
    viewer.addControl(partnerChooser[0], Seadragon.ControlAnchor.NONE);
    partnerChooserBox.css("top", viewer.viewport.getContainerSize().y/2 - partnerChooserBox.get()[0].offsetHeight/2).css("left", viewer.viewport.getContainerSize().x/2 - partnerChooserBox.get()[0].offsetWidth/2);
}
function removePartnerChooser() {
    if (partnerChooser != null) {
        viewer.removeControl(partnerChooser[0]);
        partnerChooserActive = false;
    }
}
function checkInteractiveMode() {
    if (viewer.viewport.getZoom(true) >= zoomInteractiveThreshold)
        _interactiveMessage.fadeIn("slow");
    else
        _interactiveMessage.fadeOut("slow");
}
