var WU = Class.create();

/**
* Makes a hyperlink that calls a function, f. The function will
* operate as a member of fContext if fContext is not null. If
* fContext is null the function will not be bound.
* ex: p.appendChild(makeFnLink("Find Address", "label", showAddress, addr));
*/
WU.makeFnLink = function(text, className, f, fContext){
    var link = document.createElement('a');
    link.className = className;
    if (fContext) {
            link.onclick = f.bindAsEventListener(fContext);
    } else {
            link.onclick = f;
    }
    link.href = '#';
    textNode=document.createTextNode(text);
    link.appendChild(textNode);
    return link;
};

/**
* Makes a hyperlink that calls a function, f, and adds it
* to parent el.
*/
WU.addFnLink = function(el, text, className, f, fContext){
    var link = WU.makeFnLink(text, className, f, fContext);
    el.appendChild(link);
};

WU.makeAddressLabel = function(label, closeHandler){
    var doc = document;
    doc.ce = document.createElement;
    doc.ct = document.createTextNode;

    var lblStr = new String(label);
    var width = lblStr.length + 3;

    var div = doc.ce('div');
    div.style.width = "" + width + 'ex';
    div.style.border = '1px solid #333333';
    div.className='popupBackground';
    div.style.zIndex = 255;

    // Add a pointer image
    var pointer = doc.ce('img');
    pointer.src = 'images/here.gif';
    pointer.width = 10;
    pointer.height = 10;
    pointer.className = 'pointer';

	// The Title of the popup. Always visible.
    var popupHeader = doc.ce('h4');
    //popupHeader.style.width =  width + 'ex';
    popupHeader.className = 'popupHeader';
    // Add the close 'x'
    var closer = doc.ce('a');
    closer.href = '#';
    closer.appendChild(doc.ct('x'));
    closer.className='closeX';
    closer.onclick = function() {  closeHandler(div); };

    popupHeader.appendChild(pointer);

    popupHeader.appendChild(closer);

    popupHeader.appendChild(doc.ct(label + "  "));

    div.appendChild(popupHeader);

    return div;
};

WU.addChildElement = function(parent, tag, styleClass){
    var el = document.createElement(tag);
    if (styleClass){
        el.className = styleClass;
    }
    parent.appendChild(el);
    return el;
};

WU.addEl = function(parent, tag, styleClass){
	return WU.addChildElement(parent, tag, styleClass);
};

WU.addInput = function(fieldset, name, id, classname, value){
    //var input = WU.addEl(fieldset, "input");
    var input = document.createElement('input');
    input.setAttribute('type', 'text');
    input.setAttribute('id', id);
    input.setAttribute('name', name);
    if (classname){ input.className = classname; }
    if (value) { input.value = value; }
    fieldset.appendChild(input);
    return input;
};

WU.addHidden = function(fieldset, name, id, value){
    //var input = WU.addEl(fieldset, "input");
    var input = document.createElement('input');
    input.setAttribute('type', 'hidden');
    input.setAttribute('id', id);
    input.setAttribute('name', name);
    if (value) { input.value = value; }
    fieldset.appendChild(input);
    return input;
};

WU.addLabel = function(fieldset, text, classname){
    var label = WU.addEl(fieldset, "label");
    WU.addText(label, text);
    if (classname){ label.className = classname; }
    return label;
};


/*
 * selectedVals: array of values to select
 * options: array of arrays [ [val1, innerHTML1], [val2, innerHTML2], etc ]
 */
WU.addSelect = function(parent, name, id, styleClass, multiple, selectedVals, options){
    var select = WU.addEl(parent, 'select', styleClass);
    select.name = name;
    select.id = id;
    if (multiple){
            select.multiple = 'multiple';
    }
    for (i = 0; i < options.length; i++){
            var opt = WU.addEl(select, 'option');
            opt.value = options[i][0];
            for (j = 0; j < options.length; j++){
                    if (options[i][0] == selectedVals[j]){
                            opt.selected = 'selected';
                            break;
                    }
            }
            opt.innerHTML = options[i][1]
    }
    return select;
};

WU.addText = function(el, text){
    var t = document.createTextNode(text);
    el.appendChild(t);
    return t;
};

// Adds the datepicker icon attached to a named field.
WU.addDatePicker = function(el, fieldName, id, styleClass){
    // Needs to add an input and a link around an img
    // returns the input
    var input = WU.addChildElement(el, 'input', styleClass);
    input.name = fieldName;
    input.id = id;
    var link = WU.addChildElement(el, 'a');
    link.href = 'javascript:displayDatePicker("' + fieldName + '");';
    var img = WU.addChildElement(link, 'img');
    img.src = "images/cal.gif";
    img.alt = "Pick a date";
    return [input, link];
};

/**
 * Prints a list of possible address matches to a div.
 * fArray is an array of objects like this:
 * { label: 'Label Text"; fn: function, c: label class}
 * That create links to functions that will be called when the
 * link is clicked. The functions are no-parameter functions that
 * are bound to an address instance.
 */
WU.printAddressMatchList = function(addresses, div, fArray){
    while(div.childNodes.length > 0){
        div.removeChild(div.firstChild);
    }
    var d = document;

    if (addresses == null || addresses.length == 0){
        var p = WU.addChildElement(div, 'p');
        WU.addText(p, 'No addresses found.');
        return;
    }

    for (var i = 0; i < addresses.length; i++){
        var item = WU.makeAddressMatchItem(addresses[i], fArray);
        div.appendChild(item);
        if (i != addresses.length - 1) {
            div.appendChild(d.createElement('hr'));
        }
    }
};

WU.makeAddressMatchItem = function(addr, fns){
    var p = document.createElement('p');
    // Address
    if (addr.streetName) {
            var text1=document.createTextNode(addr.from + " - " + addr.to + " " + addr.streetName);
            p.appendChild(text1);
            p.appendChild(document.createElement('br'));
            var text2=document.createTextNode(addr.city + ", " + addr.state + " " + addr.zip);
            p.appendChild(text2);
    } else {
            var text1=document.createTextNode(addr.address);
            p.appendChild(text1);
    }
    p.appendChild(document.createElement('br'));
    for (var i = 0; i < fns.length; i++){
        p.appendChild(WU.makeFnLink(fns[i].label, fns[i].className, fns[i].fn, addr));
        if (i != fns.length - 1) {
            var spacer = document.createTextNode(' | ');
            p.appendChild(spacer);
        }
    }
    return p;
};

WU.removeChildren = function(el){
    while(el.childNodes.length > 0){
        el.removeChild(el.firstChild);
    }
};

/**
 * Prints a list of possible appointment matches to a table.
 * fArray is an array of objects like this:
 * { label: 'Label Text"; f: function, c: label class}
 * That create links to functions that will be called when the
 * link is clicked. The functions are no-parameter functions that
 * are bound to an address instance.
 */
WU.printAppointmentMatchTable = function(addresses, table, fArray){
    WU.removeChildren(table);
    var d = document;

    if (addresses == null || addresses.length == 0){
        var tr = WU.addChildElement(table, 'tr');
        var td = WU.addChildElement(tr, 'td');
        WU.addText(td, 'No addresses found.');
        return;
    }
    // Build the header row
    var headerData = [{className:'label', contents:'Date'},
                     {className:'label', contents:'Tech.'},
                     {className:'label', contents:'Address'},
                     {className:'label', contents:'Dist.'},
                     {className:'label', contents:'Schedule'}];
    var headerRow = buildTableRow('th', headerRow);
    table.appendChild(headerRow);

    for (var i = 0; i < addresses.length; i++){
        var addr = addresses[i];
        var rowData = [{className:'data', contents:''},
                       {className:'data', contents:''},
                       {className:'data', contents:''},
                       {className:'data', contents:''},
                       {className:'data', contents:''}];
        var tr = WU.buildTableRow('data', rowData);
        table.appendChild(tr);
    }
};

/**
 * cellType : 'td' or 'th'
 * cellArray : {className: 'className'; contents:'TextOrElementOrArray'; }
 */
WU.buildTableRow = function(table, cellType, cellArray){
    var tr = WU.addChildElement(table, 'tr');
    for (var i = 0; i < cellArray.length; i++){
        var contents = null;
        var td = WU.addChildElement(tr, cellType);
        if (cellArray[i].className){
            td.className = cellArray[i].className;
        }

        if (cellArray[i].contents.push){ // Is it an array?
            for (var j = 0; j < cellArray[i].contents.length; j++){
                WU.addTextOrElement(td, cellArray[i].contents[j]);
            }
        } else {
            WU.addTextOrElement(td, cellArray[i].contents);
        }

    }
    return tr;
};

// Adds something to a parent. 'Something' must be text or an element.
WU.addTextOrElement = function(parent, child){
    if (child.getAttribute){ // It is an Element?
        parent.appendChild(child); // Should we clone?
    } else { // Assume it is a string
        WU.addText(parent, child);
    }
};

// Disables all forms and links in the element
WU.disableAll = function(el_id){
    var el = $(el_id);
    el.style.cursor = 'wait';
    var forms = el.getElementsByTagName('form');
    var fArray = $A(forms);
    fArray.each(function(form){
        Form.disable(form);
    });

    var links = el.getElementsByTagName('a');
    var lArray = $A(links);
    lArray.each(function(link){
        link.oldonclick = link.onclick;
        link.onclick = null;
        link.style.cursor = 'wait';
        link.oldhref = link.href;
        link.href = '#';
    });
};

// Enables all forms and links in the element
WU.enableAll = function(el_id){
    var el = $(el_id);
    el.style.cursor = 'pointer';
    var forms = el.getElementsByTagName('form');
    var fArray = $A(forms);
    fArray.each(function(form){
        Form.enable(form);
    });

    var links = el.getElementsByTagName('a');
    var lArray = $A(links);
    lArray.each(function(link){
        link.onclick = link.oldonclick;
        link.oldonclick = null;
        link.style.cursor = 'pointer';
        link.href = link.oldhref;
        link.oldhref = null;
    });
};

WU.populateDeviceSelect = function(el_id) {
    var el = $(el_id);
    var myAjax = new Ajax.Request(
            'device_list_json.php',
            {
                    method: 'get',
                    onComplete: function(req) {
                            WU.populateDeviceSelectReturn(req, el);
                            },
                    onError: WU.populateDeviceError,
                    onFailure: WU.populateDeviceError,
                    selectDiv: el
            });

};

WU.populateDeviceSelectReturn = function(req, select){
    var ary = eval('(' + req.responseText + ')');
    //if (log) { log.info("received device list " + ary); }
    for (var i = 0; i < ary.length; i++){
        //if (log) { log.info("adding device " + ary[i][0]); }
        var opt = WU.addEl(select, 'option');
        opt.value = ary[i][0];
        opt.innerHTML = ary[i][1];
    }
};

WU.populateDeviceError = function(req){
    //alert("Error retrieving device list");
    if (log) { log.info("Error retrieving device list " + req); }
};

WU.disabledLink = function(){
    alert('Please wait.');
};

WU.isSet = function(field, message){
    var valid = field.value != null && trim(field.value) != '';
    if (!valid){
        alert(message);
        field.focus();
        field.select();
    }
    return valid;
};

// Takes an array [{fieldId:failMessage},...]
WU.validateFields = function(array) {
    for(var i = 0; i < array.length; i++){
        WU.isSet($(array[i].fieldId), array[i].message);
    }
};

// Removes leading whitespaces
function LTrim( value ) {
	var re = /\s*((\S+\s*)*)/;
	return value.replace(re, "$1");
};

// Removes ending whitespaces
function RTrim( value ) {
	var re = /((\s*\S+)*)\s*/;
	return value.replace(re, "$1");
};

// Removes leading and ending whitespaces
function trim( value ) {
	return LTrim(RTrim(value));
};

