var slide_n = -1;
var apxl = document.implementation.createDocument("", "", null);
var loaded = 0;
var build_queue = [];

function next_thing () { 
    if (build_queue.length > 0) {
        build(build_queue.shift());
    } else if (slide_n > apxl.lastChild.getElementsByTagName("slide").length) {
        alert("End of presentation");
    } else { next_slide() }
}

function next_slide () {
   if (! loaded) { apxl.onload = next_slide; // good hack!
       apxl.load("presentation.xml");
       loaded = 1;
       return;
   } 
   document.slide = apxl.lastChild.getElementsByTagName("slide")[++slide_n];
   document.slide.master = 
        get_master(document.slide.getAttribute("master-slide-id"));
   do_background();
   do_bullets();
   do_drawables();
   prepare_events();
}

function get_master (id) {
    // apxl.getElementById( id ) doesn't work, this is a hack
    if (!document.slidemasters) {
        var masters = apxl.childNodes[0].getElementsByTagName("master-slide");
        var i;
        document.slidemasters = []; // An array? A hash?
        for (i = 0; i < masters.length; i++) {
            document.slidemasters[masters[i].getAttribute("id")] = masters[i];
        }
    }
    return document.slidemasters[id];
}

function do_background () {
    var background =
        document.slide.getElementsByTagName("background-fill-style")[0]
        || document.slide.master.getElementsByTagName("background-fill-style")[0];
    if (background.getAttribute("fill-type") == "image") {
        document.getElementById("body").style.backgroundImage = 
            "url("+background.getAttribute("image-data")+")";
    } else if (background.getAttribute("fill-type") == "color") {
        var col = convert_color(background.getAttribute("fill-color"));
        document.getElementById("body").style.backgroundColor = col;
    } else if (background.getAttribute("fill-type") == "gradient") {
        // Fake it
        background = background.getElementsByTagName("gradient")[0];
        var col = convert_color(background.getAttribute("end-color"));
        document.getElementById("body").style.backgroundColor = col;
    }
}

function do_bullets () {
    document.bullets = document.slide.getElementsByTagName("bullet");
    var ss_bullet = document.getElementById("bullets");
    kill_children(ss_bullet);

    var ss_title = document.getElementById("bullettitle");
    kill_children(ss_title);

    var i;
    var bullet_stack = [ss_bullet];
    for (i = 0; i < document.bullets.length; i++) {
        var bullet = document.bullets[i];
        var content = bullet.getElementsByTagName("content")[0];
        var now_level = bullet.getAttribute("level");
        if (now_level == 0) { // Title
            document.title = content.textContent;
            var content_box = render_content("div", content);
            ss_title.appendChild(content_box);
        } else {
            if (now_level > bullet_stack.length) {
                bullet_stack.push(document.createElement("ul"));
                bullet_stack[bullet_stack.length - 2].appendChild(
                    bullet_stack[bullet_stack.length - 1]
                );
            }
            var li = render_content("li", content);
            bullet_stack[now_level - 1].appendChild(li);
        }
    }
}

function do_drawables () {
    reposition("title", "bullettitle");
    reposition("body", "bullets");
    kill_children(document.getElementById("textboxes"));
    kill_children(document.getElementById("images"));
    do_images(document.slide);
    do_images(document.slide.master);
    do_textboxes(document.slide);
    do_textboxes(document.slide.master);
}

function do_textboxes (which) {
    var drawables = which.getElementsByTagName("textbox");
    var ss = document.getElementById("textboxes");
    var i;
    for (i =0; i < drawables.length; i++) {
        var box = drawables[i];
        var content_box = render_content("div",
            box.getElementsByTagName("content")[0]
        );
        var origin = apply_transformation(0,0,box.getAttribute("transformation"));
        set_position(content_box, origin.x, origin.y);
        if (box.getAttribute("id")) {
            content_box.setAttribute("id", box.getAttribute("id"));
        }
        ss.appendChild(content_box);
    }
}

function reposition(in_xml, in_html) {
    var title = document.slide.getElementsByTagName(in_xml)[0];
    var master_title = document.slide.master.getElementsByTagName(in_xml)[0];
    var ss_title = document.getElementById(in_html);
    var location = (title.getAttribute("location") ||
                   master_title.getAttribute("location")).split(/\s+/);
    set_position(ss_title, location[0], location[1]);
}

function do_images (which) {
    var drawables = which.getElementsByTagName("image");
    var ss = document.getElementById("images");
    var i;
    for (i =0; i < drawables.length; i ++) {
        var image = drawables[i];
        var img = document.createElement("img");
        img.setAttribute("src", image.getAttribute("image-data"));
        if (image.getAttribute("id")) {
            img.setAttribute("id", image.getAttribute("id"));
        }
        var corner = image.getAttribute("natural-size").split(/\s+/);
        var origin = apply_transformation(0,0,image.getAttribute("transformation"));
        var bottom = apply_transformation(corner[0],corner[1],image.getAttribute("transformation"));
        set_position(img, origin.x, origin.y);
        img.setAttribute("width", bottom.x - origin.x);
        img.setAttribute("height", bottom.y - origin.y);
        ss.appendChild(img);
    }
}

function prepare_events () {
    var builds = document.slide.getElementsByTagName("build");
    var i;
    build_queue = [];
    for (i =0; i < builds.length; i ++) {
        var build = builds[i];
        var target_id = build.getAttribute("target-id");
        var type = "in";
        var props = build.getElementsByTagName("property");
        var j;
        for (j=0; j < props.length; j++) {
            if (props[j].getAttribute("animationType") == 2) {
                type = "out";
            }
        }
        // Who am I and what do I apply to?
        var html_target = target_id;
        if (target_id.match(/body/)) { html_target = "bullets" }
        else if (target_id.match(/title/)) { html_target = "bullettitle" }
        var html_elem = document.getElementById(html_target);
        if (!html_elem) { alert("Can't find element "+target_id); return;}
        if (html_target == "bullets") { // XXX hack 
           var bullets = html_elem.getElementsByTagName("li")
           for (j=0; j < bullets.length; j++) {
                html_elem = bullets[j];
                if (type == "in") { html_elem.style.visibility = "hidden"; }
                build_queue.push( { "type": type, "element": html_elem } )
           }
        } else { 
            if (type == "in") { html_elem.style.visibility = "hidden"; }
            build_queue.push( { "type": type, "element": html_elem } )
        }
    }
}

function build(build_spec) {
    if (build_spec.type == "in") { 
        build_spec.element.style.visibility = "visible" 
    } else {  
        build_spec.element.style.visibility = "hidden"
    }
}

// Utility functions
function apply_transformation (x, y, transform) { 
    var o = {"x":0, "y":0};
    if (transform) {
        var coords = transform.split(/\s+/);
        o.x = parseFloat(coords[0]) * x + parseFloat(coords[2]) * y + parseFloat(coords[4]);
        o.y = parseFloat(coords[1]) * x + parseFloat(coords[3]) * y + parseFloat(coords[5]);
    }
    return o;
}

function render_content (tag, content) {
    var elem = document.createElement(tag);
        if (!content) { return elem }
    elem.style.fontSize = content.getAttribute("font-size");
    elem.style.fontFamily = content.getAttribute("font-name");
    elem.style.color = convert_color(content.getAttribute("font-color"));
    //elem.appendChild( document.createTextNode( content.textContent));
    elem.appendChild(content); // It's not really HTML but it's close.
    return elem;
}

function kill_children(node) {
    while (node.childNodes.length > 1) { node.removeChild(node.lastChild); }
}

function set_position (elem, x, y) {
    elem.style.left = x;
    elem.style.top = y;
    elem.style.position = "absolute";
    elem.style.styleFloat = "top";
}

function convert_color (color) {
    if (color == "g1") { return "white" }
    if (!color) {return "black" } // XXX inherit from master
    var stuff = color.split(/\s+/);
    if (stuff.length == 3) {
        var col = "#";
        var i;
        for ( i =0 ; i < 3; i++) {
            col = col + parseInt((stuff[i] * 255).toString()).toString(16);
        }
        return col;
    }
    return "black";
}


