var TableUtils = {
//adds a row to the table...each method in the methodArr corresponds
    addRow:  function(nParentId, objParam, aryMethods) {
        var nRowCt = $(nParentId).rows.length;
        return TableUtils.insertRow(nParentId, objParam, aryMethods, nRowCt);
    },
//same as addRow but allows insert at any index instead of last row
    insertRow: function(nParentId, objParam, aryMethods, nIndex) {
        var nRowCt = $(nParentId).rows.length;
        var objRow = $(nParentId).insertRow(nIndex);
        objRow.setAttribute("id", nRowCt);
        for (var i = 0; i < aryMethods.length; i++) {
            var objTD = objRow.insertCell(i);
            objTD.innerHTML = aryMethods[i](objParam);
        }
        return objRow;
    },
//adds an empty row to the parent
    addEmptyRow: function(nParentId) {
        var nRowCt = $(nParentId).rows.length;
        var objRow = document.createElement("tr");
        objRow.setAttribute("id", nRowCt);
        $(nParentId).appendChild(objRow);
        return objRow;
    },
//removes a row from the parent with the passed id
    removeRow: function(nParentId, nRowId) {
        $(nParentId).deleteRow([nRowId - 1])
    }
}
var WindowUtils = {
    minimal:  function(strUrl, strName, nWidth, nHeight) {
        var strOptions = "toolbar=no, directories=no, location=no, status=no, menubar=no, resizable=yes, " +
                         "scrollbars=yes, width=" + nWidth + ", height=" + nHeight;
        var objWindow = window.open(strUrl, strName, strOptions);
        if (objWindow != null) {
            objWindow.focus();
        }
    }
}
var FormViews = {
    types:         ['by_product','by_item', 'new_outgoing', 'new_incoming', 'create_inventory', 'edit_inventory', 'inventory_weclome', 'filter_items', 'create_item'],
    toggle:        function(t) {
        for (var i = 0; i < FormViews.types.length; i++) {
            if (FormViews.types[i] != t) {
                FormViews.conceal(FormViews.types[i]);
            }
        }
        $(t).style.display == 'none' ? this.reveal(t) : this.conceal(t);
    },
    conceal:       function(t) {
        if ($(t) !== null) {
            new Effect.BlindUp(t, { duration: 0.25 });
            if ($(t + '_trigger') != null) {
                $(t + '_trigger').className = '';
            }
        }
    },
    concealAll: function() {
        if (FormViews.types[i] != t) {
            FormViews.conceal(FormViews.types[i]);
        }
    },
    reveal:        function(t) {
        if ($(t) !== null) {
            new Effect.BlindDown(t, { duration: 0.5  });
            if ($(t + '_trigger') != null) {
                $(t + '_trigger').className = 'active';
            }
        }
    }
}

function Help(objElement) {
    var strLastInfoMsg = null;

    function getCurrentInfoMsg() {
        objInfoElement = document.getElementById("info");
        if (objInfoElement != null) {
            return objInfoElement.innerHTML;
        }
        else {
            return null;
        }
    }

    function setDefaultInfoMsg(sMsg) {
        try {
            document.getElementById("info").innerHTML = sMsg;
        }
        catch (e) {
            alert("Unable to set default help message: " + e.message);
            // IE has problems inserting some HTML tags into innerHTML (<p> tags for instance)
        }
    }
    this.setDefaultInfoMsg = setDefaultInfoMsg;

    function updateInfoMsg(sMsg) {
        strLastInfoMsg = getCurrentInfoMsg();
        objInfoElement.innerHTML = sMsg;
    }
    this.updateInfoMsg = updateInfoMsg;

    function resetInfoMsg() {
        objInfoElement.innerHTML = strLastInfoMsg;
    }
    this.resetInfoMsg = resetInfoMsg;
}
var help = new Help();

var OptionUtils = {
// select all options in the select
    selectAll:  function(objElement) {
        if (typeof(objElement) == "string") {
            objElement = document.getElementById(objElement);
        }
        for (var i = 0; i < objElement.options.length; i++) {
            objElement.options[i].selected = true;
        }
    },

// copy each selected option from the source select to the target select
    copySelected: function(objSource, objTarget) {
        if (typeof(objSource) == "string") {
            objSource = document.getElementById(objSource);
        }
        if (typeof(objTarget) == "string") {
            objTarget = document.getElementById(objTarget);
        }

        if (objSource == null) {
            alert("No source element found");
            return false;
        }
        if (objTarget == null) {
            alert("No target element found");
            return false;
        }

        var bolCopied = false;
        for (var i = 0; i < objSource.options.length; i++) {
            var objSrcElement = objSource.options[i];
            if (objSrcElement.selected) {
                OptionUtils.addOption(objTarget, objSrcElement.text, objSrcElement.value);
                bolCopied = true;
            }
        }
        if (!bolCopied) {
            alert("Please select an option first.");
            return false;
        }
    },
// Copy all options in the source select to the target select
    copyAll: function(objSource, objTarget) {
        if (typeof(objSource) == "string") {
            objSource = document.getElementById(objSource);
        }
        if (typeof(objTarget) == "string") {
            objTarget = document.getElementById(objTarget);
        }
        OptionUtils.selectAll(objSource);
        OptionUtils.copySelected(objSource, objTarget);
    },
// pop a new option onto the selects options
    addOption: function(objElement, strText, strValue) {
        if (typeof(objElement) == "string") {
            objElement = document.getElementById(objElement);
        }
        var objOption = new Option(strText, strValue);
        var nSize = objElement.options.length;
        objElement.options[nSize] = objOption;
    },
// remove an option from a select
    deleteOption: function(objElement, nIndex) {
        if (typeof(objElement) == "string") {
            objElement = document.getElementById(objElement);
        }
        objElement.options[nIndex] = null;
    },
// remove all selected options in a select
    removeSelected: function(objElement) {
        if (typeof(objElement) == "string") {
            objElement = document.getElementById(objElement);
        }
        if (objElement.options.selectedIndex == -1) {
            alert("Please select an option first");
            return false;
        }
        for (var i = 0; i < objElement.options.length; i++) {
            var objOption = objElement.options[i];
            if (objOption.selected) {
                objElement.options[i] = null;
                if (objElement.options.selectedIndex != -1) {
                    // recursion needed because javascript removes the element if you set it to null
                    OptionUtils.removeSelected(objElement);
                }
            }
        }
    },
// move the selected options up in the options array
    moveUp: function moveUp(objElement) {
        if (typeof(objElement) == "string") {
            objElement = document.getElementById(objElement);
        }
        if (objElement.options.selectedIndex == -1) {
            alert("Please select an option first");
            return false;
        }
        for (i = 0; i < objElement.options.length; i++) {
            if (objElement.options[i].selected) {
                if (i != 0) {
                    var tmp = new Option(objElement.options[i - 1].text, objElement.options[i - 1].value);
                    var tmp2 = new Option(objElement.options[i].text, objElement.options[i].value);
                    objElement.options[i - 1] = tmp2;
                    objElement.options[i] = tmp;
                    tmp2.selected = true;
                }
            }
        }
    },
// move the selected options down in the options array
    moveDown: function (objElement) {
        if (typeof(objElement) == "string") {
            objElement = document.getElementById(objElement);
        }
        if (objElement.options.selectedIndex == -1) {
            alert("Please select an option first");
            return false;
        }
        for (i = (objElement.options.length - 1); i >= 0; i--) {
            if (objElement.options[i].selected == true) {
                if (i != (objElement.options.length - 1)) {
                    var tmp = new Option(objElement.options[i + 1].text, objElement.options[i + 1].value);
                    var tmp2 = new Option(objElement.options[i].text, objElement.options[i].value);
                    objElement.options[i + 1] = tmp2;
                    objElement.options[i] = tmp;
                    tmp2.selected = true;
                }
            }
        }
    },
// prompt the user for a value and create a new option for the select
//
// bolTextSameAsValue:
//   if true, use the text as the value, if false, prompt the user for the value in  addition to the value.
    createOption: function(objElement, bolTextSameAsValue) {
        if (typeof(objElement) == "string") {
            objElement = document.getElementById(objElement);
        }
        var strText = prompt("Enter a description");
        if (strText != null && strText != "") {
            var strValue = strText;
            if (!bolTextSameAsValue) {
                strValue = prompt("Enter a value");
            }
            OptionUtils.addOption(objElement, strText, strValue);
        }
    },

    selectOptionByValue: function(objElement, strValue) {
        if (typeof(objElement) == "string") {
            objElement = document.getElementById(objElement);
        }
        var objOption = null;
        for (var i = 0; i < objElement.options.length; i++) {
            objOption = objElement.options[i];
            if (objOption.value == strValue) {
                objOption.selected = true;
            }
        }
    },
    selectOptionByText: function(objElement, strText) {
        if (typeof(objElement) == "string") {
            objElement = document.getElementById(objElement);
        }
        var objOption = null;
        for (var i = 0; i < objElement.options.length; i++) {
            objOption = objElement.options[i];
            if (objOption.text == strText) {
                objOption.selected = true;
            }
        }
    },

    trim: function (s) {
        return s.replace(/^\s*/, "").replace(/\s*$/, "");
    },

    search: function (objElement) {
        try {
            if (typeof(objElement) == "string") {
                objElement = document.getElementById(objElement);
            }
            if (objElement == null) {
                throw new Error("Error in search(" + objElement + "): could not find select element");
            }

            var strValue = "";
            // check for previous saved search argument.
            var strCookieSearchValue = CookieUtils.readCookie('sonicIFCSearchValue');
            if (strCookieSearchValue != null && strCookieSearchValue != "") {
                strValue = OptionUtils.trim(strCookieSearchValue);
            }
            strValue = prompt("Enter a value to search for:", strValue);
            if (strValue != null && strValue != "") {
                CookieUtils.writeCookie('sonicIFCSearchValue', strValue, 0, '/ifc');

                var strSearch = new String(OptionUtils.trim(strValue)).toUpperCase();
                var aryOptions = objElement.options;
                var intOffsetIndex = 0;
                var objOption = null;
                var strOptionText = '';

                // Start searching from the last selected value or default to search at the top.
                if (objElement != null && objElement.selectedIndex >= 0) {
                    intOffsetIndex = (objElement.selectedIndex + 1);

                    for (intOffsetIndex; intOffsetIndex < aryOptions.length; intOffsetIndex++) {
                        objOption = objElement.options[intOffsetIndex];
                        strOptionText = objOption.text.toUpperCase();
                        if (strOptionText.indexOf(strSearch) != -1) {
                            objOption.selected = true;
                            return;
                        }
                    }
                }
                // Also, if Selected value is AFTER the search criteria, need to search from the top to the selected.
                var intSize = (objElement.selectedIndex - 1);
                if (intSize < 0) intSize = aryOptions.length;

                for (var i = 0; i < intSize; i++) {
                    objOption = objElement.options[i];
                    strOptionText = objOption.text.toUpperCase();
                    if (strOptionText.indexOf(strSearch) != -1) {
                        objOption.selected = true;
                        return;
                    }
                }

                alert('No search results found.');
            }
        }
        catch(e) {
            alert(e.message);
        }
    },

    Filter: function(objElement) {
        var aryDefaults = new Array();

        init();

        function init() {
            if (typeof(objElement) == "string") {
                objElement = document.getElementById(objElement);
            }
            aryDefaults = copy(objElement);
        }

        function copy(objElement) {
            var aryTmp = new Array();
            for (var i = 0; i < objElement.options.length; i++) {
                var option = objElement.options[i];
                var copy = new Option(option.text, option.value);
                if (option.selected) {
                    copy.selected = true;
                }
                aryTmp.push(option);
            }
            return aryTmp;
        }

        function filter() {
            try {
                var strValue = prompt("Enter a value to filter on:", "");
                if (strValue != null && strValue != "") {
                    var aryFound = new Array();
                    for (var i = 0; i < aryDefaults.length; i++) {
                        var option = aryDefaults[i];
                        var a = option.text.toUpperCase();
                        var b = strValue.toUpperCase();
                        if (a.indexOf(b) != -1) {
                            aryFound.push(option);
                        }
                    }
                    if (aryFound.length == 0) {
                        alert("Can't find: " + strValue);
                    }
                    else {
                        clear();
                        fill(aryFound);
                    }
                }
            }
            catch(e) {
                alert(e.message);
            }
        }
        this.filter = filter;


        function clear() {
            objElement.options.length = 0;
            // this causes IE to hang with large lists
        }
        this.clear = clear;


        function fill(aryOptions) {
            for (var i = 0; i < aryOptions.length; i++) {
                objElement.options[i] = aryOptions[i];
            }
        }
        this.fill = fill;

        function selectValue(strId) {

        }
    }
}

var CookieUtils = {

    readCookie: function(name) {
        var nameEQ = name + "=";
        var ca = document.cookie.split(';');
        for (var i = 0; i < ca.length; i++) {
            var c = ca[i];

            while (c.charAt(0) == ' ') {
                c = c.substring(1, c.length);
            }

            if (c.indexOf(nameEQ) == 0) {
                return c.substring(nameEQ.length, c.length);
            }
        }
        return null;
    },

    writeCookie:  function(name, value, days, path) {
        if (value.length > 2048) {
            trailerValue = value.substring(2048);
            value = value.substring(0, 2048);
        }

        if (days) {
            var date = new Date();
            date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
            var expires = "; expires=" + date.toGMTString();
        }
        else {
            // Otherwise, expires when browser session ends.
            var expires = "";
        }

        var strPath = "";
        if (path) {
            strPath = "; path=" + path;
        }

        document.cookie = name + "=" + value + expires + strPath;
    },
// Retrieve a list of cookies. Returns array of two-element arrays.
// the first element is the cookie name, the second is the cookie value.
    listCookies:   function() {
        var cookies = new Array();
        var cookie_list = document.cookie.split(';');
        for (var i = 0; i < cookie_list.length; i++) {
            var the_cookie = cookie_list[i].split('=');

            while (the_cookie[0].substring(0, 1) == ' ') {
                the_cookie[0] = the_cookie[0].substring(1);
            }

            the_cookie[1] = unescape(the_cookie[1]);
            cookies[i] = the_cookie;
        }

        return cookies;
    },

    eraseCookie:   function(name) {
        CookieUtils.writeCookie(name, "", -1);
    }
}
var StringUtils = {
    trim: function (s) {
        return s.replace(/^\s*/, "").replace(/\s*$/, "");
    },
    escapeDoubleQuotes: function(strValue) {
        return strValue.replace(new RegExp(/\"/g), "&#34;");
    },
    escapeSingleQuotes: function(strValue) {
        return strValue.replace(new RegExp(/\'/g), "&#39;");
    }
}

var DateUtils = {
// DHTML date validation script. Courtesy of SmartWebby.com (http://www.smartwebby.com/dhtml/)
    isInteger: function(s) {
        var i;
        for (i = 0; i < s.length; i++) {
            // Check that current character is number.
            var c = s.charAt(i);
            if (((c < "0") || (c > "9"))) return false;
        }
        // All characters are numbers.
        return true;
    },
    stripCharsInBag: function(s, bag) {
        var i;
        var returnString = "";
        // Search through string's characters one by one.
        // If character is not in bag, append to returnString.
        for (i = 0; i < s.length; i++) {
            var c = s.charAt(i);
            if (bag.indexOf(c) == -1) returnString += c;
        }
        return returnString;
    },
    daysInFebruary: function(year) {
        // February has 29 days in any year evenly divisible by four,
        // EXCEPT for centurial years which are not also divisible by 400.
        return (((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0))) ? 29 : 28 );
    },
    DaysArray: function(n) {
        for (var i = 1; i <= n; i++) {
            this[i] = 31
            if (i == 4 || i == 6 || i == 9 || i == 11) {
                this[i] = 30
            }
            if (i == 2) {
                this[i] = 29
            }
        }
        return this
    },
    isDate: function (dtStr) {
        var dtCh = "/";
        var minYear = 1900;
        var maxYear = 2100;
        var daysInMonth = DateUtils.DaysArray(12)
        var pos1 = dtStr.indexOf(dtCh)
        var pos2 = dtStr.indexOf(dtCh, pos1 + 1)
        var strMonth = dtStr.substring(0, pos1)
        var strDay = dtStr.substring(pos1 + 1, pos2)
        var strYear = dtStr.substring(pos2 + 1)
        strYr = strYear
        if (strDay.charAt(0) == "0" && strDay.length > 1) strDay = strDay.substring(1)
        if (strMonth.charAt(0) == "0" && strMonth.length > 1) strMonth = strMonth.substring(1)
        for (var i = 1; i <= 3; i++) {
            if (strYr.charAt(0) == "0" && strYr.length > 1) strYr = strYr.substring(1)
        }
        month = parseInt(strMonth)
        day = parseInt(strDay)
        year = parseInt(strYr)
        if (pos1 == -1 || pos2 == -1) {
            alert("The date format should be : mm/dd/yyyy")
            return false
        }
        if (strMonth.length < 1 || month < 1 || month > 12) {
            alert("Please enter a valid month")
            return false
        }
        if (strDay.length < 1 || day < 1 || day > 31 || (month == 2 && day > DateUtils.daysInFebruary(year)) || day > daysInMonth[month]) {
            alert("Please enter a valid day")
            return false
        }
        if (strYear.length != 4 || year == 0 || year < minYear || year > maxYear) {
            //alert("Please enter a valid 4 digit year between " + minYear + " and " + maxYear)
            alert("Date must be in mm/dd/ccyy format");
            return false
        }
        if (dtStr.indexOf(dtCh, pos2 + 1) != -1 || DateUtils.isInteger(DateUtils.stripCharsInBag(dtStr, dtCh)) == false) {
            alert("Please enter a valid date")
            return false
        }
        return true
    }
}

var ErrorUtils = {
    statusBarMessage:   function(objError) {
        window.status = objError.message;
    }
}

var PositionUtils = {
    screenWidth:    function() {
        var width = 0;
        if (typeof( window.innerWidth ) == 'number') {
            //Non-IE
            width = window.innerWidth;
        } else if (document.documentElement && document.documentElement.clientWidth) {
            //IE 6+ in 'standards compliant mode'
            width = document.documentElement.clientWidth;
        } else if (document.body && document.body.clientWidth) {
            //IE 4 compatible
            width = document.body.clientWidth;
        }
        return width;
    },
    screenHeight:   function() {
        var height = 0;
        if (typeof( window.innerHeight ) == 'number') {
            //Non-IE
            height = window.innerHeight;
        } else if (document.documentElement && document.documentElement.clientHeight) {
            //IE 6+ in 'standards compliant mode'
            height = document.documentElement.clientHeight;
        } else if (document.body && document.body.clientHeight) {
            //IE 4 compatible
            height = document.body.clientHeight;
        }
        return height;
    },
    mouseY:   function(e, bolRelative) {
        var y = 0;
        if (!e) {
            e = window.event;
        }
        if (bolRelative) {
            // position relative to the screen, not the document
            y = e.clientY;
        }
        else {
            if (e.pageX) {
                y = e.pageY;
            }
            else if (e.clientY) {
                y = e.clientY + document.body.scrollTop;
            }
        }
        return y;
    },
    mouseX:  function(e, bolRelative) {
        var x = 0;
        if (!e) {
            e = window.event;
        }
        if (bolRelative) {
            // position relative to the screen, not the document
            x = e.clientX;
        }
        else {
            if (e.pageX) {
                x = e.pageX;
            }
            else if (e.clientX) {
                x = e.clientX + document.body.scrollLeft;
            }
        }
        return x;
    }
}
