(function(window, $) {

/*********************************
          School Form
*********************************/

// private vars
var SF = SchoolForm = {},
    _loading = false,
    _abort = null,
    _complete = null,
    _error = null;

/**
 * Verify that all required parameters are accounted for and valid.
 * @param dictionary params Dictionary of parameters that we'll be verifying:
 *                          List of acceptable keys: path, form_id, postal
 * @access private
 */
function _checkParams(params) {
    // check for required parameters
    if (!params || typeof params.path != 'string') {
        _trigger('error', SF.defaults.INV_ARGS);
    } else {
        return true;
    }

    return false;
}

/**
 * Determines if an ajax response has been aborted by checking the response headers
 * @param object xhr XmlHttpRequest object
 * @return boolean
 * @access private
 */
function _userAborted(xhr) {
    return !xhr.getAllResponseHeaders();
}

/**
 * Triggers a set of instructions based on the provided event name.
 * @param string eventName Event name to trigger
 *        Currently supports values of 'abort', 'complete', and 'error' for `eventName`.
 * @access private
 */
function _trigger(eventName) {
    switch (eventName) {
        // arguments: string [data] - HTML data
        case 'complete':
            var handler = SF.defaults.completeHandler;

            if (typeof _complete == 'function') {
                handler = _complete;
            }
            _cleanup();

            // trigger user-defined completion handler
            if (handler) handler(arguments[1]);
            break;

        case 'error': // argument: string/int [error] - Error code/status
            // save error callback
            var handler = SF.defaults.errorHandler;
            if (typeof _error == 'function') {
                handler = _error;
            }

            // trigger user-defined error handler
            if (handler) handler(arguments[1]);
            _cleanup();
            break;

        case 'abort': 
            if (!_loading) return; // if already stopped, just bail

            // save abort callback
            var handler = SF.defaults.abortHandler;
            if (typeof _abort == 'function') {
                handler = _abort;
            }

            // trigger user-defined abort handler
            if (handler) handler();
            _cleanup();
            break;
    }
}

/**
 * Cleans user defined callbacks and internal result set.
 * @param boolean keepResults Set to true if results shouldn't be cleared. Default: false.
 * @access private
 */
function _cleanup(keepResults) {
    _laoding = false;
    _complete = null;
    _error = null;
    _abort = null;
}

/*
 * Initiates the form building process by sending an asynchrous request that triggers the server-side handler.
 * @param string request_path URL path to start the search request in the backend
 * @param dictionary data Dictionary to pass as filter parameters to the server-side handler
 * @access private
 */
function _sendRequest(request_path, data) {
    if (_loading) return;

    var error = false;
    var errorCB = function(xhr, status) {
        if (error) return; // prevent duplicate calls
        error = true;

        if (!xhr.status || _userAborted(xhr)) {
            _trigger('abort');
        } else {
            _trigger('error', SF.defaults.AJAX_REQ);
        }
    };

    _loading = true;
    $.ajax({
        type: 'GET',
        url: request_path,
        data: data,
        cache: false,
        dataType: 'json',

        success: function(data, status, xhr) {
            if (xhr && xhr.status) {
                if (data.error == 0) { 
                    delete data.error;
                    _trigger('complete', data);
                } else {
                    _trigger('error', data.error);
                }
            } else {
                errorCB(xhr, status);
            }
        },

        error: errorCB
    });
}

// SchoolForm Class
SF = SchoolForm = {
    defaults: {
        /* errors */
        INV_ARGS: -1,
        INV_SCHOOL: -2,
        INV_CAMPUS: -3,
        NO_OFFERINGS: -4,
        AJAX_REQ: -999,

        /* handlers */
        abortHandler: null,
        completeHandler: null,
        errorHandler: null
    },


    /**
     * @param dictionary params Dictionary to pass as parameters to the server-side handler
     * @access public
     */
    load: function(params) {
        if (_loading) return;

        // custom handlers
        if (typeof params.complete == 'function') {
            _complete = params.complete;
            delete params.complete;
        }
        if (typeof params.error == 'function') {
            _error = params.error;
            delete params.error;
        }
        if (typeof params.abort == 'function') {
            _abort = params.abort;
            delete params.abort;
        }
        if (!_checkParams(params)) return;

        // kick off form load process
        var path = params.path
        delete params.path;

        _sendRequest(path, params);
    }
};

// expose to global object
window.SchoolForm = SchoolForm;

})(window, jQuery);

