////////////////////////////////////////////////////////////////////////////////
// Constants
////////////////////////////////////////////////////////////////////////////////

var __CFDOCUMENT_DEBUG_ON_LOAD_EVENTS = false;
var __CFDOCUMENT_DEBUG_ON_LOADED_EVENTS = false;

var CFDOCUMENT_LOAD_STATUS_PARSING = 0;
var CFDOCUMENT_LOAD_STATUS_LOADING = 1;
var CFDOCUMENT_LOAD_STATUS_LOADED = 2;
var CFDOCUMENT_LOAD_STATUS_UNLOADING = 3;
var CFDOCUMENT_LOAD_STATUS_UNLOADED = 4;

var __CFDOCUMENT_FREE_ID_CHARS = Array.fromString(String.ALPHANUMERIC);
var __CFDOCUMENT_FREE_ID_PREFIX = "cf-document-free-id-";

var __CFDOCUMENT_LOAD_STATUS_MESSAGES = new Array();
__CFDOCUMENT_LOAD_STATUS_MESSAGES[CFDOCUMENT_LOAD_STATUS_PARSING] = "parsing";
__CFDOCUMENT_LOAD_STATUS_MESSAGES[CFDOCUMENT_LOAD_STATUS_LOADING] = "loading";
__CFDOCUMENT_LOAD_STATUS_MESSAGES[CFDOCUMENT_LOAD_STATUS_LOADED] = "loaded";
__CFDOCUMENT_LOAD_STATUS_MESSAGES[CFDOCUMENT_LOAD_STATUS_UNLOADING] =
    "unloading";
__CFDOCUMENT_LOAD_STATUS_MESSAGES[CFDOCUMENT_LOAD_STATUS_UNLOADED] = "unloaded";

////////////////////////////////////////////////////////////////////////////////
// Static variables
////////////////////////////////////////////////////////////////////////////////

var __cfDocumentFreeIdSuffix = [__CFDOCUMENT_FREE_ID_CHARS[0]];
var __cfDocumentLoadStatus = CFDOCUMENT_LOAD_STATUS_PARSING;
var __cfDocumentOnLoadedHandlerSet = undefined;
var __cfDocumentOnLoadHandlerSet = undefined;
var __cfDocumentOnUnloadHandlerSet = undefined;

////////////////////////////////////////////////////////////////////////////////
// Event handlers
////////////////////////////////////////////////////////////////////////////////

function __cfDocumentHandleOnLoadEvent()
{
    __cfDocumentLoadStatus = CFDOCUMENT_LOAD_STATUS_LOADING;
    if (__cfDocumentOnLoadHandlerSet) {
        __cfDocumentOnLoadHandlerSet.execute();
    }
    __cfDocumentLoadStatus = CFDOCUMENT_LOAD_STATUS_LOADED;
    if (__cfDocumentOnLoadedHandlerSet) {
        __cfDocumentOnLoadedHandlerSet.execute();
    }
}

function __cfDocumentHandleOnUnloadEvent()
{
    __cfDocumentLoadStatus = CFDOCUMENT_LOAD_STATUS_UNLOADING;
    if (__cfDocumentOnUnloadHandlerSet) {
        __cfDocumentOnUnloadHandlerSet.execute();
    }
    __cfDocumentLoadStatus = CFDOCUMENT_LOAD_STATUS_UNLOADED;
}

////////////////////////////////////////////////////////////////////////////////
// Public API
////////////////////////////////////////////////////////////////////////////////

function cfDocumentAddOnLoadCallback()
{
    if (! __cfDocumentOnLoadHandlerSet) {
        __cfDocumentOnLoadHandlerSet =
            new CFEventHandlerSet(__CFDOCUMENT_DEBUG_ON_LOAD_EVENTS);
        if (! __cfDocumentOnLoadedHandlerSet) {
            var f = cfEventHandlerCreate(__cfDocumentHandleOnLoadEvent);
            __cfDocumentHandleOnLoadEvent = f;
        }
    }
    __cfDocumentOnLoadHandlerSet.add.apply(__cfDocumentOnLoadHandlerSet,
                                           arguments);
}

function cfDocumentAddOnLoadedCallback()
{
    if (! __cfDocumentOnLoadedHandlerSet) {
        __cfDocumentOnLoadedHandlerSet =
            new CFEventHandlerSet(__CFDOCUMENT_DEBUG_ON_LOADED_EVENTS);
        if (! __cfDocumentOnLoadHandlerSet) {
            var f = cfEventHandlerCreate(__cfDocumentHandleOnLoadEvent);
            __cfDocumentHandleOnLoadEvent = f;
        }
    }
    __cfDocumentOnLoadedHandlerSet.add.apply(__cfDocumentOnLoadedHandlerSet,
                                             arguments);
}

function cfDocumentAddOnUnloadCallback()
{
    if (! __cfDocumentOnUnloadHandlerSet) {
        __cfDocumentOnUnloadHandlerSet = new CFEventHandlerSet();
        var f = cfEventHandlerCreate(__cfDocumentHandleOnUnloadEvent);
        __cfDocumentHandleOnUnloadEvent = f;
    }
    __cfDocumentOnUnloadHandlerSet.add.apply(__cfDocumentOnUnloadHandlerSet,
                                             arguments);
}

function cfDocumentGetFreeElementId()
{
    var numChars = __CFDOCUMENT_FREE_ID_CHARS.length;
    for (;;) {
        var i;
        var testId = __CFDOCUMENT_FREE_ID_PREFIX +
                     __cfDocumentFreeIdSuffix.join('').reverse();
        for (i = 0; i < __cfDocumentFreeIdSuffix.length; i++) {
            var c = __cfDocumentFreeIdSuffix[i];
            var n = (__CFDOCUMENT_FREE_ID_CHARS.indexOf(c) + 1) % numChars;
            __cfDocumentFreeIdSuffix[i] = __CFDOCUMENT_FREE_ID_CHARS[n];
            if (n) {
                break;
            }
        }
        if (i == __cfDocumentFreeIdSuffix.length) {
            __cfDocumentFreeIdSuffix.push(__CFDOCUMENT_FREE_ID_CHARS[0]);
        }
        var element = document.getElementById(testId);
        if (! element) {
            return testId;
        }
    }
}

function cfDocumentGetLoadStatus()
{
    return __cfDocumentLoadStatus;
}

function cfDocumentGetLoadStatusMessage()
{
    return __CFDOCUMENT_LOAD_STATUS_MESSAGES[__cfDocumentLoadStatus];
}

////////////////////////////////////////////////////////////////////////////////
// Initialization
////////////////////////////////////////////////////////////////////////////////

window.onload = __cfDocumentHandleOnLoadEvent;
window.onunload = __cfDocumentHandleOnUnloadEvent;
