// GLIG - core JavaScript functions
//
// Please don't rip this script (it's copyrighted), but if you do
// then don't forget to add a link to our site!

//==============================================================
// Namespaces
//==============================================================

var glig    = (glig ? glig : function() {});
glig.events = (glig.events ? glig.events : function() {});
glig.ui     = (glig.ui ? glig.ui : function() {});
glig.ajax   = (glig.ajax ? glig.ajax : function() {});
glig.ui     = (glig.ui ? glig.ui : function() {});

//==============================================================
// JavaScript utility functions
//==============================================================

// Function borrowed from www.dustindiaz.com adapted - thanks!
// @@@@ DEPRECATED -- use jquery instead
// @@@@ this won't work for multiple classes in same element
//
glig.getElementsByClass = function(classname, tag, node)
{
    var elements = new Array();

    if(node == null)
        node = document;
    if(tag == null)
        tag = "*";

    var matching_tags = node.getElementsByTagName(tag);
    var num_tags = matching_tags.length;

    for (var i = 0; i < num_tags; i++)
    {
        if(matching_tags[i].className == classname)
            elements.push(matching_tags[i]);
    }

    return elements;
}

glig.getFirstElementByClass = function(classname, tag, node)
{
    if(node == null)
        node = document;
    if(tag == null)
        tag = "*";

    var matching_tags = node.getElementsByTagName(tag);
    var num_tags = matching_tags.length;

    for (var i = 0; i < num_tags; i++)
    {
        if(matching_tags[i].className == classname)
            return matching_tags[i];
    }

    return null;
}

glig.isset = function(ob)
{
    return typeof(ob) != "undefined";
}

glig.arrvar = function(arr, avar, def_val)
{
    if(glig.isset(arr[avar]))
        return arr[avar];
    else
        return def_val;
}

glig.is_child_of = function(node, target)
{
    while(node)
    {
        node = node.parentNode;
        if(node == target)
            return true;
    }

    return false;
}

glig.dump = function(ob)
{
    var str = "";
    var value = null;

    if(typeof(ob) == "object")
    {
        str += "{";
        str += "<br>";
        for(var key in ob)
        {
            try
            {
                value = ob[key];
            }
            catch(e)
            {
                value = "(exception)";
            }

            str += key + ": ";

            if(typeof(value) == "object")
                str += glig.dump(value);
            else
                str += value;

            str += "<br>";
        }
        str += "}";
    }
    else
    {
        str += ob;
    }

    return str;
}

glig.redirect = function(url)
{
    window.location.href = url;
}

glig.resolve_target = function(target)
{
    if(typeof(target) == "string")
        return document.getElementById(target);
    else
        return target;
}

glig.create_element = function(tag, cln, parent)
{
    var element = document.createElement(tag);

    if(cln)
    {
        if(cln.substr(0,1) == '#')
            element.id = cln.substr(1);
        else if(cln.substr(0,1) == '.')
            element.className = cln.substr(1);
        else
            element.className = cln;
    }

    if(parent)
        parent.appendChild(element);

    return element;
}

glig.defer = function(code, timeout)
{
    setTimeout(code, timeout || 10);
}

glig.bind = function(fn, wrapper, args)
{
    fn._wrapper = wrapper;
    fn._args = args;
    var fix_scope = function(fn)
    {
        var wrapper = fn._wrapper || window;
        return function() { return fn._args ? fn.apply(wrapper, fn._args) : fn.apply(wrapper); };
    };
    return fix_scope(fn);
}

//==============================================================
// Events
//==============================================================

glig.events.resolve_event = function(e)
{
    // Resolve event object
    e = (e ? e : window.event);

    // Resolve target
    var target = (e.target ? e.target : e.srcElement);

    // Fix for Safari bug in case of text node
    if (target.nodeType == 3)
        target = target.parentNode;

    // Resolve type
    var type = e.type;

    var event =
    {
        "event":  e,
        "target": target,
        "type":   type
    };

    return event;
}

glig.events.resolve_key = function(event)
{
    var e = event["event"];
    if(!e)
    {
        event = glig.events.resolve_event(event);
        e = event["event"];
    }
    var keynum = e.keyCode;
    if(!keynum)
        keynum = e.which;

    var char = String.fromCharCode(keynum);

    return char;
}

//==============================================================
// UI
//==============================================================

glig.ui.show = function(id, bl)
{
    var ob = glig.resolve_target(id);

    if(!bl)
        bl = "block";

    ob.style.visibility = "visible";
    ob.style.display = bl;
}

glig.ui.hide = function(id)
{
    var ob = glig.resolve_target(id);

    ob.style.visibility = "hidden";
    ob.style.display = "none";
}

glig.ui.toggle = function(id, bl)
{
    var ob = glig.resolve_target(id);

    if(!ob.style.display || ob.style.display == "none")
        glig.ui.show(id);
    else
        glig.ui.hide(id);
}

glig.ui.get_scroll_top = function()
{
    if(document.documentElement && document.documentElement.scrollTop)
        return document.documentElement.scrollTop;
    else if(document.body)
        return document.body.scrollTop;
    else
        return 0;
}

glig.ui.get_window_extents = function()
{
    if(self.innerHeight)
        return { "width": self.innerWidth, "height": self.innerHeight };
    else if(document.documentElement && document.documentElement.clientHeight)
        return { "width": document.documentElement.clientWidth, "height": document.documentElement.clientHeight };
    else if(document.body)
        return { "width": document.body.clientWidth, "height": document.body.clientHeight };
    else
        return { "width": 800, "height": 600 };
}

glig.ui.get_element_position = function(ob)
{
    var left = ob.offsetLeft;
    var top = ob.offsetTop;

    while(true)
    {
        var ob = ob.offsetParent;
        if(!ob || ob == document.body)
            break;

        left += ob.offsetLeft;
        top += ob.offsetTop;
    }

    return { "x": left, "y": top };
}

glig.ui.get_mouse_position = function(e)
{
    var event = glig.events.resolve_event(e);
    event = event.event;

    var x = 0;
    var y = 0;

    if(event.pageX || event.pageY)
    {
        x = event.pageX;
        y = event.pageY;
    }
    else if (event.clientX || event.clientY)
    {
        x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
        y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
    }

    return { "x": x, "y": y };
}

glig.ui.resolve_mouse_position = function(event)
{
    var position;

    if(event.pageX || event.pageY)
    {
        position =
        {
            "x": event.pageX,
            "Y": event.pageY
        };
    }
    else
    {
        position =
        {
            "x": event.clientX + document.body.scrollLeft - document.body.clientLeft,
            "Y": event.clientY + document.body.scrollTop - document.body.clientTop
        };
    }

    return position;
}

glig.ui.add_to_bookmarks = function(url, title)
{
    url = (url ? url : location.href);
    title = (title ? title : document.title);

    if(document.all)
    {
        window.external.AddFavorite(url, title);
    }
    else if(window.sidebar)
    {
        window.sidebar.addPanel(title, url, '');
    }
}

//==============================================================
// Common AJAX functions
//==============================================================

glig.ajax.get_http_object = function()
{
    var http_object;

    try
    {
        // Firefox, Opera, Safari, etc
        http_object = new XMLHttpRequest();
    }
    catch(e)
    {
        // Internet Explorer
        try
        { http_object = new ActiveXObject("Msxml2.XMLHTTP"); }
        catch(e)
        {
            try
            { http_object = new ActiveXObject("Microsoft.XMLHTTP"); }
            catch(e)
            { }
        }
    }

    return http_object;
}

glig.ajax.send_request = function(options)
{
    var http_object = glig.ajax.get_http_object();
    var post_string = null;

    var url      = options["url"];
    var method   = glig.arrvar(options, "method", "get");

    method = method.toUpperCase();

    http_object.open(method, url, true);

    if(method.toLowerCase() == "post")
    {
        var post_vars = glig.arrvar(options, "post_vars", { });
        post_string = glig.ajax.encode_post_string(post_vars);

        http_object.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        http_object.setRequestHeader("Content-length", post_string.length);
        http_object.setRequestHeader("Connection", "close");
    }

    wrapper = this;
    options["http_object"] = http_object;

    bind_args = [options];

    http_object.onreadystatechange = glig.bind(glig.ajax.handle_callback, wrapper, bind_args);
    http_object.send(post_string);
}

glig.ajax.handle_callback = function(options)
{
    // Intermediate function to handle different error and timeout states.
    // This makes things quite a bit easier than having to check the readyState
    // and status in every single AJAX callback function.
    //
    var http_object = options["http_object"];

    if(http_object.readyState == 4)
    {
        var callback = options["callback"];

        if(http_object.status == 200)
        {
            options["error"] = false;
            options["response"] = http_object.responseText;
        }
        else
        {
            options["error"] = true;
        }

        callback(options);
    }
}

glig.ajax.send_get_request = function(url, fn, wrapper, args)
{
    var hob = glig.ajax.get_http_object();
    hob.open("GET", url, true);

    if(!wrapper)
        wrapper = this;

    if(!args)
        args = new Array();

    args = (new Array(hob)).concat(args);

    hob.onreadystatechange = glig.bind(fn, wrapper, args);
    hob.send(null);
}

glig.ajax.send_post_request = function(url, parameters, fn, wrapper, args)
{
    var hob = glig.ajax.get_http_object();

    var post_string = glig.encode_post_string(parameters);

    hob.open("POST", url, true);
    hob.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    hob.setRequestHeader("Content-length", post_string.length);
    hob.setRequestHeader("Connection", "close");

    if(!wrapper)
        wrapper = this;

    if(!args)
        args = new Array();

    args = (new Array(hob)).concat(args);

    hob.onreadystatechange = glig.bind(fn, wrapper, args);

    hob.send(post_string);
}

// Convenience callback function
//
glig.ajax.callback_evaluate_remote = function(hob)
{
    if(hob.readyState != 4)
        return;

    if(hob.status == 200)
    {
        js_code = hob.responseText;
        eval(js_code);
    }
}

glig.ajax.display_loading_icon = function(element_id)
{
    var element = glig.resolve_target(element_id);

    if(element)
    {
        var element_width = element.offsetWidth;
        var element_height = element.offsetHeight;

        var icon = document.createElement("div");
        icon.innerHTML = "<img src=/images/icons/loading.gif class=inline width=17 height=17>";

        icon.style.position = "absolute";
        icon.style.top  = (element_height - 17) / 2 + "px";
        icon.style.left = (element_width - 17) / 2 + "px";
        
        element.appendChild(icon);
    }
}

glig.ajax.encode_post_string = function(parameters)
{
    // @@@@ replace all ajax calls with jQuery equivalents
    return $.param(parameters);

    /*
    var post_string = "";

    for(key in parameters)
    {
        if(post_string.length > 0)
            post_string += "&";

        post_string += key + "=" + encodeURI(parameters[key]);
    }

    return post_string;
    */
}

//==============================================================
// Glig Boxes: popin box/panel and slanted
//==============================================================

var popin_panel_on_close_function;

glig.ui.open_popin_panel = function(options)
{
    glig.ui.close_popin_panel();

    var rel    = options["rel"];
    var parent = options["parent"];
    var classname  = glig.arrvar(options, "class");

    popin_panel_on_close_function = options["on_close"];

    var panel = glig.create_element("div", "#glig_popin_panel");

    if(rel)
    {
        var position = glig.ui.get_element_position(rel);
        var x = position.x;
        var y = position.y + rel.offsetHeight + 2;

        if(parent)
        {
            var parent_position = glig.ui.get_element_position(parent);
            x -= parent_position.x;
            y -= parent_position.y;
        }

        panel.style.left = x + "px";
        panel.style.top  = y + "px";
    }

    // var width  = glig.arrvar(options, "width", 200);
    // var height = glig.arrvar(options, "height", 200);
    // panel.style.width = width + "px";
    // panel.style.height = height + "px";

    classname = (classname ? "glig_popin_panel_defaults " + classname : "glig_popin_panel_defaults");

    panel.className = classname;

    if(parent)
    {
        parent.appendChild(panel);
    }
    else
    {
        document.body.appendChild(panel);
    }

    glig.defer("document.onclick = glig.ui.handle_panel_event");

    return panel;
}

glig.ui.close_popin_panel = function()
{
    var panel = glig.resolve_target("glig_popin_panel");
    if(panel)
    {
        if(popin_panel_on_close_function)
            popin_panel_on_close_function();

        panel.parentNode.removeChild(panel);
    }

    document.onclick = null;
    popin_panel_on_close_function = null;
}

glig.ui.handle_panel_event = function(e)
{
    var event = glig.events.resolve_event(e);

    // if(event.type != "click")
    //     return;

    var panel = glig.resolve_target("glig_popin_panel");
    if(!panel || (event.target != panel && !glig.is_child_of(event.target, panel)))
    {
        glig.ui.close_popin_panel();
    }
}

glig.ui.open_popin_box = function(url, title, width, height)
{
    glig.ui.close_popin_box();

    if(!width)
        width = 500;
    if(!height)
        height = 500;

    var header_height = 23;
    var padding = 5;

    // document.body.style.opacity = "0.35";

    var box = glig.create_element("div", "#glig_popin_box");
    var content = glig.create_element("div", "#glig_popin_box_content", box);
    var tit = glig.create_element("div", "title", box);
    var close = glig.create_element("div", "close", box);

    // Outer Box
    box.style.width = width + "px";
    box.style.height = height + "px";

    var dims = glig.ui.get_window_extents();
    var st = glig.ui.get_scroll_top();
    var dw = Math.floor((dims.width - width) / 2);
    var dh = Math.floor((dims.height - height) / 2);

    box.style.left = (dw>0?dw:0) + "px";
    box.style.top = (dh>0?dh+st:st) + "px";

    // Title
    if(title)
    {
        tit.innerHTML = title;
    }

    // Close
    close.innerHTML = "<a href=# onClick='glig.ui.close_popin_box(); return false;' class=inv_a>Close <img src=/images/boxes/popin/close.gif></a>";

    // Inner Content
    content.style.width = (width - (padding+3+1) * 2) + "px";
    content.style.height = (height - header_height - 3 - (padding+1) * 2) + "px";
    content.style.left = "3px";
    content.style.top = (header_height) + "px";

    glig.ajax.send_request
    ({
        "url":      url, 
        "callback": glig.ui.open_popin_box_helper
    });

    document.body.appendChild(box);

    glig.ui.render_drop_shadow(box);
    glig.ui.begin_drag(box);

    return box;
}

glig.ui.begin_drag = function(element)
{
    mouse_down = function(e)
    {
        var event = glig.events.resolve_event(e);
        var m  = glig.ui.get_mouse_position(e);
        var el = glig.ui.get_element_position(element);

        // Only react if we're pulling the top bar
        //
        if(event.target != element)
            return;

        var delta = { "x": m.x - el.x, "y": m.y - el.y };

        mouse_move = function(e)
        {
            var mouse_position = glig.ui.get_mouse_position(e);

            element.style.left = (mouse_position.x - delta.x) + "px";
            element.style.top = (mouse_position.y - delta.y) + "px";

            return false;
        }

        mouse_up = function(e)
        {
            document.onmousemove = null;
            document.onmousedown = null;
            document.onmouseup = null;
        }

        mouse_down_dummy = function(e)
        {
            return false;
        }

        document.onmousemove = mouse_move;
        document.onmousedown = mouse_down_dummy;
        document.onmouseup = mouse_up;
    }

    element.onmousedown = mouse_down;

    return false;
}

glig.ui.open_popin_box_helper = function(options)
{
    var content = glig.resolve_target("glig_popin_box_content");
    if(!content)
        return;

    if(options["error"] == false)
    {
        content.innerHTML = options["response"];
    }
    else
    {
        glig.ui.close_popin_box();
    }
}

glig.ui.close_popin_box = function()
{
    // document.body.style.opacity = "1";

    var box = glig.resolve_target("glig_popin_box");
    if(box)
        document.body.removeChild(box);
}

glig.ui.render_drop_shadow = function(element)
{
    var shadow_left = glig.create_element("div", "drop_shadow_left", element);
    var shadow_right = glig.create_element("div", "drop_shadow_right", element);

    shadow_right.style.width = (element.offsetWidth - shadow_left.offsetWidth) + "px";
}

glig.ui.render_slanted_boxes = function()
{
    var count = 0;

    $("div.glig_slanted_box").each(function()
    {
        glig.ui.render_slanted_box(this, count++);
    });

    /*
        var boxes = glig.getElementsByClass("glig_slanted_box", "div");
        var num_boxes = boxes.length;
        for(var i = 0; i < num_boxes; i++)
            glig.ui.render_slanted_box(boxes[i], i);
    */
}

glig.ui.render_slanted_box = function(box, num)
{
    var divs = glig.ui.get_slanted_box_divs(box);

    var box_width = box.offsetWidth;
    var box_height = box.offsetHeight;

    var params = glig.ui.get_slanted_box_params(num);

    var W = box_width - 8;
    var H = box_height - 8;

    var x0 = 5;
    var y0 = 5;

    var top_left = glig.ui.intersect_lines(params.top_vector, params.left_vector, W, H);
    var top_right = glig.ui.intersect_lines(params.top_vector, params.right_vector, W, H);
    var bottom_left = glig.ui.intersect_lines(params.bottom_vector, params.left_vector, W, H);
    var bottom_right = glig.ui.intersect_lines(params.bottom_vector, params.right_vector, W, H);

    var element = divs["top"];
    var d = top_right[1] - top_left[1];
    var delta = params.top_vector[4];
    element.style.left = (x0 + top_left[0]) + "px";
    element.style.top = (y0 + top_left[1] + (d<0?(d-delta):0)) + "px";
    element.style.width = Math.abs(top_left[0] - top_right[0]) + "px";
    element.style.height = Math.abs(d) + delta + "px";
    element.style.backgroundImage = "url('" + params.base_image_url + "/top" + params.top_vector[5] + ".gif')";
    if(params.top_vector[1] < 0)
        element.style.backgroundPosition = "bottom left";

    var element = divs["left"];
    var d = bottom_left[0] - top_left[0];
    var delta = params.left_vector[4];
    element.style.left = (x0 + top_left[0] + (d<0?(d-delta):0)) + "px";
    element.style.top = (y0 + top_left[1]) + "px";
    element.style.width = (Math.abs(d) + delta) + "px";
    element.style.height = Math.abs(bottom_left[1] - top_left[1]) + "px";
    element.style.backgroundImage = "url('" + params.base_image_url + "/left" + params.left_vector[5] + ".gif')";
    if(params.left_vector[1] < 0)
        element.style.backgroundPosition = "top right";

    var element = divs["bottom"];
    var dx = bottom_right[0] - bottom_left[0];
    var dy = bottom_right[1] - bottom_left[1];
    var delta = params.bottom_vector[4];
    var v2 = params.bottom_vector[1];
    var v2d = Math.ceil((v2 + delta) / dx * params.bottom_vector[0]);
    element.style.left = (x0 + bottom_left[0]) + "px";
    element.style.top = (y0 + bottom_left[1] + (v2<0?(-v2d+dy-2):0)) + "px";
    element.style.width = Math.abs(bottom_left[0] - bottom_right[0]) + "px";
    element.style.height = (Math.abs(dy) + delta) + "px";
    element.style.backgroundImage = "url('" + params.base_image_url + "/bottom" + params.bottom_vector[5] + ".gif')";
    if(v2 < 0)
        element.style.backgroundPosition = "bottom left";

    var reh = 0;
    if(v2 < 0)
        reh = 2;

    var element = divs["right"];
    var d = bottom_right[0] - top_right[0];
    var delta = params.right_vector[4];
    var v1 = params.bottom_vector[0];
    element.style.left = (x0 + top_right[0] + (v1<0?(v1-d-1):0)) + "px";
    element.style.top = (y0 + top_right[1] - 1) + "px";
    element.style.width = (Math.abs(d) + delta) + "px";
    element.style.height = (Math.abs(top_right[1] - bottom_right[1]) + reh) + "px";
    element.style.backgroundImage = "url('" + params.base_image_url + "/right" + params.right_vector[5] + ".gif')";

    var element = divs["dot"];
    element.style.left = (x0 + bottom_right[0] - 1) + "px";
    element.style.top = (y0 + bottom_right[1] + (reh-2)) + "px";
    element.style.width = "9px";
    element.style.height = "9px";
//    element.style.backgroundColor = "red";
    element.style.backgroundImage = "url('" + params.base_image_url + "/dot.gif')";
}

glig.ui.slanted_box_vectors = new Array();

glig.ui.initialize_slanted_box_vectors = function()
{
    if(!glig.ui.slanted_box_vectors)
        glig.ui.slanted_box_vectors = new Array();

    av = glig.ui.slanted_box_vectors;

    av.top_vectors = new Array
    (
        new Array(900, -10, 0, 0, 2, "")
    );
    av.left_vectors = new Array
    (
        new Array(16, 986, 0, 1, 2, "")
    );
    av.bottom_vectors = new Array
    (
        new Array(900, -14, 0, 1, 12, ""),
        new Array(900, 7, 1, 1, 11, "2")
    );
    av.right_vectors = new Array
    (
        new Array(9, 1000, 1, 0, 10, "")
    );
}

glig.ui.get_slanted_box_params = function(num, width)
{
    glig.ui.initialize_slanted_box_vectors();

    var av = glig.ui.slanted_box_vectors;

    if(num == null)
        num = 0;

    var params = new Object();
    params.base_image_url = "/images/boxes/slanted/1s";
    params.top_vector = av.top_vectors[num % av.top_vectors.length];
    params.left_vector = av.left_vectors[num % av.left_vectors.length];
    params.bottom_vector = av.bottom_vectors[num % av.bottom_vectors.length];
    params.right_vector = av.right_vectors[num % av.right_vectors.length];

    return params;
}

glig.ui.get_slanted_box_divs = function(box)
{
    var divs = new Array();
    divs["top"] = null;
    divs["left"] = null;
    divs["bottom"] = null;
    divs["right"] = null;
    divs["dot"] = null;

    // Resolve the edge divs
    //
    for(var div_class in divs)
    {
        var side_elements = glig.getElementsByClass(div_class, "div", box);
        var element;

        if(side_elements.length != 0)
        {
            element = side_elements[0];
        }
        else
        {
            element = document.createElement("div");
            element.className = div_class;
            box.appendChild(element);
        }

        divs[div_class] = element;
    }

    return divs;
}

glig.ui.intersect_lines = function(a, b, W, H)
{
    if(W < 200 && a[1] == -14)
        a[1] = -12.3;

    var p = - a[0] * b[1] + b[0] * a[1];
    if(p == 0)
    {
        /* Which joker is feeding us parallel lines? */
        return new Array(0, 0);
    }

    var d0 = (b[2] - a[2]) * W;
    var d1 = (b[3] - a[3]) * H;

    var ap = - b[1] * d0 + b[0] * d1;

    var x = Math.round(a[2] * W + a[0] * ap / p);
    var y = Math.ceil(a[3] * H + a[1] * ap / p);

    return new Array(x, y);
}

glig.render_page_elements = function()
{
    glig.ui.render_slanted_boxes();
}

//==============================================================
// Convenience functions
//==============================================================

function clear_form(form)
{
    for(var i = 0; i < form.elements.length; i++)
    {
        if(form.elements[i].type == "hidden")
            continue;

        form.elements[i].value = "";
    }
}
