﻿// Copyright 2007 Genoom (Midatel)
// Tree.js v.0.9 Beta (May 2007)

var DRAW_NODES_WITH_IMAGES = 1;

var BOX_WRAPPER_WIDTH = 90;
var BOX_WRAPPER_HEIGHT = 120;

var BOX_WIDTH = 90;
var BOX_HEIGHT = 120;

var PHOTO_WIDTH = 52;
var PHOTO_HEIGHT = 52;

var ADD_RELATIONSHIP_FONT_SIZE = 10;

var LINES_THICKNESS = [1, 0.5, 2];  // thickness with lower zoom, zoom change point, thickness with greater zoom;

var OFFSET_Y = 20;

var MIN_ZOOM = 0.1;
var MAX_ZOOM = 1;
var DELTA_ZOOM = 0.1;

var RENDER_FIRSTNAME_FIRST = true;

var currentUserType = 0;

var zoom = parseInt(readCookie("ZOOM"),10);
if (!zoom || isNaN(zoom) || zoom === "")
    zoom = MAX_ZOOM;
else
    zoom = (zoom / 10);
if (zoom < MIN_ZOOM)
    zoom = MIN_ZOOM
else if (zoom > MAX_ZOOM)
    zoom = MAX_ZOOM;
    
var lastZoom = zoom;
var minDeltaZoom = 0.02;

var family = null;
var cachedNodes = {};
var CACHE = {};

var rendering = false;

var treeHTML = [];
var treeLinesHTML = [];
var treeHiddenNodes = {};
var treeHiddenNodesCount = 0;
var treeHiddenNodesCheckOnly = true;
var peopleMap = {};
var peopleMapIDs = {};
var numberOfNodesPerPerson = {};
var PeopleMapBlockSizeWidth = Math.round(screen.availWidth / 5) + 50;
var PeopleMapBlockSizeHeight = Math.round(screen.availHeight / 5) + 50;
var MaxBlockOffsetBeforeRenderingX = 1;
var MaxBlockOffsetBeforeRenderingY = 1;
var SurroundingBlocksToRenderX = 2 + MaxBlockOffsetBeforeRenderingX;
var SurroundingBlocksToRenderY = 2 + MaxBlockOffsetBeforeRenderingY;
var centerBlock = { "x":0, "y":0};
var RenderPhotos = true;
var RenderLines = true;

var treeStartTime = null;
var treeCreationTime = 0;
var treeDBTime = 0;

var Sizes = {};

var ParentsCache = {};

var RENDER_LINES_NEW_WAY = 1;

var photo_male = "images/icons/tree/male.gif";
var photo_female = "images/icons/tree/female.gif";
var photo_ghost = "images/icons/tree/ghostperson.gif";

var TreeCoords = { "x1":0, "y1":0, "x2":0, "y2":0  }

var LastTreeHiddenNodesCounterExecutor = null;

function paintTree(centerTreeAfterPainting,x,y,zoomChanged)
{
    var HTMLTimerStart = new Date();
    
    rendering = true;
    
    ParentsCache = new Object();
    
    zoom = parseInt(zoom * 100,10) / 100;
    lastZoom = zoom;
    
    document.getElementById("debug").style.zIndex = 10000;
    document.getElementById("debug").innerHTML = '';//zoom;
    document.getElementById("canvas").style.fontSize = (15*zoom) + "px";
    //try { document.getElementById("canvas").removeChild(document.getElementById("tree")); } catch (e) {}
    
    Sizes.AddRelationshipFontSize = parseInt(ADD_RELATIONSHIP_FONT_SIZE * zoom, 10);
    Sizes.AddGosthDataFontSixe = parseInt((ADD_RELATIONSHIP_FONT_SIZE+2) * zoom, 10);
    Sizes.BoxWidth = parseInt(BOX_WIDTH * zoom - 10, 10);
    Sizes.BoxHeight = parseInt(BOX_HEIGHT * zoom - 10, 10);
    Sizes.BoxWrapperWidth = parseInt(BOX_WRAPPER_WIDTH * zoom, 10) - 3;
    Sizes.BoxWrapperHeight = parseInt(BOX_WRAPPER_HEIGHT * zoom, 10) - 3;
    Sizes.PhotoWidth = parseInt(PHOTO_WIDTH * zoom, 10);
    Sizes.PhotoHeight = parseInt(PHOTO_HEIGHT * zoom, 10);
    Sizes.LineThickness = (zoom > LINES_THICKNESS[1] ? LINES_THICKNESS[2] : LINES_THICKNESS[0]);
    
    Sizes.IconTreeWidth = parseInt(20 * zoom, 10);
    Sizes.IconTreeHeight = parseInt(22 * zoom, 10);
    Sizes.IconUpdatable = parseInt(7 * zoom, 10);
    
    treeHTML = [];
    treeLinesHTML = [];
    peopleMap = {};
    peopleMapIDs = {};
    
    if (!zoomChanged)
    {
        treeHiddenNodesCount += 1;
        treeHiddenNodes = {};
        numberOfNodesPerPerson = {};
    }
    
    var cachedInfo = CACHE["ZOOM_"+zoom];
    var start = new Date();
    
    if (typeof(cachedInfo) == "object")
    {
        treeHTML = cachedInfo.treeHTML;
        treeLinesHTML = cachedInfo.treeLinesHTML;
        peopleMap = cachedInfo.peopleMap;
        peopleMapIDs = cachedInfo.peopleMapIDs;
    }
    else if (family)
    {
        var familyNodes = (family ? family.people : []);

        TreeCoords = { "x1":0, "y1":0, "x2":0, "y2":0  }
        
        for (var i=familyNodes.length-1; i>=0; --i)
            paintNode(familyNodes[i], i);

        paintTreeLines(family.lines);
        
        CACHE["ZOOM_"+zoom] = { "treeHTML" : treeHTML,
                                "treeLinesHTML" : treeLinesHTML,
                                "peopleMap" : peopleMap,
                                "peopleMapIDs" : peopleMapIDs };
    }
    
    
    var loadingImage = document.getElementById("loading");
    if (loadingImage)
        loadingImage.style.display = "none";
    
    var HTMLTimerEnd = new Date();
    
    renderVisibleTree();
    
    var end = new Date();

    if (centerTreeAfterPainting)
        centerTree(x,y);

    element_OnMouseOut();
        
    rendering = false;
}


function onCountTreeHiddenPeopleDone(info,context)
{
    var treeHiddenNodesCopy = treeHiddenNodes;
    var treeHiddenNodesCountCopy = treeHiddenNodesCount;
    
    if (context.treeHiddenNodesCount == treeHiddenNodesCountCopy)
    {
        var peopleToUpdate = context.peopleToUpdate;
        
        var count = 0;
        if (info)
        {
            var numPeopleByPerson = info.People;
            treeHiddenNodesCheckOnly = info.CheckOnly;
            
            for (var id in numPeopleByPerson)
            {
                count += 1;
                treeHiddenNodesCopy[id] = numPeopleByPerson[id];
            }
        }

        if (DEBUG_MODE)
        {
            var HiddenPeopleElapsedTime = document.getElementById("HiddenPeopleElapsedTime");
            if (HiddenPeopleElapsedTime)
            {
                HiddenPeopleElapsedTime.innerHTML = (info ? "&nbsp;-&nbsp;" + info.ElapsedTime + " ms" : "");
                HiddenPeopleElapsedTime.style.display = (info ? "" : "none");
            }
        }

        for (var i=0; i<peopleToUpdate.length; i++)
        {
            var id = peopleToUpdate[i];
            var numPeople = treeHiddenNodesCopy[id];
            
            if (numPeople != "0")
            {
                var totalNodes = (numberOfNodesPerPerson[id] || 1);
                for (var k=1; k<=totalNodes; k++)
                {
                    var elem = document.getElementById("numPeople_" + id + "_" + k);
                    if (elem)
                    {
                        elem.innerHTML = "&nbsp;(+" + (treeHiddenNodesCheckOnly ? "" : numPeople) + ")";
                        elem.style.display = "";
                    }
                }
            }
        }

        if (treeHiddenNodesCount == treeHiddenNodesCountCopy)
            treeHiddenNodes = treeHiddenNodesCopy;
    }
}

function getCenterMapBlock()
{
    var treeCenter = getTreeCenter();
    
    var x = parseInt(treeCenter.x / PeopleMapBlockSizeWidth,10);
    var y = parseInt(treeCenter.y / PeopleMapBlockSizeHeight,10);
    
    return {"x" : x, "y" : y};
}


function renderVisibleTree()
{
    var treeHiddenNodesCountCopy = treeHiddenNodesCount;

    centerBlock = getCenterMapBlock();
    var centerBlockKey = "b"+centerBlock.x+","+centerBlock.y;
        
    try { document.getElementById("canvas").removeChild(document.getElementById("tree")); } catch (e) {}


    var cachedInfo = CACHE["ZOOM_"+zoom];
    var cachedTreeBlock = null;
    if ((typeof(cachedInfo) == "object") && (cachedInfo) && (typeof(cachedInfo.TreeBlock) == "object"))
        cachedTreeBlock = cachedInfo.TreeBlock;
        
    var newTree = null;
    var peopleIDs = null;
    if ((typeof(cachedTreeBlock) == "object") && (cachedTreeBlock) && 
                                                 (cachedTreeBlock.BlockKey == centerBlockKey))
    {
        newTree = cachedTreeBlock.Tree;
        peopleIDs = cachedTreeBlock.PeopleIDs;
    }
    else
    {
        var html = [];
        peopleIDs = [];
        for (var bx = centerBlock.x-SurroundingBlocksToRenderX; bx <= centerBlock.x+SurroundingBlocksToRenderX; bx++) {
            for (var by = centerBlock.y-SurroundingBlocksToRenderY; by <= centerBlock.y+SurroundingBlocksToRenderY; by++) {
                var block = peopleMap["b"+bx+","+by];
                if (typeof(block) != "undefined")
                {
                    for (var i=0; i<block.length; i++)
                        html[html.length] = block[i];
                }
                var idList = peopleMapIDs["b"+bx+","+by];
                if (typeof(idList) != "undefined")
                {
                    for (var i=0; i<idList.length; i++)
                        peopleIDs[peopleIDs.length] = idList[i];
                }
            }
        }
        
        for (var i=0; i<treeLinesHTML.length; i++)
            html[html.length] = treeLinesHTML[i];

        newTree = document.createElement("div");
        newTree.id = "tree";
        newTree.innerHTML = html.join("");

        cachedTreeBlock = { "BlockKey" : centerBlockKey,
                            "NumPeople" : html.length,
                            "PeopleIDs" : peopleIDs,
                            "Tree" : newTree };
        if ((typeof(cachedInfo) == "object") && cachedInfo)
            cachedInfo.TreeBlock = cachedTreeBlock;
    }
    
    var peopleRendered = (cachedTreeBlock.NumPeople || 0);

    document.getElementById("canvas").appendChild(newTree);
    
    
    if (DEBUG_MODE)
        document.title = "";
    if (Sizes.AddRelationshipFontSize >= 7)
    {
        var peopleIDsToCalculate = [];
        for (var i=0; i<peopleIDs.length; i++)
        {
            var id = peopleIDs[i].toString();
            if (typeof(treeHiddenNodes[id]) == "undefined")
                peopleIDsToCalculate[peopleIDsToCalculate.length] = id;
        }
        
        var context = { peopleToUpdate: peopleIDs, 
                        treeHiddenNodesCount: treeHiddenNodesCountCopy }
        if (DEBUG_MODE)
            document.title = "Calculating hidden nodes for " + peopleIDsToCalculate.length + " people";
        if (peopleIDsToCalculate.length > 0)
        {
            //ws_Utilities.CountTreeHiddenPeople(peopleIDsToCalculate, onCountTreeHiddenPeopleDone, function() {}, context);
            var wr = Sys.Net.WebServiceProxy.invoke(ws_Utilities.get_path(), "CountTreeHiddenPeople", false, {"people" : peopleIDsToCalculate}, onCountTreeHiddenPeopleDone, function() {}, context);
            LastTreeHiddenNodesCounterExecutor = wr.get_executor();
        }
        else
            setTimeout(function() {onCountTreeHiddenPeopleDone(null, context);},100);
    }

    //document.getElementById("hiddenTree").innerHTML = tree2.join("");

    //document.getElementById("debug").innerHTML = "(" + peopleRendered + " " + RESOURCESHTML.txtPeople + ")</span>&nbsp;";
}


function renderTreeIfNecessary()
{
    var currentCenterBlock = getCenterMapBlock();
    if ((Math.abs(currentCenterBlock.x - centerBlock.x) > MaxBlockOffsetBeforeRenderingX) || 
        (Math.abs(currentCenterBlock.y - centerBlock.y) > MaxBlockOffsetBeforeRenderingY))
        setTimeout(renderVisibleTree,0);
}


function clearTree()
{
    document.getElementById("tree").innerHTML = "";
}


function paintNode(node, nodeNumber)
{
    var mainNode = node.mp;
    var isMale = node.g;
    var id = node.pid;
    var alive = node.al;
    var ghost = node.gh;
    var allowDisplayTree = node.tr;
    var photo_person = node.ph;
    var paintedTwice = node.pt;
    var hasParents = node.hp;
    //var numHiddenNodes = node.getAttribute("hn") | 0;
    
    var userTypeAllowed = ((currentUserType == 1) || (currentUserType == 3));
    
    var coords = getNodeCoords(node, true);
    var coordsWithoutZoom = getNodeCoords(node, false);
    var centerTreeCoords = { x: (coordsWithoutZoom.x + (BOX_WRAPPER_WIDTH/2)),
                             y: (coordsWithoutZoom.y + (BOX_WRAPPER_HEIGHT/2)) };
    
    if (TreeCoords.x1 > coords.x)
        TreeCoords.x1 = coords.x;
        
    if (TreeCoords.x2 < (coords.x + Sizes.BoxWrapperWidth))
        TreeCoords.x2 = coords.x + Sizes.BoxWrapperWidth;
        
    if (TreeCoords.y1 > coords.y)
        TreeCoords.y1 = coords.y;
        
    if (TreeCoords.y2 < (coords.y + Sizes.BoxWrapperHeight))
        TreeCoords.y2 = coords.y + Sizes.BoxWrapperHeight;
    
    
    var name = node.n;
    var surname = node.sn;

    var htmlEncodedName = htmlEncode(name);
    var htmlEncodedSurname = htmlEncode(surname);
    var htmlEncodedFullName = (RENDER_FIRSTNAME_FIRST ? htmlEncodedName + " " + htmlEncodedSurname
                                                      : htmlEncodedSurname + " " + htmlEncodedName);

    var firstLineName = (zoom < 0.3 ? "" : (RENDER_FIRSTNAME_FIRST ? htmlEncodedName : htmlEncodedFullName));
    var secondLineName = (zoom < 0.3 ? "" : (RENDER_FIRSTNAME_FIRST ? htmlEncodedSurname : ""));
    
    var dates = (zoom < 0.9 ? "" : htmlEncode(node.at) || "&nbsp;");
    
    var relationType = (zoom < 0.3 ? "" : "&nbsp;");
    
    var photo_genre = (isMale ? photo_male : photo_female);

    var photo_showed = (photo_person == "" ? photo_genre 
                                           : encodeURI(TREE.FilesURL + photo_person.replace("{0}","_1")));

    var photo = "";
    
    var jsOpenProfileCard = "openProfileCardPopup(" + id + "); return false;"

    if (photo_person == "") 
    {
        photo = (zoom < 0.3 ? "" : 
                    "<img class='photo' " +
                         "width='" + Sizes.PhotoWidth + "px' " +
                         "height='" + Sizes.PhotoHeight + "px' " +
                         "src='" + htmlEncode(photo_showed) + "' " + 
                         "alt='" + RESOURCESHTML.txtAddPhoto + " " + htmlEncodedFullName + "' />");
    }
    else
    {
        photo = (zoom < 0.3 ? "" : 
                        "<img class='photo' " + 
                             "onmouseout='element_OnMouseOut();tree_showHideTooltip(this,true);' " + 
                             "onmousemove='element_OnMouseMove(event,\"" + htmlEncode(jsEncode(encodeURI(TREE.FilesURL + photo_person.replace("{0}","_2")))) + "\");tree_showHideTooltip(this,false);' " +
                             "width='" + Sizes.PhotoWidth + "px' " +
                             "height='" + Sizes.PhotoHeight + "px' " +
                             "src='" + htmlEncode(photo_showed) + "' alt='' />");
    }
    
    var addRelationsLink = "";
    var displayTreeLink = "";
    var deceased = ""; 
      
    if (!alive && !ghost)
    {
        deceased = "deceased";
    }
    
    var lineHeight = parseInt(Sizes.BoxWrapperHeight*0.12,10);
    
    numberOfNodesPerPerson[id] = (numberOfNodesPerPerson[id] || 0) + 1;
    
    displayTreeLink = 
                (!allowDisplayTree || Sizes.AddRelationshipFontSize < 7 ? "" : 
                "<a href='#' class='viewtree' style='min-height:" + lineHeight + "px !important; " +
                                                    "top:" + (Sizes.BoxWrapperHeight-2*lineHeight) + "px; " +
                                                    "left:" + (0) + "px; " +
                                                    "width:" + (Sizes.BoxWrapperWidth) + "px !important; " + 
                                                    "height:" + lineHeight + "px !important; " + 
                                                    "font-size:" + Sizes.AddRelationshipFontSize + "px;' " +
                   "onclick='refreshTree(" + id + "); return false;'>" + RESOURCESHTML.btnViewTree + "<strong id='numPeople_"+id+"_"+numberOfNodesPerPerson[id]+"' style='display:none;' ></strong></a>");

    var marginTop = (zoom < 0.5 ? (6 * zoom) : 6);

    var divTooltip = "";
    var divPerson = "";

    if (ghost)
    {
        var ghostAction = "return false;"

        dates = (zoom < 0.9 ? "" : "&nbsp;");
        
        relationType = (zoom < 0.3 ? "" : "&nbsp;");
                            
        photo = (zoom < 0.3 ? "" :
                     "<a href='#' onclick='" + ghostAction + "'>" + 
                         "<img class='photo' " +
                              "width='" + Sizes.PhotoWidth + "px' " +
                              "height='" + Sizes.PhotoHeight + "px' " +
                              "src='" + photo_ghost + "' alt='?' />" + 
                     "</a>");
   
        divPerson = "<span class='name' style='margin-top:" + marginTop + "px;'>" + 
                        (zoom < 0.3 ? "" : 
                                      "&nbsp;") +
                    "</span>"+ 
                    "<span class='years'>" + dates + "</span>" +
                    (zoom < 0.5 ? "" : "<span class='relation'>&nbsp;</span>") +
                    photo;
    }
    else
    {
        divTooltip = htmlEncodedFullName;

        divPerson = "<a href='#' onclick='" + jsOpenProfileCard + "' class='name' style='margin-top:" + marginTop + "px !important;display:block;white-space:nowrap;'>" + firstLineName + "</a>" +
                    "<span class='surname'>" + secondLineName + "</span>"+
                    "<span class='years'>" + dates + "</span>" +
                    "<a href='#' onclick='" + jsOpenProfileCard + "'>" + photo + "</a>" +
                    "<span class='relation'>&nbsp;</span>" +
                    displayTreeLink;
    }
    
    var genderClass = (isMale ? "boy" : "girl")
                      + (paintedTwice ? (isMale ? " twiceBoy" : " twiceGirl") : "")
                      + (mainNode ? " current" : "");
   

    if (paintedTwice)
        divTooltip += (divTooltip != "" ? "\n" : "") + RESOURCESHTML.txtPersonPaintedTwice;
    
    var div = "<div class='person " + genderClass + " " + deceased + "' title='" + divTooltip + "' " + 
                   "style='overflow:hidden; " +
                          "min-height:"+Sizes.BoxWrapperHeight+"px !important; " +
                          "top:" + coords.y + "px; " +
                          "left:" + coords.x + "px; " +
                          "width:" + Sizes.BoxWrapperWidth + "px !important; " + 
                          "height:" + Sizes.BoxWrapperHeight + "px; !important;'>" + 
                    divPerson + /*numHiddenNodes +*/
              "</div>" ;

    var ix = parseInt(coords.x / PeopleMapBlockSizeWidth,10);
    var iy = parseInt(coords.y / PeopleMapBlockSizeHeight,10);
    var idBlock = "b"+ix+","+iy;
    var peopleArray = peopleMap[idBlock];
    if (typeof(peopleArray) == "undefined")
    {
        peopleArray = [];
        peopleMap[idBlock] = peopleArray;
    }
    var peopleIDsArray = peopleMapIDs[idBlock];
    if (typeof(peopleIDsArray) == "undefined")
    {
        peopleIDsArray = [];
        peopleMapIDs[idBlock] = peopleIDsArray;
    }
    peopleArray[peopleArray.length] = div;
    peopleIDsArray[peopleIDsArray.length] = id;
}


function paintTreeLines(lines)
{
    for (var i=lines.length-1; i>=0; --i)
    {
        var line = lines[i];
        var x1 = parseInt(line.x1 * zoom,10);
        var x2 = parseInt(line.x2 * zoom,10);
        var y1 = parseInt(line.y1 * zoom,10);
        var y2 = parseInt(line.y2 * zoom,10);
        var linetype = line.t;
        var color = line.c;
        var width = 0;
        var height = 0;
        var className = (color == "1" ? "tree-line" : "tree-dottedline");
        
        width = (x2 - x1);
        height = (y2 - y1);
        
        if (width > height)
        {
            height = Sizes.LineThickness;
            width += Sizes.LineThickness;
        }
        else
        {
            width = Sizes.LineThickness;
            height += Sizes.LineThickness;
        }

        treeLinesHTML[treeLinesHTML.length] = "<div style='position:absolute;overflow:hidden;top:";
        treeLinesHTML[treeLinesHTML.length] = y1;
        treeLinesHTML[treeLinesHTML.length] = "px;left:"
        treeLinesHTML[treeLinesHTML.length] = x1;
        treeLinesHTML[treeLinesHTML.length] = "px;width:";
        treeLinesHTML[treeLinesHTML.length] = width;
        treeLinesHTML[treeLinesHTML.length] = "px;height:";
        treeLinesHTML[treeLinesHTML.length] = height;
        treeLinesHTML[treeLinesHTML.length] = "px;' class='";
        treeLinesHTML[treeLinesHTML.length] = className;
        treeLinesHTML[treeLinesHTML.length] = "'></div>";
    }
}

function renderLines(points)
{
    for (var i=1; i<points.length; i++)
    {
        var x1, x2, y1, y2;
        if (points[i].x < points[i-1].x)
        {
            x1 = points[i].x;
            x2 = points[i-1].x;
        }
        else
        {
            x1 = points[i-1].x;
            x2 = points[i].x;
        }
        if (points[i].y < points[i-1].y)
        {
            y1 = points[i].y;
            y2 = points[i-1].y;
        }
        else
        {
            y1 = points[i-1].y;
            y2 = points[i].y;
        }
        var x = x1 * zoom
        var y = y1 * zoom;
        
        var width = (x2 - x1) * zoom + Sizes.LineThickness;
        var height = (y2 - y1) * zoom + Sizes.LineThickness;
        
        if (width > height)
            height = Sizes.LineThickness;
        else
            width = Sizes.LineThickness;
        
        treeHTML[treeHTML.length] = "<div style='position:absolute;overflow:hidden;top:";
        treeHTML[treeHTML.length] = y;
        treeHTML[treeHTML.length] = "px;left:"
        treeHTML[treeHTML.length] = x;
        treeHTML[treeHTML.length] = "px;width:";
        treeHTML[treeHTML.length] = width;
        treeHTML[treeHTML.length] = "px;height:";
        treeHTML[treeHTML.length] = height;
        treeHTML[treeHTML.length] = "px;' class='tree-line'></div>";

//        var div = "<div style='position:absolute;overflow:hidden;" +
//                              "top:" + y + "px;" +
//                              "left:" + x + "px;" +
//                              "width:" + width + "px;" + 
//                              "height:" + height + "px;'" + 
//                              "class='tree-line'" +
//                  "></div>";
//        treeHTML[treeHTML.length] = div;
    }
}

function getNodeCoords(node,withZoom)
{
    var x = node.tx;
    var y = -node.ty;
    
    return {"x": (withZoom ? parseInt(x*zoom,10) : x), "y": (withZoom ? parseInt(y*zoom,10) : y)};
}

function getNode(id)
{
    if (!cachedNodes[id])
        cachedNodes[id] = family.selectSingleNode("/xml/p[@pid='" + id + "']");
    return cachedNodes[id];
}

function selectNodes(node, xpath)
{
    if (window.ie)
        return node.selectNodes(xpath);
    else
        return family.selectNodes(xpath, node);
}

function startTimer()
{
    treeStartTime = new Date();
}

function stopTimer()
{
    if (treeStartTime)
        return (new Date()) - treeStartTime;
    return 0;
}

var clicked = false;
var mousePos = null;
var origPos = null;
var treeCanvas = null;

function mouseDown(e)
{
    if (!clicked && (e.button === Sys.UI.MouseButton.leftButton))
    {
        clicked = true;
        mousePos = getPosition(e);
        origPos = getCanvasCoords();
        document.body.style.cursor = 'pointer';
        preventSelection();
        treeCanvas = document.getElementById("canvas");
    }
}

function mouseUp(e)
{
     if (clicked)
     {
        /*alert("origin: " + TreeCoords.x1 + "," + TreeCoords.y1 + "   final:" + TreeCoords.x2 + "," + TreeCoords.y2 + "\n\n" + 
              "width: " + (TreeCoords.x2-TreeCoords.x1) + "   height:" + (TreeCoords.y2-TreeCoords.y1) + "\n\n" +
              $get("canvas").style.left + "," + $get("canvas").style.top)*/
        clicked = false;
        document.body.style.cursor = 'default';
        allowSelection();
        renderTreeIfNecessary();
     }
}

function mouseMove(e)
{
    if (clicked)
    {
        var pos = getPosition(e);
        var top = origPos.y + (pos.y - mousePos.y);
        var left = origPos.x + (pos.x - mousePos.x);
        /*if (top < -TreeCoords.y1)
            top = -TreeCoords.y1;
        if (left < -TreeCoords.x1)
            left = -TreeCoords.x1;*/
        //setTimeout(function() {
        treeCanvas.style.top = top + "px";
        treeCanvas.style.left = left + "px";
        //            }, 0);
        //document.getElementById("debug").innerHTML = (origPos.y + (pos.y - mousePos.y));
    }
}

function preventSelection()
{
    if (window.ie)
    {
        document.body.ondrag = function () { return false; };
        document.body.onselectstart = function () { return false; };
    }
    else
    {
        document.body.style.MozUserSelect = "none";
        document.getElementById("canvasContainer").style.MozUserSelect = "none";
    }
}

function allowSelection()
{
    if (window.ie)
    {
        document.body.ondrag = null;
        document.body.onselectstart = null;
    }
    else
    {
        document.body.style.MozUserSelect = "";
        document.getElementById("canvasContainer").style.MozUserSelect = "";
    }
}

function zoomChanged(e)
{
    var pos = getPosition(e);
    pos.x = pos.x - 10;
    zoom = 1 - (200 - pos.x)/300;
    $find(ZoomSliderClientID).set_Value(parseInt(zoom*10,10));
    if (Math.abs(zoom-lastZoom) > minDeltaZoom)
        postZoomChanged();    
}


function zoomChanged2()
{
    zoom = $find(ZoomSliderClientID).get_Value() / 10;
    if (Math.abs(zoom-lastZoom) > minDeltaZoom)
        postZoomChanged();    
}


function postZoomChanged()
{
    var oldZoom = lastZoom;
    createCookie("ZOOM", (zoom*10), 90);
    if (!rendering)
    {
        startTimer();
        paintTree(false,null,null,true);
        
        var canvas = document.getElementById("canvas");
        
        var top = canvas.style.top;
        var left = canvas.style.left;
        top = parseInt(top.substring(0,top.length-2));
        left = parseInt(left.substring(0,left.length-2));
        var coords = {"x":left, "y":top}
        
        var el = (window.opera ? document.body : document.documentElement);
	    var docHeight = el.clientHeight-118;
	    var docWidth = el.clientWidth;
	    
	    var oldCenterX = -parseInt((coords.x - docWidth/2)/oldZoom,10);
	    var oldCenterY = -parseInt((coords.y - docHeight/2)/oldZoom,10);
	    
	    /*alert(CENTER_TREE_X);
	    alert(CENTER_TREE_Y);
	    alert(CENTER_TREE_LEFT);
	    alert(CENTER_TREE_TOP);
	    
	    var oldCenterX = CENTER_TREE_X - (coords.x - CENTER_TREE_LEFT);
	    var oldCenterY = CENTER_TREE_Y - (coords.y - CENTER_TREE_TOP);*/
	    
	    centerTree(oldCenterX, oldCenterY);
    }
}


function getZoom()
{
    return zoom;
}


function getCanvasCoords()
{
    var top = document.getElementById("canvas").style.top;
    var left = document.getElementById("canvas").style.left;
    top = parseInt(top.substring(0,top.length-2),10);
    left = parseInt(left.substring(0,left.length-2),10);
    return {"x":left, "y":top};
}


function getTreeCenter()
{
    var el = (window.opera ? document.body : document.documentElement);
 
	var docHeight = el.clientHeight-118;
	var docWidth = el.clientWidth;
	
	var canvasCoords = getCanvasCoords();
	
	return { "x" : parseInt(-canvasCoords.x + (docWidth / 2),10),
	         "y" : parseInt(-canvasCoords.y + (docHeight / 2),10) };
}


function getPosition(e) {
    var posx = 0;
    var posy = 0;
    if (!e) var e = window.event;
    if (e.pageX || e.pageY) 	{
        posx = e.pageX;
        posy = e.pageY;
    }
    else if (e.clientX || e.clientY) 	{
        posx = e.clientX + document.body.scrollLeft
	        + document.documentElement.scrollLeft;
        posy = e.clientY + document.body.scrollTop
	        + document.documentElement.scrollTop;
    }
    return {"x":posx, "y":posy};
}


function onWindowLoad()
{
    $addHandler($get("canvasContainer"), 'mousedown', mouseDown);
    $addHandler($get("canvasContainer"), 'mouseup', mouseUp);
    $addHandler($get("canvasContainer"), 'mousemove', mouseMove);
    var prm = Sys.WebForms.PageRequestManager.getInstance();
    prm.add_beginRequest(onPageRequestManagerBeginRequest)
    setTreeDimensions();
    var img = new Image();
    img.src = photo_male;
    var img = new Image();
    img.src = photo_female;
    var img = new Image();
    img.src = photo_ghost;
}

function addOnPageLoadedHandler(pageLoadedHandler)
{
    Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageLoadedHandler);
}

function removeOnPageLoadedHandler(pageLoadedHandler)
{
    Sys.WebForms.PageRequestManager.getInstance().remove_pageLoaded(pageLoadedHandler);
}

function onPageRequestManagerBeginRequest()
{
    try {
        if ((LastTreeHiddenNodesCounterExecutor != null) && (LastTreeHiddenNodesCounterExecutor.get_started()))
            LastTreeHiddenNodesCounterExecutor.abort();
        LastTreeHiddenNodesCounterExecutor = null;
    }
    catch(e) {}
}


/* mouse wheel */

/** This is high-level function.
 * It must react to delta being more/less than zero.
 */
function onMouseWheel(delta)
{
    if (!rendering)
    {
        if (delta < 0)
        {
            if (zoom > MIN_ZOOM)
            {
                zoom = (zoom - DELTA_ZOOM < MIN_ZOOM ? MIN_ZOOM : zoom - DELTA_ZOOM);
                $find(ZoomSliderClientID).set_Value(Math.round(zoom*10));
                //postZoomChanged();
            }
        }
        else
        {
            if (zoom < MAX_ZOOM)
            {
                zoom = (zoom + DELTA_ZOOM > MAX_ZOOM ? MAX_ZOOM : zoom + DELTA_ZOOM);
                $find(ZoomSliderClientID).set_Value(Math.round(zoom*10));
                //postZoomChanged();
            }
        }
    }
}

/** Event handler for mouse wheel event.
 */
function mouseWheelHandler(event){
        var delta = 0;
        if (!event) /* For IE. */
                event = window.event;
        if (event.wheelDelta) { /* IE/Opera. */
                delta = event.wheelDelta/120;
                /** In Opera 9, delta differs in sign as compared to IE.
                 */
                if (window.opera)
                        delta = -delta;
        } else if (event.detail) { /** Mozilla case. */
                /** In Mozilla, sign of delta is different than in IE.
                 * Also, delta is multiple of 3.
                 */
                delta = -event.detail/3;
        }
        /** If delta is nonzero, handle it.
         * Basically, delta is now positive if wheel was scrolled up,
         * and negative, if wheel was scrolled down.
         */
        if (delta)
                onMouseWheel(delta);
        /** Prevent default actions caused by mouse wheel.
         * That might be ugly, but we handle scrolls somehow
         * anyway, so don't bother here..
         */
        if (event.preventDefault)
                event.preventDefault();
	event.returnValue = false;
}

function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	} else {
		window.onload = function() {
			oldonload();
			func();
		}
	}
}

function addDomLoadedEvent(func)
{
	if (document.all) {
		func();
	} else {
		window.document.addEventListener("DOMContentLoaded", func, true);
	}
}


/** Initialization code. 
 * If you use your own event management code, change it as required.
 */
if (window.addEventListener)
        /** DOMMouseScroll is for mozilla. */
        window.addEventListener('DOMMouseScroll', mouseWheelHandler, false);
/** IE/Opera. */
window.onmousewheel = document.onmousewheel = mouseWheelHandler;


function createCookie(name,value,days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

function eraseCookie(name) {
	createCookie(name,"",-1);
}


var movementInterval = null;

function tree_startMove(event,x,y) {
    var speed = (Sys.Browser.agent == Sys.Browser.InternetExplorer ? 5 : 10);
    var interval = (Sys.Browser.agent == Sys.Browser.InternetExplorer ? 10 : 5);
    event.cancelBubble = true;
    event.returnValue = true;
    if (!movementInterval)
        movementInterval = setInterval("tree_move("+x+","+y+","+speed+")",interval);
}

function tree_cancelMove()
{
    clearInterval(movementInterval);
    movementInterval = null;
}

function tree_move(x,y,speed)
{
    var canvasCoords = getCanvasCoords();
    var canvas = document.getElementById("canvas");
    canvas.style.top = (canvasCoords.y + speed*y) + "px";
    canvas.style.left = (canvasCoords.x + speed*x) + "px";

    renderTreeIfNecessary();
}

function tree_showHideTooltip(img,show)
{
    var container = img.parentNode.parentNode;
    
    if (show)
    {
        if (container.title2 && container.title2 != "")
        {
            container.title = container.title2;
            container.title2 = "";
        }
    }
    else
    {
        if (container.title && container.title != "")
        {
            container.title2 = container.title;
            container.title = "";
        }
    }
}
