// <m name="JavaScript Utilities"
//    author="Edwin Rijvordt (erijvordt@consultdata.nl)"
//    version="1.0"
//    type="library"
//    language="JavaScript"> Client-side Javascript module containing lots of useful utilities.
// </m>

// Capitalize the first letter of a string.
function capWord(str) {
    var f = str.substring(0, 1).toUpperCase();
    return f + str.substring(1, str.length);
}

// Capitalize all words in a string.
function capWords(str) {
    var words = str.split(" ");
    var strNew = "";
    for( var i = 0; i < words.length; ++i ) {
        if (i > 0 && words[i].length > 0) {
            strNew += " ";
        }
        strNew += capWord(words[i]);
    }
    return strNew;
}

// Function to round an amount value to at most 4 decimals after the comma.
function roundAmount(flt) {
    var f = Math.round(flt * 10000) / 10000.0;
    return f;
}

// Trim all leading and trailing whitespace of a string.
function wtrim(str) {
    str = String(str);
    str = str.replace(/^\s+/, "");
    str = str.replace(/\s+$/, "");
    return str;
}

// Check an expresssion for truth.
// The 'source' parameter describes the check that is being done;
// a string version of the expression must be passed via the 'expr' parameter,
// and the value of the expression via the 'value' parameter.
function assert(source, expr, value) {
    if (!value) {
		var msg = "";
		msg += source + ":\n";
        msg += "Assertion failed: \"" + expr + "\".";
        alert(msg);
        return false;
    }
    return true;
}

// Calculate the coordinates needed to center a window of the given
// width and height on the user's screen.  Returns an array with
// two elements: first the x-coordinate, then the y-coordinate.
function centerWindow(width, height) {
	var sw = screen.availWidth;
	var sh = screen.availHeight;
	return [(sw - width)/2, (sh - height)/2];
}

// Language ID's supported by the dayToString, monthToString and formatDate
// functions.
var LANGUAGE_NL = 0; // Dutch language.
var LANGUAGE_EN = 1; // English language.


var arrMonthsNL = ["januari", "februari", "maart", "april", "mei", "juni",
				   "juli", "augustus", "september", "oktober", "november", "december"];

var arrMonthsEN = ["january", "february", "march", "april", "may", "june",
				   "july", "august", "september", "october", "november", "december"];


// Convert a month number into a month name.
// The month number must be from 1 to 12.
// If no language is specified, or null, the Dutch name is returned.
function monthToString(month, lang) {
    if (lang == null) {
        lang = LANGUAGE_NL;
    }

    if (lang == LANGUAGE_EN) {
		return capWord(arrMonthsEN[month-1]);
	} else {
		return arrMonthsNL[month-1];
    }
}

var arrDaysNL = ["zondag", "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag"];

var arrDaysEN = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];

// Convert a weekday number into a day name.
// The day number must be from 1 to 7, where 1 is sunday.
// If lang is 1, the Dutch name is returned, else the English name.
// If no language is specified, or null, the Dutch is returned as well.
function dayToString(day, lang) {
    if (lang == null) {
        lang = LANGUAGE_NL;
    }

	if (lang == LANGUAGE_EN) {
		return capWord(arrDaysEN[day-1]);
    } else {
		return arrDaysNL[day-1];
    }
}

// Format a date.  Use one these types to determine the format:
//
var DATEFMT_DMY      = 0; // day-month-year: all numbers
var DATEFMT_YMD      = 1; // year-month-day: all numbers
var DATEFMT_DMY_HM   = 2; // day-month-year hh:mm (all numbers)
var DATEFMT_DMY_HMS  = 3; // day-month-year hh:mm:ss (all numbers)
var DATEFMT_YMD_HMS  = 4; // year-month-day hh:mm:ss (all numbers)
var DATEFMT_LONG     = 5; // dayname day monthname year
var DATEFMT_LONG_HM  = 6; // dayname day monthname year hh:mm
var DATEFMT_LONG_HMS = 7; // dayname day monthname year hh:mm:ss
var DATEFMT_TEXT     = 8; // day monthname year
var DATEFMT_TEXT_HM  = 9; // day monthname year hh:mm
var DATEFMT_TEXT_HMS = 10;// day monthname year hh:mm:ss
var DATEFMT_HM       = 11;// hh:mm
var DATEFMT_HMS      = 12;// hh:mm:ss

function formatDate(date, type, lang) {
    if (lang == null) {
        lang = LANGUAGE_NL;
    }

    var day = date.getDate();
    var weekDay = date.getDay();
    var month = String(date.getMonth() + 1);
    var year = date.getFullYear();
    var hour = String(date.getHours());
    var minute = String(date.getMinutes());
    var second = String(date.getSeconds());

    if (type <= DATEFMT_YMD_HMS && day.length < 2) {
        day = "0" + day;
    }

    if (type <= DATEFMT_YMD_HMS && month.length < 2) {
        month = "0" + month;
    }

    if (hour.length < 2) {
        hour = "0" + hour;
    }

    if (minute.length < 2) {
        minute = "0" + minute;
    }

    if (second.length < 2) {
        second = "0" + second;
    }

    if (type == DATEFMT_DMY) {
		return day + "-" + month + "-" + year;

    } else if (type == DATEFMT_YMD) {
		return year + "-" + month + "-" + day;

    } else if (type == DATEFMT_DMY_HM) {
		return day + "-" + month + "-" + year + " " + hour + ":" + minute;

	} else if (type == DATEFMT_DMY_HMS) {
		return day + "-" + month + "-" + year + " " + hour + ":" + minute + ":" + second;

	} else if (type == DATEFMT_YMD_HMS) {
		return year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second;

	} else if (type == DATEFMT_TEXT) {
		if (lang == LANGUAGE_NL) {
			return day + " " + monthToString(month, lang) + " " + year;
		} else {
			return monthToString(month, lang) + " " + day + ", " + year;
		}

	} else if (type == DATEFMT_TEXT_HM) {
		if (lang == LANGUAGE_NL) {
			return day + " " + monthToString(month, lang) + " " + year + " " + hour + ":" + minute;
		} else {
			return monthToString(month, lang) + " " + day + ", " + year + " " + hour + ":" + minute;
		}

	} else if (type == DATEFMT_TEXT_HMS) {
		if (lang == LANGUAGE_NL) {
			return day + " " + monthToString(month, lang) + " " + year + " " + hour + ":" + minute + ":" + second;
		} else {
			return monthToString(month, lang) + " " + day + ", " + year + " " + hour + ":" + minute + ":" + second;
		}

	} else if (type == DATEFMT_LONG) {
		if (lang == LANGUAGE_NL) {
			return dayToString(weekDay + 1, lang) + " " + day + " " + monthToString(month, lang) + " " + year;
		} else {
			return dayToString(weekDay + 1, lang) + ", " + monthToString(month, lang) + " " + day + ", " + year;
		}

	} else if (type == DATEFMT_LONG_HM) {
		if (lang == LANGUAGE_NL) {
			return dayToString(weekDay + 1, lang) + " " + day + " " + monthToString(month, lang) + " " + year + " " + hour + ":" + minute;
		} else {
			return dayToString(weekDay + 1, lang) + ", " + monthToString(month, lang) + " " + day + ", " + year + " " + hour + ":" + minute;
		}


	} else if (type == DATEFMT_LONG_HMS) {
		if (lang == LANGUAGE_NL) {
			return dayToString(weekDay + 1, lang) + " " + day + " " + monthToString(month, lang) + " " + year + " " + hour + ":" + minute + ":" + second;
		} else {
			return dayToString(weekDay + 1, lang) + ", " + monthToString(month, lang) + " " + day + ", " + year + " " + hour + ":" + minute + ":" + second;
		}

	} else if (type == DATEFMT_HM) {
		return hour + ":" + minute;

	} else if (type == DATEFMT_HMS) {
		return hour + ":" + minute + ":" + second;

	} else {
		return "[invalid date type given to formatDate: " + type + "]";
    }
}

function getDayOptionList(name, date, options, noneSelected) {
    var html = "<SELECT NAME='" + name + "' " + options + ">";
    var day = -1;
    if (date != null) {
        day = date.getDate();
    } else if (!noneSelected) {
		day = new Date().getDate();
	} else {
        html += "<OPTION VALUE='-1'>-</OPTION>";
    }
    for( var i = 1; i <= 31; ++i ) {
        html += "<OPTION VALUE='" + i + "'";
        if (i == day) {
            html += " SELECTED";
        }
        html += ">" + i + "</OPTION>";
    }
	html += "</SELECT>";
    return html;
}

var arrMonthsEN = ["January", "February", "March", "April", "May", "June",
				   "July", "August", "September", "October", "November", "December"];

function getMonthOptionList(name, date, options, noneSelected) {
    var html = "<SELECT NAME='" + name + "' " + options + ">";
    var month = -1;
    if (date != null) {
        month = date.getMonth();
    } else if (!noneSelected) {
		month = new Date().getMonth();
	} else {
        html += "<OPTION VALUE='-1'>-</OPTION>";
    }
    for( var i = 0; i < 12; ++i ) {
        html += "<OPTION VALUE='" + (i+1) + "'";
        if (i == month) {
            html += " SELECTED";
        }
        html += ">" + arrMonthsEN[i] + "</OPTION>";
    }
	html += "</SELECT>";
    return html;
}

function getYearOptionList(name, firstYear, lastYear, date, options, noneSelected) {
    var html = "<SELECT NAME='" + name + "' " + options + ">";
    var year = -1;
    if (date != null) {
        year = date.getFullYear();
    } else if (!noneSelected) {
		year = new Date().getFullYear();
	} else {
        html += "<OPTION VALUE='-1'>-</OPTION>";
    }
    for( var i = firstYear; i <= lastYear; ++i ) {
        html += "<OPTION VALUE='" + i + "'";
        if (i == year) {
            html += " SELECTED";
        }
        html += ">" + i + "</OPTION>";
    }
	html += "</SELECT>";
    return html;
}

// Use the above three functions to create date input fields.
// The names are constructed by appending "Day", "Month" and "Year" to the given name.
// If noneSelected is given and true, options name "-" are added as the first option,
// to indicate that no date has been chosen.
function getDateOptionLists(name, firstYear, lastYear, date, options, noneSelected) {
    var html = "";

    html += getDayOptionList(name + "Day", date, options, noneSelected);
    html += getMonthOptionList(name + "Month", date, options, noneSelected);
    html += getYearOptionList(name + "Year", firstYear, lastYear, date, options, noneSelected);

    return html;
}

// Create date input fields.
// The names are constructed by appending "Day", "Month" and "Year" to the given name.
function getDateInputs(name, date, noneSelected) {
    var html = "<font face='courier'>";

    var year = "";
    if (date != null) {
        year = date.getFullYear();
    } else if (!noneSelected) {
		year = new Date().getFullYear();
	}
    html += "<input class='dt' type='text' size='4' maxlength='4' name='" + name + "Year' value='" + year + "'/>";

    var month = "";
    if (date != null) {
        month = 1 + date.getMonth();
    } else if (!noneSelected) {
		month = 1 + (new Date().getMonth());
	}
    html += "<input class='dt' type='text' size='2' maxlength='2' name='" + name + "Month' value='" + month + "'/>";

    var day = "";
    if (date != null) {
        day = date.getDate();
    } else if (!noneSelected) {
		day = new Date().getDate();
	}
    html += "<input class='dt' type='text' size='2' maxlength='2' name='" + name + "Day' value='" + day + "'/>";

    html += "</font>";
    html += " (yyyy-mm-dd)";

    return html;
}

// Maximize the height attribute in the given attribute string (to be passed to window.open()).
function maximizeHeight(attrs) {
	var newHeight = screen.availHeight - 48;
    attrs = attrs.replace(/height=[0-9]+/, "height=" + newHeight);
    return attrs;
}

// Convert an array to a map.
function arrayToMap(arr) {
    var dict = new Object();
    for( var i = 0; i < arr.length; ++i ) {
        dict[arr[i]] = 1;
    }
    return dict;
}

// Convert an array to a map.  Each item in the array must be of the
// form a:b, where a will become the key in the map, and b the value.
function arrayToMap2(arr) {
    var dict = new Object();
    for( var i = 0; i < arr.length; ++i ) {
        var item = arr[i].split(":");
        dict[parseInt(item[0], 10)] = parseInt(item[1], 10);
    }
    return dict;
}

// Word-wrap a string to lines no longer than 'maxWidth' characters.
function wordWrap(str, maxWidth) {
    if (str.length == 0 || maxWidth < 1) {
        return str;
    }

    var wrapped = "";
    var words = str.split(/[ \n\r\t]/g);
    var width = 0;
    for( var i = 0; i < words.length; ++i ) {
        var word = words[i];
        var wordWidth = word.length;
        if (width + wordWidth > maxWidth) {
            wrapped += "\n";
            width = 0;
        }

        if (width > 0 && wordWidth > 0) {
            wrapped += " ";
            ++width;
        }

        wrapped += word;
        width += wordWidth;
    }

    return wrapped;
}

