/**
 * @fileoverview GUI library
 *
 * @author      WebDialogs
 * @version     1.2
 */

/**
 * @class Encapsulates functions for creation of GUI elements.
 * @constructor
 * @return A new instance of WdGui class
 */
function WdGui() {
    /**
     * Creates a border (current implementation is a table with WD look & feel),
     * and moves eHead, eBody, and eFoot elements inside.
     * <p>
     * The newly created container will become a child of eBody's parent, thus,
     * it is advisable that eHead and eFoot belong to the same parent node.
     *
     * @param   eHead       DOM element, or its id, to be put in the header section
     * @param   eBody       DOM element, or its id, to be put in the middle section
     * @param   eFoot       DOM element, or its id, to be put in the footer section
     * @return  (Object)    The newly created container
     */
    this.createBorder = function() {
        // The following code facilitates the transiton to the new function syntax //
        var eTitle, eStatus, eHead, eBody, eFoot;                                  //
        var args = wdGui.createBorder.arguments;                                   //
        if (args.length == 3) {                                                    //
            eTitle = args[0];                                                      //
            eBody = args[1];                                                       //
            eFoot = args[2];                                                       //
        } else {                                                                   //
            eTitle = args[0].title;                                                //
            eStatus = args[0].status;                                              //
            eHead = args[0].header;                                                //
            eBody = args[0].body;                                                  //
            eFoot = args[0].footer;                                                //
        }                                                                          //
        if (typeof eTitle == "string")                                             //
            eTitle = wdDom.getElement(eTitle);                                     //
        if (typeof eStatus == "string")                                            //
            eStatus = wdDom.getElement(eStatus);                                   //
        if (typeof eHead == "string")                                              //
            eHead = wdDom.getElement(eHead);                                       //
        if (typeof eBody == "string")                                              //
            eBody = wdDom.getElement(eBody);                                       //
        if (typeof eFoot == "string")                                              //
            eFoot = wdDom.getElement(eFoot);                                       //
        if (!eBody)                                                                //
            return;                                                                //
        /////////////////////////////////////////////////////////////////////////////
        var parent = eBody.parentNode;
        if (parent.tagName.toLowerCase() == "td" && parent.className == "wdborder-body-center")
            // perhaps all is already done (e.g. when rendering static html)
            return eBody.parentNode.parentNode.parentNode.parentNode;
        var table, tbody, row, cell;
        table = wdDom.createElement("table", {border:0, cellPadding:0, cellSpacing:0, align:"center"});
        if (eBody.nextSibling)
            parent.insertBefore(table, eBody.nextSibling);
        else
            parent.appendChild(table);
        table.appendChild(tbody = wdDom.createElement("tbody"));
        tbody.appendChild(row = wdDom.createElement("tr"));
        row.appendChild(wdDom.createElement("td", {className:"wdborder-title-top-left"}));
        row.appendChild(cell = wdDom.createElement("td", {className:"wdborder-title-top-center"}));
        if (eTitle)
            cell.appendChild(eTitle);
        row.appendChild(wdDom.createElement("td", {className:"wdborder-title-top-right"}));

        if (eHead) {
            tbody.appendChild(row = wdDom.createElement("tr"));
            row.appendChild(wdDom.createElement("td", {className:"wdborder-header-left"}));
            row.appendChild(cell = wdDom.createElement("td", {className:"wdborder-header-center"}));
            cell.appendChild(eHead);
            row.appendChild(wdDom.createElement("td", {className:"wdborder-header-right"}));
            tbody.appendChild(row = wdDom.createElement("tr", {style:{height:"1px"}}));
            row.appendChild(wdDom.createElement("td", {className:"wdborder-sep-left"}));
            row.appendChild(wdDom.createElement("td", {className:"wdborder-sep-center"}));
            row.appendChild(wdDom.createElement("td", {className:"wdborder-sep-right"}));
        }

        tbody.appendChild(row = wdDom.createElement("tr"));
        row.appendChild(wdDom.createElement("td", {className:"wdborder-body-left"}));
        row.appendChild(cell = wdDom.createElement("td", {className:"wdborder-body-center"}));
        cell.appendChild(eBody);
        row.appendChild(wdDom.createElement("td", {className:"wdborder-body-right"}));
        tbody.appendChild(row = wdDom.createElement("tr"));
        row.appendChild(wdDom.createElement("td", {className:"wdborder-footer-bottom-left"}));
        row.appendChild(cell = wdDom.createElement("td", {className:"wdborder-footer-bottom-center"}));
        if (eFoot)
            cell.appendChild(eFoot);
        row.appendChild(wdDom.createElement("td", {className:"wdborder-footer-bottom-right"}));
        return table;
    };

    this.createBorder2 = function(border) {
        var title = wdDom.getElementsByAttributes({rel:"wdborder-title"}, border, true)[0];
        var header = wdDom.getElementsByAttributes({rel:"wdborder-header"}, border, true)[0];
        var body = wdDom.getElementsByAttributes({rel:"wdborder-body"}, border, true)[0];
        var footer = wdDom.getElementsByAttributes({rel:"wdborder-footer"}, border, true)[0];
        if (!body)
            return;
        if (body.parentNode.tagName.toLowerCase() == "td" && body.parentNode.className == "wdborder-body-center")
            return; // perhaps all is already done (e.g. when rendering static html)
        var table, tbody, row, cell;
        table = wdDom.createElement("table", {border:0, cellPadding:0, cellSpacing:0, style:{width:border.style.width, height:border.style.height}});
        if (border.firstChild)
            border.insertBefore(table, border.firstChild);
        else
            border.appendChild(table);
        table.appendChild(tbody = wdDom.createElement("tbody"));
        if (title) {
            tbody.appendChild(row = wdDom.createElement("tr"));
            row.appendChild(wdDom.createElement("td", {className:"wdborder-title-top-left"}));
            row.appendChild(cell = wdDom.createElement("td", {className:"wdborder-title-top-center"}));
            cell.appendChild(title);
            row.appendChild(wdDom.createElement("td", {className:"wdborder-title-top-right"}));
        } else if (header) {
            tbody.appendChild(row = wdDom.createElement("tr"));
            row.appendChild(wdDom.createElement("td", {className:"wdborder-header-top-left"}));
            row.appendChild(cell = wdDom.createElement("td", {className:"wdborder-header-top-center"}));
            row.appendChild(wdDom.createElement("td", {className:"wdborder-header-top-right"}));
        } else {
            tbody.appendChild(row = wdDom.createElement("tr"));
            row.appendChild(wdDom.createElement("td", {className:"wdborder-body-top-left"}));
            row.appendChild(cell = wdDom.createElement("td", {className:"wdborder-body-top-center"}));
            row.appendChild(wdDom.createElement("td", {className:"wdborder-body-top-right"}));
        }
        if (header) {
            tbody.appendChild(row = wdDom.createElement("tr"));
            row.appendChild(wdDom.createElement("td", {className:"wdborder-header-left"}));
            row.appendChild(cell = wdDom.createElement("td", {className:"wdborder-header-center"}));
            cell.appendChild(header);
            row.appendChild(wdDom.createElement("td", {className:"wdborder-header-right"}));
            tbody.appendChild(row = wdDom.createElement("tr", {style:{height:"1px"}}));
            row.appendChild(wdDom.createElement("td", {className:"wdborder-sep-left"}));
            row.appendChild(wdDom.createElement("td", {className:"wdborder-sep-center"}));
            row.appendChild(wdDom.createElement("td", {className:"wdborder-sep-right"}));
        }
        tbody.appendChild(row = wdDom.createElement("tr"));
        row.appendChild(wdDom.createElement("td", {className:"wdborder-body-left"}));
        row.appendChild(cell = wdDom.createElement("td", {className:"wdborder-body-center"}));
        cell.appendChild(body);
        row.appendChild(wdDom.createElement("td", {className:"wdborder-body-right"}));
        if (footer) {
            tbody.appendChild(row = wdDom.createElement("tr"));
            row.appendChild(wdDom.createElement("td", {className:"wdborder-footer-bottom-left"}));
            row.appendChild(cell = wdDom.createElement("td", {className:"wdborder-footer-bottom-center"}));
            cell.appendChild(footer);
            row.appendChild(wdDom.createElement("td", {className:"wdborder-footer-bottom-right"}));
        } else {
            tbody.appendChild(row = wdDom.createElement("tr"));
            row.appendChild(wdDom.createElement("td", {className:"wdborder-body-bottom-left"}));
            row.appendChild(cell = wdDom.createElement("td", {className:"wdborder-body-bottom-center"}));
            row.appendChild(wdDom.createElement("td", {className:"wdborder-body-bottom-right"}));
        }
        return table;
    };

    /**
     * Wraps a button (or any other HTML element) in a "WD"-style button.
     * Current implementation is a table with WD look&feel.
     * <br>
     * To prevent double-wrapping in case of loading an already rendered document,
     * it checks the element's parentNode; if it appears to be a "wd"-container,
     * it does not wrap the element.
     * <br>
     * If the element's style specifies width, the width is assigned to the new table,
     * and the element assumes 100% width;
     * <br>
     * Because Safari ignores some style attributes of "input" elements, on non-Windows
     * platforms, only "buttons" are wrapped; "input"-s are left for browser to render natively.
     * <br>
     * In addition, it adds the following methods to the element:
     * <br><br><ul>
     * <code>
     *   onmouseover() -- only if it doesn't already exist; appends the string "_highlighted" to the class name
     *   onmouseout() -- only if it doesn't already exist; removes the string "_highlighted" from the class name
     *   setVisible(&lt;boolean&gt; on) -- sets visibility of the wrapping table on or off
     *   show() -- equivalent to setVisible(true)
     *   hide() -- equivalent to setVisible(false)
     * </code>
     *
     * @param   elem        Element (button, input-button, or input-submit), to wrap
     * @return  (Object)    The newly created button
     */
    this.createButton = function(elem) {
        if (typeof elem == "string")
            elem = wdDom.getElement(elem);
        if (!elem)
            return;
        if (!elem.onmouseover)
            elem.onmouseover = function() {
                if (this.className.indexOf("_") == -1)
                    this.className += "_highlighted";
            };
        if (!elem.onmouseout)
            elem.onmouseout = function() {
                var i = this.className.indexOf("_highlighted");
                if (i > -1)
                    this.className = this.className.slice(0, i);
            };
        if (!elem.setVisible) {
            elem.setVisible = function(on) {
                this.wrapper.style.display = on ? "" : "none";
            };
            elem.show = function() {
                this.setVisible(true);
            };
            elem.hide = function() {
                this.setVisible(false);
            };
        }
        var cls = elem.className;
        if (cls.indexOf("_") > -1)
            cls = cls.slice(0, cls.indexOf("_"));
        if (elem.parentNode.tagName.toLowerCase() == "td" && elem.parentNode.className == cls + "-mid") {
            // we could be rendering static html; in such case, just assign the non-standard properties and get out
            elem.wrapper = elem.parentNode.parentNode.parentNode.parentNode;
            //               ->|td      ->|tr      ->|tbody   ->|table
            return;
        } else if (elem.tagName.toLowerCase() == "input"
            && window.navigator.platform.toLowerCase().indexOf('win') == -1
            && window.navigator.userAgent.toLowerCase().indexOf('firefox') == -1)
        {
            elem.wrapper = elem;
            return;
        }

        var table, tbody, row, cell;
        table = wdDom.createElement("table", {border:0, cellPadding:0, cellSpacing:0});
        if (elem.style.width) {
            table.style.width = elem.style.width;
            elem.style.width = "100%";
        }
        if (elem.nextSibling)
            elem.parentNode.insertBefore(table, elem.nextSibling);
        else
            elem.parentNode.appendChild(table);
        table.appendChild(tbody = wdDom.createElement("tbody"));
        tbody.appendChild(row = wdDom.createElement("tr"));
        row.appendChild(wdDom.createElement("td",  {className:cls + "-left"}));
        row.appendChild(cell = wdDom.createElement("td", {className:cls + "-mid"}));
        wdDom.setAttributes(elem.style, {backgroundColor:"transparent", border:"none"});
        cell.appendChild(elem);
        row.appendChild(wdDom.createElement("td",  {className:cls + "-right"}));
        elem.wrapper = table;
        return table;
    };

    /**
     * Traverse the document, discover wdbutton's and wdborder's and dress them
     */
    this.init = function() {
        var wdBorders = wdDom.getElementsByAttributes({rel:"wdborder"});
        for (var b in wdBorders)
            this.createBorder2(wdBorders[b]);
        var wdButtons = wdDom.getElementsByAttributes({className:/wdbutton-\w+$/});
        for (var b in wdButtons)
            this.createButton(wdButtons[b]);
    }
}

/**
 * ready-to-use instance
 */
var wdGui = new WdGui();

