/**
 * (c) Novatice Technologies 2011
 * http://www.novatice.com
 * @author Vincent Bataille "vincebattle" <v.bataille@novatice.com>
 */

/*
 * Thu Apr 21 2011 1.10
 * - fix: initWindow -> variable listbox is not defined
 *
 * Fri Apr 15 2011 1.9
 * - new: initWindow -> tree scroll with arrows up and down
 *
 * Wed Apr 06 2011 1.8
 * - new: getGeckoRv()
 * - new: initWindow -> set gecko version on search textboxes
 *
 * Fri Feb 11 2011 1.7
 * - new: initWindow -> fix tree size (rows attribute)
 * - new: initWindow -> fix listbox size (rows attribute)
 *
 * Thu Jan 20 2011 1.6
 * - new: String.format -> supports choice pattern
 * - new: various -> parseDescriptionContent(element)
 *
 * Mon Jan 10 2010 1.5
 * - del: showMessage(deckId, value, time) -> use noticebox instead
 * - del: hideMessage(deckId) -> use noticebox instead
 *
 * Wed Dec 29 2010 1.4
 * - mod: tree -> sortTree
 *
 * 01.03
 * - new: showMessage(deckId, value, time)
 * - new: hideMessage(deckId
 *
 * Thu Jul 22 2010 1.2
 * - mod: String.format -> use "arguments" object instead of an array
 * - del: String -> trim and format functions
 *
 * Mon Jun 28 2010 1.1
 * - new: help -> openHelpFromElem, openHelpPopup
 *
 * Wed Apr 07 2010 1.0
 * - new: logs -> info, infoProps
 * - new: initWindow -> textbox context, tree scroll, radiogroup value
 * - new: String -> isBlank, trim, format
 * - new: various -> loadRDF
 * - new: tree -> sortTree, getSelectedRows, getSelectedRowsCellText, getSelectedRowsCellValue
 */

//******************************************************************************
//* LOGS
//******************************************************************************
/**
 * Write given message on console.
 * @param msg (string) the message to write
 * @param time (boolean) if true, write time before message
 */
function info(msg, time) {
    
    if (time) {
        var date = new Date();
        dump("["+date.getHours()+":"+date.getMinutes()+":"+date.getSeconds()+":"+date.getMilliseconds()+"] "+msg+"\n");
    } else {
        dump(msg+"\n");
    }
}

/**
 * Write given object properties matching given filter.
 * @param obj (object)
 * @param filter (string) property is written if its name contains this filter
 */
function infoProps(obj, filter) {

    var props = [];

    for (var p in obj) {
        if ((filter == null) || (p.toLowerCase().indexOf(filter)!=-1)) {
            props.push(p);
        }
    }

    props.sort();

    for (var i=0; i<props.length; i++) {
        var prop = props[i];
        info(prop+" = "+obj[prop]);
    }
}

//******************************************************************************
//* INIT WINDOW
//******************************************************************************
window.addEventListener("load", initWindow, false);
function initWindow() {

    var gecko = getGeckoRv();

    //TEXTBOXES
    var textboxes = document.getElementsByTagName("textbox");
    for (var a=0; a<textboxes.length; a++) {
        var textbox = textboxes[a];
        //prevent context problem
        if (!textbox.hasAttribute("context")) {
            textbox.inputField.parentNode.removeAttribute("context");
        }

        //set gecko version on search textbox for binding purpose
        if (textbox.getAttribute("type") == "search") {
            if (gecko < 2) {
                textbox.setAttribute("gecko", "1");
            } else {
                textbox.setAttribute("gecko", "2");
            }
        }
    }
    
    //TREES
    var trees = document.getElementsByTagName("tree");
    for (var b=0; b<trees.length; b++) {
        var tree = trees[b];
        //prevent scrolling problem
        tree.addEventListener("DOMMouseScroll", function(event) {
            event.preventDefault();
        }, false);
        tree.addEventListener("keypress", function(event) {
            if ((event.keyCode == KeyEvent.DOM_VK_DOWN)
                || (event.keyCode == KeyEvent.DOM_VK_UP)) {
                event.preventDefault();
                }
        }, false);

        //fix size problem
        var treechildren = null;
        if (tree.view == null) {
            //add fake treechildren to make the tree have its right size
            treechildren = tree.appendChild(document.createElement("treechildren"));
        }
        //set size
        tree.style.height = tree.boxObject.height+"px";
        if (treechildren != null) {
            //remove fake treechildren
            tree.removeChild(treechildren);
        }
    }
    
    //LISTBOXES
    var listboxes = document.getElementsByTagName("listbox");
    for (var c=0; c<listboxes.length; c++) {
        var listbox = listboxes[c];
        if(listbox.itemCount == 0) {
            //add fake item to make the listbox have its right size
            listbox.appendItem("");
            //set size
            listbox.style.height = listbox.boxObject.height + "px";
            //remove fake item
            listbox.removeItemAt(0);
        }
    }
}

/**
 * Returns the rv value of a Gecko user agent
 * as a floating point number.
 * (from https://developer.mozilla.org/en/Browser_Detection_and_Cross_Browser_Support)
 * @return -1 for non-gecko browsers
 *         0 for pre Netscape 6.1/Gecko 0.9.1 browsers
 *         number > 0 for other Gecko browsers
 */
function getGeckoRv() {
  
    if (navigator.product != "Gecko") {
        return -1;
    }

    var rvValue = 0;
    var ua = navigator.userAgent.toLowerCase();
    var rvStart = ua.indexOf("rv:");

    if (rvStart == -1) {
        return -1;
    }

    var rvEnd = ua.indexOf(")", rvStart);
    var rv = ua.substring(rvStart+3, rvEnd);
    var rvParts = rv.split(".");
    var exp = 1;

    for (var i=0; i<rvParts.length; i++) {
        var val = parseInt(rvParts[i]);
        rvValue += val / exp;
        exp *= 100;
    }

    return rvValue;
}

//******************************************************************************
//* STRING
//******************************************************************************
/**
 * @return True if the string is blank; false otherwise.
 */
String.prototype.isBlank = function() {

    var exp = /^\s*$/;
    return exp.test(this);
};

/**
 * @return The string without left or right whitespace.
 */
String.prototype.trim = function() {

    return this.replace(/^\s+|\s+$/g, "");
};

/**
 * Formats the string:
 *  {i} sequences are replaced by arguments[i]
 *  {i,0=text if equals zero|1<text if greater than one} are relaced by given text depending on arguments[i] value
 * @return The formated string.
 */
String.prototype.format = function() {

    var str = this.toString();
    var args = arguments;

    //replace simple items
    str = str.replace(/\{(\d+)\}/g, function(str, p1) {
        return (typeof(args[p1]) != "undefined") ? args[p1] : "{" + p1 + "}";
    });

    //replace choice items
    var exp = /\{(\d+),(\d+(?:=|<).*)\}/g;
    str = str.replace(exp, function(str, p1, p2, offset, s) {
        var text = str;
        var arg = parseInt(args[p1], 10);
        if (!isNaN(arg)) {
            //get choices
            var choices = p2.match(/\d+(?:=|<)[^\|]*/gi);

            for (var i=0; i<choices.length; i++) {
                var choice = choices[i];
                //get test
                var index = choice.search(/(=|<)/) + 1;
                var test = choice.substring(0, index);
                test = test.replace("=", "==");
                //get text to use to replace item
                text = choice.substring(index);

                if (eval(test + arg)) {
                    return text;
                }
            }
        }
        //if argument is not a number or if no choice is found, do nothing
        return text;
    });

    return str;
};

//******************************************************************************
//* VARIOUS
//******************************************************************************
/**
 * Load a given element rdf datasource with given xmlns and parameters.
 * @param element (element or string) the element to load or its id
 * @param rdfXmlns (string) the rdf spacename
 * @param rdfParams (string) extra rdf parameters
 */
function loadRDF(element, rdfXmlns, rdfParams) {

    if (typeof(element) == "string") {
        element = document.getElementById(element);
    }

    var params = "xmlns="+rdfXmlns+"&z="+Math.random();
    if ((rdfParams != null) && (rdfParams != "")) {
        params += "&"+rdfParams;
    }

    var pathname = window.location.pathname;
    var context = pathname.substring(0, pathname.indexOf("/", 1));
    element.setAttribute("datasources", context + "/Rdf?" + params);
}

/**
 * Parses the html content of a description element.
 * @param element (element or string) The description element to parse.
 */
function parseDescriptionContent(element) {

    if (typeof(element) == "string") {
        element = document.getElementById(element);
    }

    var xmlns_html = "http://www.w3.org/1999/xhtml";
    var html = "<html:html xmlns:html=\""+xmlns_html+"\">"+element.textContent+"</html:html>";
    var parsedContent = (new DOMParser()).parseFromString(html, "text/xml").documentElement;

    //delete text content (or it is displayed twice)
    element.textContent = "";

    //add parsed content
    while (parsedContent.firstChild) {
        element.appendChild(parsedContent.firstChild);
    }
}

//******************************************************************************
//* HELP POPUP
//******************************************************************************
/**
 * Open a help popup window from an event on an element.
 * @param elem the element on which occured the event.
 */
function openHelpFromElem(elem) {

    openHelpPopup(elem.getAttribute("page"), elem.getAttribute("anchor"));
}

/**
 * Open a help popup window.
 * Help pages must be located in the '/resources/help' directory.
 * @param page the name of the help page to open
 * @param anchor the id of the anchor to go to on the help page
 */
function openHelpPopup(page, anchor) {

    if ((page != null) && (page != "")) {
        //build help page url
        var pathname = window.location.pathname;
        var context = pathname.substring(0, pathname.indexOf("/", 1));
        var url = context + "/resources/help/" + page;
        if ((anchor != null) && (anchor != "")) {
            url += "#"+anchor;
        }

        //build help page options
        var width = window.screen.availWidth / 2;
        var height = window.screen.availHeight / 3;
        var left= window.screen.availLeft;
        var top = window.screen.availTop + window.screen.availHeight - height;

        var options = "scrollbars,outerWidth="+width+",outerHeight="+height+",left="+left+",top="+top;

        //open help
        var win = window.open(url, "help", options);
        win.focus();
    }
}

//******************************************************************************
//* TREE
//******************************************************************************
/**
 * Sort a tree on a column.
 * @param event (click event) the click on treecol header event
 */
function sortTree(event) {

    var col = event.target;
    var direction = col.getAttribute("sortDirection");

    if (direction == "descending") {
        col.setAttribute("sortDirection", "natural");
    }
}

/**
 * Get selected rows index.
 * @param tree (element or string) the tree element or its id
 * @return an array with the index of the selected rows
 */
function getSelectedRows(tree) {

    if (typeof(tree) == "string") {
        tree = document.getElementById(tree);
    }
    var selectedRows = new Array();

    if (tree.view != null) {
        var rangeCount = tree.view.selection.getRangeCount();

        for (var r=0 ; r<rangeCount ; r++) {
            var start = {};
            var end = {};
            tree.view.selection.getRangeAt(r, start, end);
            for (var c=start.value ; c<=end.value ; c++) {
                selectedRows.push(c);
            }
        }
    }

    return selectedRows;
}

/**
 * Get selected rows cell text in given column.
 * @param tree (element or string) the tree element or its id
 * @param colId (string) the id of the column or null for primary column
 * @return an array with the selected rows cell text in given column
 */
function getSelectedRowsCellText(tree, colId) {

    if (typeof(tree) == "string") {
        tree = document.getElementById(tree);
    }
    var selectedRows = getSelectedRows(tree);
    var cellsText = new Array();

    if (colId == null) {
        for (var i=0; i<selectedRows.length; i++) {
            cellsText.push(tree.view.getCellText(selectedRows[i], tree.columns.getPrimaryColumn()));
        }
    } else {
        for (var j=0; j<selectedRows.length; j++) {
            cellsText.push(tree.view.getCellText(selectedRows[j], tree.columns.getNamedColumn(colId)));
        }
    }
   
    return cellsText;
}

/**
 * Get selected rows cell value in given column.
 * @param tree (element or string) the tree element or its id
 * @param colId (string) the id of the column or null for primary column
 * @return an array with the selected rows cell value in given column
 */
function getSelectedRowsCellValue(tree, colId) {

    if (typeof(tree) == "string") {
        tree = document.getElementById(tree);
    }
    var selectedRows = getSelectedRows(tree);
    var cellsValue = new Array();

    if (colId == null) {
        for (var i=0; i<selectedRows.length; i++) {
            cellsValue.push(tree.view.getCellValue(selectedRows[i], tree.columns.getPrimaryColumn()));
        }
    } else {
        for (var i=0; i<selectedRows.length; i++) {
            cellsValue.push(tree.view.getCellValue(selectedRows[i], tree.columns.getNamedColumn(colId)));
        }
    }

    return cellsValue;
}

