// SSG-3850 used by
// https://uwdev.service-now.com/nav_to.do?uri=catalog_script_client.do?sys_id=b9dc4e5d6fa6a60054aacd16ad3ee4ea
function changePersNoticeChangeHelpText(HELP_TEXT_CHANGE_MAP) {
    setTimeout(function () {
        var LOGSRC = ['UWITGlobalCatalogItemFunctions', 'changePersNoticeChangeHelpText()'].join('.');
        console.log(LOGSRC);
        // original_help_text: new_help_text
        // var HELP_TEXT_CHANGE_MAP = {
        // 'Select a Division and Unit.  Refer to <a href="https://www.washington.edu/intech/hr/people/contacts/org.php" target="_blank">UW-IT Organizational Chart</a>.': "Employee's new division / unit",
        // 'UW-IT office building': "Employee's new office building",
        // "Employee's phone number (xxx-xxx-xxxx)": "Employee's new phone number (xxx-xxx-xxxx)",
        // "Supervisor's UW NetID": "New supervisor's UW NetID",
        // 'Budget number (xx-xxxx)': "New budget number on which Employee's salary will be paid (xx-xxxx)"
        // };

        try {
            var helpblocks = angular.element("[class*='help-block']");
            console.log([LOGSRC, 'helpblocks.length', helpblocks.length].join('\n'));
            var i;
            var n;
            for (i = 0, n = helpblocks.length; i < n; i++) {
                var current_help_text = helpblocks[i].innerHTML;
                var new_help_text = HELP_TEXT_CHANGE_MAP[current_help_text];
                if (new_help_text) {
                    if (console && console.log) {
                        console.log(['Changing', current_help_text, 'to', new_help_text].join('\n'));
                    }
                    helpblocks[i].innerHTML = new_help_text;
                }
            }
        } catch (e) {
            console.log([LOGSRC, e].join('\n'));
        }
    }, 1000);
} // changePersNoticeChangeHelpText


/*
 * @param ex exception object from try catch block; logged after all other passed args
 * @param show_trace boolean, if true run console.trace()
 * @param msg object to log
 */
function UWITJSException(ex, show_trace, msg) {
    if (!ex) throw new Error('Missing required argument "ex" (exception object from catch block)');
    console.log('UWITJSException', arguments);
    try {
        if (typeof show_trace !== 'boolean') show_trace = false;
        var objs_to_log = [];
        if (arguments.length === 2) {
            // assume show_trace is msg
            objs_to_log.push(arguments[1]);
        } else {
            objs_to_log = arguments.slice(2); // log everything after show_trace arg
        }
        objs_to_log.push(ex);
        if (console.error) {
            console.error(objs_to_log);
        } else if (console.log) {
            console.log(objs_to_log);
        }
        // else { alert(msg); }
        if (show_trace && console.trace) console.trace();
    } catch (e) {
        console.error('UWITJSException', e);
    }
};

top.INVALID_FIELDS = {};

function __setFieldAsInvalid(fieldname) {
    if (!fieldname) return;
    top.INVALID_FIELDS[fieldname] = true;
}

function __setFieldAsValid(fieldname) {
    if (!fieldname) return;
    try {
        delete top.INVALID_FIELDS[fieldname];
    } catch (e) {
        console.error(['__setFieldAsInvalid', fieldname, e]);
    }
}

function UWITBudgetFieldsValidator(g_form) {
    if (!g_form) throw new Error('Missing required argument "g_form"');
    this.g_form = g_form;
    this.UWIT_BUDGET_FIELDS = {
        'budget': {
            regex: '^[0-9]{2}-[0-9]{4}$',
            error: 'Must be in the budget format of 00-0000.'
        },
        'pca_project': {
            regex: '^[0-9a-zA-Z]{1,6}$',
            error: 'Must only include 1-6 letters or numbers.'
        },
        'pca_option': {
            regex: '^[0-9a-zA-Z]{1,3}$',
            error: 'Must only include 1-3 letters or numbers.'
        },
        'pca_task': {
            regex: '^[0-9a-zA-Z]{1,3}$',
            error: 'Must only include 1-3 letters or numbers.'
        }
    };

    /*
     * @param field string, one of: budget, pca_project, pca_project, pca_option, pca_task
     * @param fieldname string, name of variable (item_option_new.name)
     * @returns boolean
     */
    this.validateBudgetFieldOnChange = function (field, fieldname, newValue) {
        if (!field) throw new Error('Missing required argument "field"');
        if (!(/^(?:budget|pca_(?:project|option|task))$/.test(field))) throw new Error('Invalid field.  Must be one of budget, pca_project, pca_option, or pca_task');
        if (!fieldname) throw new Error('Missing required argument "fieldname"');
        try {
            if (field === 'budget') {
                return this.validateBudget(field, fieldname, newValue);
            }
            var FIELD_REGEXP = this.UWIT_BUDGET_FIELDS[field].regex;
            var FIELD_ERROR = this.UWIT_BUDGET_FIELDS[field].error;
            this.g_form.hideFieldMsg(fieldname, true);
            if (newValue && !(newValue.match(FIELD_REGEXP))) {
                this.g_form.showErrorBox(fieldname, FIELD_ERROR);
                __setFieldAsInvalid(fieldname);
                return false;
            }
            __setFieldAsValid(fieldname);
            return true;
        } catch (e) {
            throw e;
        }
    }; // validateBudgetFieldOnChange

    // TODO
    this.validateBudget = function (field, fieldname, newValue) {
        if (newValue === '') return;
        if (top.budgetValidationInProgress) return;

        var g_form = this.g_form;
        top.isValidUWBudget = false;
        top.budgetValidationInProgress = true;
        g_form.hideFieldMsg(fieldname, true);

        if (newValue.match(/^[0-9]{6}$/)) {
            newValue = newValue.substr(0, 2) + '-' + newValue.substr(2, 4);
            this.g_form.setValue(fieldname, newValue);
        }
        var FIELD_REGEXP = this.UWIT_BUDGET_FIELDS[field].regex;
        var FIELD_ERROR = this.UWIT_BUDGET_FIELDS[field].error;
        if (newValue && !(newValue.match(FIELD_REGEXP))) {
            top.budgetValidationInProgress = false;
            g_form.showErrorBox(fieldname, FIELD_ERROR);
            __setFieldAsInvalid(fieldname);
            return false;
        }

        var ajax = new GlideAjax('AJAXUWBudget');
        ajax.addParam('sysparm_name', 'isValid');
        ajax.addParam('sysparm_budget', newValue);
        ajax.getXMLAnswer(function (answer) {
            try {
                console.log(['validateBudget', newValue, answer]);
                // getXMLAnswer returns a string
                if (answer === "true") {
                    g_form.showFieldMsg(fieldname, 'Budget is valid and open for charges.', 'info', false);
                    __setFieldAsValid(fieldname);
                    top.isValidUWBudget = true;
                } else {
                    g_form.showErrorBox(fieldname, 'Must be a valid budget open for charges.', true);
                    __setFieldAsInvalid(fieldname);
                    top.isValidUWBudget = false;
                }
                top.budgetValidationInProgress = false;
            } catch (e) {
                UWITJSException(e, true, newValue, answer);
            }
        });
    }; // validateBudget

    // TODO
    // is this needed? fields are already validated onChange
    this.validateBudgetFieldsOnSubmit = function (fieldnames) {
        if (!fieldnames) throw new Error('Missing required argument "fieldnames"');
        try {
            var LOGSRC = 'validateBudgetFields';
            var error = false;
            var invalid_fields = Object.keys(top.INVALID_FIELDS);
            if (invalid_fields.length > 0) {
                this.g_form.addErrorMessage('One or more budget fields are not valid.  Correct them and try again.');
                return false;
            }
            // validate budget
            if (top.budgetValidationInProgress) {
                this.g_form.addErrorMessage('Budget validation in progress.  Please wait until it finishes then try again.')
                return false;
            }

            if (top.isValidUWBudget == false) {
                this.g_form.addErrorMessage('Budget validation in progress.  Please wait until it finishes then try again.')
                return false;
            }
            var i;
            var n;
            for (i = 0, n = fieldnames.length; i < n; i++) {
                if (!top.INVALID_FIELDS) this.g_form.hideFieldMsg(fieldname);
            }
        } catch (e) {
            throw e;
        }
    }; // validateBudgetFieldsOnSubmit
}


var UWITOnChangeValidationFunctions = {
    'pca_option': function (control, oldValue, newValue, isLoading, g_form, global_name, variable_name) {
        var v = new UWITBudgetFieldsValidator(g_form);
        return v.validateBudgetFieldOnChange('pca_option', variable_name, newValue);
    },
    'pca_project': function (control, oldValue, newValue, isLoading, g_form, global_name, variable_name) {
        var v = new UWITBudgetFieldsValidator(g_form);
        return v.validateBudgetFieldOnChange('pca_project', variable_name, newValue);
    },
    'pca_task': function (control, oldValue, newValue, isLoading, g_form, global_name, variable_name) {
        var v = new UWITBudgetFieldsValidator(g_form);
        return v.validateBudgetFieldOnChange('pca_task', variable_name, newValue);
    },
    'budget': function (control, oldValue, newValue, isLoading, g_form, global_name, variable_name) {
        var v = new UWITBudgetFieldsValidator(g_form);
        return v.validateBudgetFieldOnChange('budget', variable_name, newValue);
    }
};


/*
 * For use in onChange catalog client scripts.
 * Script must return on isLoading, otherwise there will be a javascript error on page load.
 *
 * A corresponding validation function must exist for global_name in UWITOnChangeValidationFunctions.
 * All arguments are required.
 *
 * @param global_name string, a global name for a validation function in UWITOnChangeValidationFunctions.
 * @param variable_name string, "Variable name" field on a catalog client script, aka item_option_new.variable_name
 *
 * Sample usage in onChange catalog client script:
function onChange(control, oldValue, newValue, isLoading) {
    if (isLoading) return;
    return UWITValidateOnChange(control, oldValue, newValue, isLoading, g_form, 'pca_task', 'u_pca_task');
}
 */
function UWITValidateOnChange(control, oldValue, newValue, isLoading, g_form, global_name, variable_name) {
    try {
        // TODO is returning on isLoading global?
        if (isLoading) return;
        // TODO other required arguments?
        if (arguments.length != 7) throw new Error('Missing required number of arguments');
        var missing_required_args = [];
        if (!g_form) missing_required_args.push('g_form');
        if (!global_name) missing_required_args.push('global_name');
        if (!variable_name) missing_required_args.push('variable_name');
        if (missing_required_args.length > 0) {
            throw new Error('Missing required argument(s): ' + missing_required_args.join(', '));
        }

        var fn = UWITOnChangeValidationFunctions[global_name];
        if (!fn) throw new Error('Unimplemented validation function for "' + global_name + '"');
        if (typeof fn !== 'function') throw new Error('Validation function must be a function type');

        if (fn && typeof fn === 'function') {
            return fn.apply(null, arguments);
        }
    } catch (e) {
        UWITJSException(e, true, 'UWITValidatorOnChange');
        throw e;
    }
}


(function () {
    // https://jira.cac.washington.edu/browse/SSG-4312
    // https://uwdev.service-now.com/sp?id=sc_cat_item&sys_id=5a1402036f303500328c8bec5d3ee422
    // https://community.servicenow.com/community?id=community_question&sys_id=e87f0725dbdcdbc01dcaf3231f9619ee&view_source=searchResult
    function initMutationObserver(targetNode) {
        // console.log(['initMutationObserver()', targetNode]);
        if (!targetNode) {
            return false;
        }
        var observer = new MutationObserver(function (mutationList) {
            for (var mutation of mutationList) {
                if (mutation && mutation.addedNodes && mutation.addedNodes.length > 0) {
                    mutation.addedNodes.forEach(function (element) {
                        if (element.className && element.className.match(/(?:bg-(?:danger|info))/)) {
                            $(element).html(element.innerText);
                        }
                    });
                }
            }
        });

        var config = {
            childList: true,
            attributes: false,
            subtree: true
        };
        observer.observe(targetNode, config);
    }

    // waits 15 seconds for sc_cat_item
    top.UWITWaitForCatalogItemElement = function (elapsedTime) {
        var targetNode = document.getElementById('sc_cat_item');
        // console.log(['top.UWITWaitForCatalogItemElement()', elapsedTime, typeof targetNode]);
        if (targetNode == null) {
            if (elapsedTime <= 15000) {
                // console.log('top.UWITWaitForCatalogItemElement() setTimeout');
                setTimeout("top.UWITWaitForCatalogItemElement(" + (elapsedTime + 500) + ")", 500);
            } else {
                // console.log('top.UWITWaitForCatalogItemElement timed out.  no sc_cat_item?');
                // timed out
            }
        } else {
            // console.log(['top.UWITWaitForCatalogItemElement()', elapsedTime, 'initMutationObserver', typeof targetNode, targetNode]);
            initMutationObserver(targetNode);
        }
    };
    jQuery(document).ready(function () {
        top.UWITWaitForCatalogItemElement(0);
    });

}());