/**
 *
 *
 *
 * (c)2006 Jimmy Moore
 */

var timelineElement;
var timelineElementX;
var timelineElementY;
var timelineWidth = 700;        // Hard coded for now...
var timelineHeight = 300;

timeline = new TimelineGroup();
var startd = new Date(Date.UTC(1900, 0, 0, 0, 0, 0, 0));
var endd = new Date(Date.UTC(2000, 0, 0, 0, 0, 0, 0));

function initui() {
    timelineElement = document.getElementById("timeline");
    timelineElementX = findPosX(timelineElement);
    timelineElementY = findPosY(timelineElement);
    
    // pre-load images
    i1 = new Image();
    i1.src = "arrow1_e.gif";
    i2 = new Image();
    i2.src = "arrow1_w.gif";
    
    if (window.addEventListener) {
        window.addEventListener("resize", resizeHandler, true);
    } else {                // For IE (eugh)
        window.attachEvent("onresize", resizeHandler);
        // TODO: Maybe support IE4
    }
}

/**
 * Keeps the items on the timeline...
 *
 */
function resizeHandler(event) {
    timelineElement = document.getElementById("timeline");
    timelineElementX = findPosX(timelineElement);
    timelineElementY = findPosY(timelineElement);
    refreshUI();
}

function clearTimeline() {
    children = timelineElement.childNodes;
    for(i=0;i<children.length;i++) {
        if (children[i].id=="moreright"
         || children[i].id=="moreleft"
         || children[i].className=="midline") {
        } else {
            timelineElement.removeChild(children[i]);
            i--;        // Adjust i
        }
    }
    for (i=0;i<timeline.events.length;i++) {
        delete timeline.events[i].element;
        delete timeline.events[i].selement;
    }
    clearMarkers();
}

function clearMarkers() {
    markers = new Array();
    markerst = new Array();
}

/**
 * Add a marker on the timeline.
 * p = horizontal position
 * t = text to display under the marker.
 * n = 0-number needed...
 */
var markers = new Array();      // This holds all the marker elements in use.
var markerst = new Array();     // This holds all the marker text elements in use.

function addMarker(p, t, n) {
    var addThem = false;
    midy = Math.floor(timelineHeight/2);
    if (n >= markers.length) {
        mk = document.createElement("div");
        mk.className = "marker";
        mk.style.top = (timelineElementY + midy - 5) + "px";
        markers.push(mk);

        mkt = document.createElement("div");
        mkt.className = "date";
        mkt.style.width = "50px";
        mkt.style.top = (timelineElementY + midy + 5) + "px";
        markerst.push(mkt);
        addThem = true;
    }

    markers[n].style.left = (timelineElementX + p) + "px";

    markerst[n].style.left = (timelineElementX + p - 25) + "px";       // 25 and 50 will do for current font.
    markerst[n].innerHTML = t;
    
    if (addThem) {
        timelineElement.appendChild(markers[n]);
        timelineElement.appendChild(markerst[n]);
    }
}

/**
 * TODO: Tidy up year markers, allow higher res.
 * TODO: Add day markers possibly for big zoom ins
 */
function showMarkers(sd, ed) {
    yearRange = ed.getUTCFullYear() - sd.getUTCFullYear();
    step = 1;
    startYear = sd.getUTCFullYear();
    endYear = ed.getUTCFullYear();
    maxDivs = 20;
    
    if (yearRange > 2) {
        if (yearRange > maxDivs) {step = 5; startYear = Math.floor((startYear+4) / 5) * 5;}
        if (yearRange > maxDivs*5) {step = 10; startYear = Math.floor((startYear+9) / 10) * 10;}
        if (yearRange > maxDivs*10) {step = 50; startYear = Math.floor((startYear+49) / 50) * 50;}
        if (yearRange > maxDivs*50) {step = 100; startYear = Math.floor((startYear+99) / 100) * 100;}
        if (yearRange > maxDivs*100) {step = 500; startYear = Math.floor((startYear+499) / 500) * 500;}
        if (yearRange > maxDivs*500) {step = 1000; startYear = Math.floor((startYear+999) / 1000) * 1000;}
        // Some testing to show a marker...
        // Do the years...
    
        var n = 0;
        for (i=startYear;i<=endYear;i+=step) {
            p = new Date(Date.UTC(i, 0, 1, 0, 0, 0, 0));
            tof = getTimeOffset(p, startd, endd, timelineWidth);
            if (tof) addMarker(tof, i, n++);
        }
        
        removeExcessMarkers(n);
    } else {        // Do months instead...
        var monthNames = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
        var s = new Date(Date.UTC(startd.getUTCFullYear(), startd.getUTCMonth(), 1, 0, 0, 0, 0));
        
        var n = 0;
        while(s.getTime() < endd.getTime()) {
            var dispName = monthNames[s.getUTCMonth()];
            if (s.getUTCMonth()==0) dispName = dispName + " " + s.getUTCFullYear();
            tof = getTimeOffset(s, startd, endd, timelineWidth);
            if (tof) addMarker(tof, dispName, n++);
            // advance by a month...
            var month = s.getUTCMonth() + 1;
            if (month==12) {
                month=0;
                s.setUTCFullYear(s.getUTCFullYear()+1);
            }
            s.setUTCMonth(month);
        }
        removeExcessMarkers(n);
    }
}

function removeExcessMarkers(n) {
    // TODO: Perhaps we should keep them for later? Just set to display:none?
    while(markers.length > n) {
        timelineElement.removeChild(markers.pop());
        timelineElement.removeChild(markerst.pop());
    }
}

/**
 * Add an event to the timeline.
 *
 */
function addItem(startDate, endDate, i, p) {
    px = i.getOffset(startDate, endDate, timelineWidth)
    if (px==null || !i.shouldDisplay(startDate, endDate)) {
        if (i.element!=null) {
            timelineElement.removeChild(i.selement);
            timelineElement.removeChild(i.element);
            i.selement = null;
            i.element = null;
        }
        return;        // Off screen
    }

    midy = Math.floor(timelineHeight / 2);
    
    hh = 24;        // Height of each item element
    
    if (p<0) {
        m3 = -(hh*p);
        m1 = midy - m3;
        m2 = m1 - 10;
    } else {
        m1 = midy;
        m3 = hh*p;
        m2 = m1 + m3;
    }

    addthem = false;
    if (i.element==null) {
        i.element = document.createElement("div");
        i.element.setAttribute("title", i.date);
        i.element.className = "item";
        i.element.innerHTML = i.shorttext;
        i.element.style.zIndex = 6;
        i.element.style.border = "1px solid " + i.bcolor;        // TODO?
        i.element.style.background = i.color;
        
        if (i.element.addEventListener) {
            i.element.addEventListener("mousemove", showdet, true);
        } else {        // For IE.
            i.element.setAttribute("onmousemove", showdet);
        }
        i.selement = document.createElement("div");
        i.selement.className = "itemmarker";
        i.selement.style.zIndex = 5;
        i.selement.style.background = i.bcolor;

        // Check if it's the selected one.
        if (selectedElement==null || i.element.innerHTML==selectedText) {        // TODO: ID properly
            highlightItem(i, true);
            selectedText = i.element.innerHTML;
            if (selectedElement==null) {
                showDetails(selectedText);
            }
            selectedElement = i.element;
        }
        //
        addthem = true;
    }
    i.element.style.left = (timelineElementX + px - 5) + "px";
    i.element.style.top = (timelineElementY + m2) + "px";

    i.selement.style.left = (timelineElementX + px) + "px";
    i.selement.style.top = (timelineElementY + m1) + "px";
    i.selement.style.height = m3 + "px";

    if (addthem) {
        timelineElement.appendChild(i.element);
        timelineElement.appendChild(i.selement);
    }
}

function findItem(e) {
    for(i=0;i<timeline.events.length;i++) {
        if (timeline.events[i].element==e) return timeline.events[i];       // Found it...
    }
    return null;
}

function highlightItem(e, b) {
    if (!e) return;     // Nothing to highlight...
    if (b) {
//        e.element.style.background = "#ffff00";
        e.element.style.border = "1px solid red";
        e.selement.style.background = "#ff0000";
    } else {
        e.element.style.background = e.color;
        e.element.style.border = "1px solid " + e.bcolor;
        e.selement.style.background = e.bcolor;
    }
}

function refreshUI() {
    showTimeline(startd, endd, timeline);
}

function showTimeline(sd, ed, tl) {
    timeline = tl;              // so we know.
    startd = sd;
    endd = ed;
    showMarkers(sd, ed);      // Show the markers
    
    r = 4;
    
    countleft = 0;
    countright = 0;

    endtime = ed.getTime();
    starttime = sd.getTime();
    
    for (i=0;i<tl.events.length;i++) {
        if (tl.events[i].date.getTime() > endtime) countright++;
        if (tl.events[i].date.getTime() < starttime) countleft++;
        addItem(sd, ed, tl.events[i], r);
        r = -r;
        if (r==4) r = 3;
        else if(r==3) r = 2
        else if(r==2) r = 1;
        else if(r==1) r = 4;
    }
    
    // if needed add divs for left/right...
    if (countright>0) {
        mk = document.getElementById("moreright");
        mk.style.top=timelineElementY;
        mk.style.left=timelineElementX + 350;       // TODO: Only need to do this once.
        if (countright>1) pp = "s"; else pp = "";
        mk.innerHTML = countright + " more event"+pp+" <img src=arrow1_e.gif>";
    } else {
        mk = document.getElementById("moreright");
        mk.innerHTML = "";
    }
    if (countleft>0) {
        mk = document.getElementById("moreleft");
        mk.style.top=timelineElementY;
        mk.style.left=timelineElementX;
        if (countleft>1) pp = "s"; else pp = "";
        mk.innerHTML = "<img src=arrow1_w.gif> " + countleft + " more event" + pp;
    } else {
        mk = document.getElementById("moreleft");
        mk.innerHTML = "";
    }
}

/**
 * Show date under mouse...
 *
 */
function moveover(i, event) {
    ox = event.clientX - timelineElementX;
    dr = endd.getTime() - startd.getTime();
    date = new Date(startd.getTime() + (ox * dr / timelineWidth));
    document.getElementById("timelinestatus").innerHTML = date;
}

/*******************************************************************************
 * Handle the main drag movement for the timeline...
 *
 */
var grabX, grabY;
var grabStartd, grabEndd;
var grabDate;
 
function doMove(event, fin) {
    ny = (event.clientY - grabY);
    nx = (event.clientX - grabX);
    // nx and ny are the deltas from the start of the drag...
    tr = endd.getTime() - startd.getTime();     // time range (current)
    trl = grabDate.getTime() - grabStartd.getTime();
    trr = grabEndd.getTime() - grabDate.getTime();
    p = tr * nx / timelineWidth;
    zl = trl * ny / timelineHeight;
    zr = trr * ny / timelineHeight;
    
    startd = new Date(grabStartd.getTime() - p - zl);
    endd = new Date(grabEndd.getTime() - p + zr)
    showTimeline(startd, endd, timeline);
}

function moveHandler(event) {
    doMove(event, false);
    stopEventPropagation(event);
}

function upHandler(event) {
    // This is ok, as IE uses the global 'event'...
    if (document.removeEventListener) {
        document.removeEventListener("mouseup", upHandler, true);
        document.removeEventListener("mousemove", moveHandler, true);
    } else {
        document.detachEvent("onmouseup", upHandler);
        document.detachEvent("onmousemove", moveHandler);
    }
    stopEventPropagation(event);
    doMove(event, true);
    timelineElement.style.cursor = "auto";
}

function mousedown(i, event) {
    if (document.addEventListener) {
        document.addEventListener("mousemove", moveHandler, true);
        document.addEventListener("mouseup", upHandler, true);
    } else {                // For IE (eugh)
        document.attachEvent("onmousemove", moveHandler);
        document.attachEvent("onmouseup", upHandler);
        // TODO: Maybe support IE4
    }
    grabX = event.clientX;
    grabY = event.clientY;
    grabStartd = startd;
    grabEndd = endd;
    timelineElement.style.cursor="move";
    stopEventPropagation(event);
    dr = endd.getTime() - startd.getTime();
    grabDate = new Date(startd.getTime() + ((grabX - timelineElementX) * dr / timelineWidth));
}

