
//----------------------------------------------------------

// Some utilities for error reporting:

function customerServiceText ()
{
    return 'If this problem persists, please contact'
         + ' Atomic Learning Customer Service:\r\n'
         + '\r\n'
         + '   1-320-631-5900 ext 8\r\n'
         + '   cs@atomiclearning.com';
}

// Typically used in AJAX onFailure callbacks, where the request
// never hit the server:
//
function ajaxTransportError ()
{
    genericError('There was a problem connecting to the server,'
               + ' please try again.');
}

// Typically used in AJAX onSuccess callbacks, where some sort
// of server error or failure was indicated:
//
function genericError (msg, doParent)
{
    var text = '';
    if (typeof msg == 'object') {
        text = msg.msg + '\r\n\r\n';
    }
    else if (msg) {
        text = msg + '\r\n\r\n';
    }
    text += customerServiceText();

    al_alert(text, doParent);
}

// A generic popup message
//
function al_alert (params, doParent)
{
    var msg   = '';
    var title = 'Atomic Learning';

    if (typeof params == 'object') {
        msg     = params.msg;
        if(typeof params.title != 'undefined'){
                title   = params.title;
        }
    }
    else {
        msg = params;
    }

    var extInstance = null;
    if (doParent && parent.Ext) {
        extInstance = parent.Ext;
    }
    else if (Ext) {
        extInstance = Ext;
    }

    if (extInstance) {
        var htmlMsg = msg.replace(/\r?\n/g, '<br />').replace(/\t/g, '&nbsp;&nbsp;&nbsp;&nbsp;');
        var cb = extInstance.emptyFn();
        cb = params.callback;
        extInstance.Msg.alert(title, htmlMsg, cb);
    }
    else {
        alert(msg);
    }

    return true;
}

// Utility function for using the console
// This allows it to be commented out in one
// place.
function console_log (msg) {
    if (window.console) {
        console.log(msg);
    }
}

//----------------------------------------------------------

// Utility for making Ajax requests.
//
// Assumes JSON response includes a "status" value that is
// set to "success" if the onSuccess callback is to be invoked.
//
// If the JSON status is not "success", can optionally include
// a "msg" value to be included in the error message that is
// presented to the user.
//
// "opts" can include:
//     url (required) - e.g. "/admin/customseries"
//     parameters - for form post
//     onSuccess - callback function
//     failureMessage - e.g. "The attempt to reorder failed"
//                      (no trailing punctuation, for default onNotSuccess)
//     onNotSuccess - optional callback function
//
function makeAjaxRequest (opts)
{
    var url = opts.url ? opts.url : '/';
    url = ALBase.make_uri(url);

    var parameters = opts.parameters ? opts.parameters : {};

    var failureMessage = opts.failureMessage ? opts.failureMessage
                                             : 'The request failed';

    var onSuccess = opts.onSuccess ? opts.onSuccess : function () {};

    var onNotSuccess = opts.onNotSuccess
            ? opts.onNotSuccess
            : function (json) {
                  var msg = failureMessage + ', please try again.'
                  if (json.msg) {
                      msg += '\r\n\r\n'
                           + 'The message was:'
                           + '\r\n\r\n'
                           + '\t' + json.msg;
                  }
                  genericError(msg);
              };

    var onFailure = opts.onFailure
            ? opts.onFailure
            : function () { ajaxTransportError(); };

    var ajax = new Ajax.Request(url, {
        method:     'post',
        parameters: parameters,
        onSuccess:  function (transport) {
                        var json = transport.responseText.evalJSON(true);
                        if (json.status == 'success') {
                            onSuccess(json);
                        }
                        else {
                            onNotSuccess(json);
                        }
                    },
        onFailure:  onFailure
    });
}

//----------------------------------------------------------

// HACK HACK HACK
//
// As of Firefox 3.0.11:
//
// There is a bug in Firefox that happens when an Iframe is loaded.
// It creates a duplicate entry for the current page (not the
// Iframe) at the top of the history list, and that duplicate entry
// causes the Back button to not work.  The bug is triggered when
// we load an Iframe into floatbox.
//
// The fix replaces the current "someurl" with "someurl#reload".
// This changes the most recent history entry, but does not actually
// reload the page in the browser.  This allows back to work, since
// now the two most recent entries are different.  Then we go "back"
// one entry past the duplicate, to get to the original page.
//
// Yuck.
//
// Another complication is that the duplicate history entry seems
// to only happen if the Iframe is loaded *before* the page finishes
// loading.  So in that case, we do *not* want to do the history
// fix.
//
// Double yuck.
//

var fixFirefoxBrowserHistoryPageIsLoaded = false;
var fixFirefoxBrowserHistoryNeedFix      = true;

Ext.onReady(function () {
    // Set a flag when the page is loaded:
    fixFirefoxBrowserHistoryPageIsLoaded = true;
});

// Call this function with floatbox "beforeBoxStart" handler:
//
function fixFirefoxBrowserHistoryCheckPageLoad ()
{
    // Only need to fix the duplicate history entry if the page
    // has finished loading at the time the floatbox is loaded: 
    //
    fixFirefoxBrowserHistoryNeedFix = fixFirefoxBrowserHistoryPageIsLoaded;
}

// Call this function with floatbox "beforeBoxEnd" handler:
//
function fixFirefoxBrowserHistoryCheckContentType (box)
{
    // Do not need history fix if an inline DIV was loaded,
    // as opposed to an IFRAME:
    //
    if (box && box.currentItem && box.currentItem.type == 'inline') {
        fixFirefoxBrowserHistoryNeedFix = false;
    }
}

// Call this function with floatbox "afterBoxEnd" handler:
//
function fixFirefoxBrowserHistory ()
{
    // TODO not working consistently, turned off for now!
    return;

    if (! fixFirefoxBrowserHistoryNeedFix) return;

    var offsets = document.viewport.getScrollOffsets();

    var newLocationHref;
    if (location.hash == '#reload') {
        newLocationHref = location.href.replace(/#reload$/, '');
    }
    else {
        newLocationHref = location.href + '#reload';
    }
    location.replace(newLocationHref);
    history.back();

    window.scroll(offsets[0], offsets[1]);
}

//----------------------------------------------------------

function removeNewlyCreated ()
{
    // Remove the "newly_created" class name
    // from existing elements:
    //
    $$('.newly_created').each(
            function (el) {
                $(el).removeClassName('newly_created');
            }
    );
    $$('.newly_created_dark').each(
            function (el) {
                $(el).removeClassName('newly_created_dark');
            }
    );
}

function removeNewlyCreatedAfterDelay ()
{
    setTimeout('removeNewlyCreated()', 4000);
}

//----------------------------------------------------------

function saveMyTrainingState (divId)
{
    // Need to give the toggle some time to update the div,
    // before we test if it is visible or not:
    //
    setTimeout("_saveMyTrainingState('" + divId + "')", 500);
}

function _saveMyTrainingState (divId)
{
    var state = $(divId).visible() ? 'open' : 'closed';

    var url = ALBase.make_uri('/session/set_mytraining_state/'
                              + divId + '/' + state);

    new Ajax.Request(url, {
        method: 'post'
        // no need for onSuccess or onFailure,
        // silent failure is ok...
    });
}

//----------------------------------------------------------

// E.g.:
//    <textarea
//       onkeydown="textCounter(this,myform.numchars,128)"
//         onkeyup="textCounter(this,myform.numchars,128)"
//    ></textarea>
//    There are <input type="text" name="numchars" value="128" /> chars left
//
function textCounter (textField, countField, maxchars)
{
    var remaining = maxchars - textField.value.length;

    if (remaining < 0) {
        textField.value = textField.value.substring(0, maxchars);
        remaining = 0;
    }

    countField.value = remaining;
}

//----------------------------------------------------------

function floatboxPopupPage (page, opts)
{
    if (typeof opts == 'undefined') {
        opts = {};
    }
    if (typeof opts.showCaption == 'undefined') {
        opts.showCaption = true;
    }
    if (typeof opts.width == 'undefined') {
        opts.width = 480;
    }
    if (typeof opts.height == 'undefined') {
        opts.width = 360;
    }

    var fbOptsString = getGenericFloatboxOptions(opts);

    fbOptsString = decode_html_entities(fbOptsString);    // for caption

    fb.start(
        {
         href: ALBase.make_uri('/' + page) + '?popup=1',
         rev:  fbOptsString
        }
    );

    return;
}

function floatboxPopupLink (url, title, opts)
{
    var fbopts = getGenericFloatboxOptions(opts);

    return '<a href="' + url + '"'
         + ' class="floatbox"'
         + ' onclick="fb.start(this); return false"'
         + ' oncontextmenu="return false"'
         + ' data-fb-options="' + fbopts + '">' + title + '</a>';
}

function getGenericFloatboxOptions (opts)
{
    if (typeof opts == 'undefined') {
        opts = {};
    }

    if (typeof opts.loadPageOnClose == 'undefined') {
        opts.loadPageOnClose = false;
    }
    if (typeof opts.sameBox == 'undefined') {
        opts.sameBox = false;
    }
    if (typeof opts.scrolling == 'undefined') {
        opts.scrolling = 'auto';
    }

    if (typeof opts.width == 'undefined') {
        opts.width = 650;
    }
    if (typeof opts.height == 'undefined') {
        opts.height = 350;
    }

    if (typeof opts.showCaption == 'undefined') {
        opts.showCaption = false;
    }
    if (typeof opts.caption == 'undefined' && opts.showCaption == true) {
        var now = new Date();
        var year = now.getFullYear();
        opts.caption = '`&copy; Copyright ' + year
                     + ' Atomic Learning, Inc. &nbsp; All rights reserved.`';
    }

    if (browserIsFirefox) {
        var beforeBoxStart = 'fixFirefoxBrowserHistoryCheckPageLoad(this)';
        var beforeBoxEnd   = 'fixFirefoxBrowserHistoryCheckContentType(this)';
        var afterBoxEnd    = 'fixFirefoxBrowserHistory(this)';
        if (opts.beforeBoxStart) {
            opts.beforeBoxStart = opts.beforeBoxStart.replace(/`$/, '');
            opts.beforeBoxStart += beforeBoxStart + '`';
        }
        else {
            opts.beforeBoxStart = '`' + beforeBoxStart + '`';
        }
        if (opts.beforeBoxEnd) {
            opts.beforeBoxEnd = opts.beforeBoxEnd.replace(/`$/, '');
            opts.beforeBoxEnd += beforeBoxEnd + '`';
        }
        else {
            opts.beforeBoxEnd = '`' + beforeBoxEnd + '`';
        }
        if (opts.afterBoxEnd) {
            opts.afterBoxEnd = opts.afterBoxEnd.replace(/`$/, '');
            opts.afterBoxEnd += afterBoxEnd + '`';
        }
        else {
            opts.afterBoxEnd = '`' + afterBoxEnd + '`';
        }
    }
    
    var optsParts = new Array();
    for (var part in opts) {
        optsParts.push(part + ':' + opts[part]);
    }

    var optsString = optsParts.join(' ');

    optsString += ''
         + ' disableScroll:true'        // fb stays put if window scrolls
         + ' shadowType:drop'           // shadow on bottom and right
         + ' padding:10'                // padding around content
         + ' panelPadding:4'            // padding above/below "close"
         + ' innerBorder:0'             // pixel width of inner border
         + ' controlPos:tr'             // position of controls (e.g. close)
         + ' infoPos:bc'                // position of info (e.g. caption)
         + ' resizeDuration:0.5'        // time to expand/collapse (0-10)
         + ' overlayFadeDuration:0'     // time to fade page background (0-10)
         + ' navType:none'              // no prev/next options
         + ' hideFlash:false'           // do not hide flash when box opens
         + '';

    return optsString;
}

//----------------------------------------------------------

function startProgressMask (opts)
{
    var message  = opts.message  || 'Loading...';

    var checkURL = opts.checkURL || ALBase.make_uri('/getProgressMaskStatus');

    var checkInterval = opts.checkInterval || 1;    // in seconds

    var maskedElement = opts.maskElementId ? Ext.get(opts.maskElementId)
                                           : Ext.getBody();

    var successCallback = opts.successCallback || false;
    var failureCallback = opts.failureCallback || false;

    // Not too worried if this fails - just attempting to keep
    // the message on the server in sync with what's on screen:
    //
    var params = {message: message};
    if (opts.initialExpireSeconds) {
        params.expire_seconds = opts.initialExpireSeconds;
    }
    makeAjaxRequest({
                     url:          '/setProgressMaskStatus',
                     parameters:   params,
                     onSuccess:    function () {},
                     onNotSuccess: function () {},
                     onFailure:    function () {}
                    });

    maskedElement.mask(message);

    var myDummyElement = document.createElement('div');
    var updater = Ext.get(myDummyElement).getUpdater();

    var stopFunction = function () {
        maskedElement.unmask();
        updater.stopAutoRefresh();
    };

    updater.startAutoRefresh(checkInterval, checkURL);

    updater.on('update', function () {

        newMessage = myDummyElement.innerHTML;

        if (!newMessage || newMessage == 'CLOSE') {
            stopFunction();
            if (successCallback) successCallback();
            return;
        }

        if (newMessage != 'KEEP') {
            maskedElement.mask(newMessage);
        }
    });

    updater.on('failure', function () {
        stopFunction();
        if (failureCallback) failureCallback();
    });

}

//----------------------------------------------------------

function getTextForSelectedOption (select)
{
    var i = select.selectedIndex;
    if (i < 0) return '';
    return select.options[i].text;
}

function decode_html_entities (str)
{
  var myTextarea = document.createElement('textarea');

  myTextarea.innerHTML = str.replace(/</g, '&lt;').replace(/>/g, '&gt;');

  return myTextarea.value;
}

