/* $Id: barrierLoaderDRM.js,v 1.64 2009/06/05 09:56:18 bcowgill Exp $ */
/*jslint bitwise: true, browser: true, eqeqeq: true, immed: true, newcap: true, nomen: true, regexp: true, undef: true, white: true, indent: 4 */
/*globals ActiveXObject, FT, escape, optimost, window,  HurdleType, SiTrackData, loginForgottenPassword, is */

/******************************************************************************
Javascript library file to replace content in the body of a loaded document with
content from the server using AJAX.

getDynamicData(replaceId , replaceLocation)
===========================================
getDynamicData(replaceId , replaceLocation) is the function to be invoked in the
calling page; it handles sanitizing the url and initializing the request object -
opening the url and attaching the callback function, where:
    replaceId is the id of the node whose content is to be replaced
        (note the node itself will still be present in the target document, but its
        content will be replaced with the data fetched from the server)
    replaceLocation is the location of the content it is to be replaced with.

callbackFunction()
==================
At the moment the callbackFunction only handles retrieving content as text/html, i.e as text;
all the retrieved content will be placed inside the target node as there is no safe way
of accessing any internal structure.
(text is used because the well-formedness constraint on content served as application/xml
is too strict for the content we want to send. )

Ideally the getDynamicData() function would be called on document load - it shouldn't
be called before as the dom will not be available, and should be called as soon as
possible after in case the server is slow.

emyr.tomos@ft.com
Major facelift by brent.cowgill@ft.com
*******************************************************************************/

/*members ActiveXObject, DRM, Enabled, M, Optimise, XHR, XMLHttpRequest,
    active, appendChild, callbackFunction, className, createElement,
    displayModule, evalScripts, finished, getAllResponseHeaders,
    getDynamicData, getElementById, getElementsByTagName, getHiResTime,
    getNewHTTPObject, getUTCMilliseconds, getUTCSeconds, hostname, howLong,
    href, ie, indexOf, init, initHTTPObject, innerHTML,
    isOptimisationActive, isOptimostReady, length, location, log, match,
    module, noOptimisationTestIAI, onTrialCodeLoaded, onload,
    onreadystatechange, open, opera, optimisationTestIAI, protocol,
    queryString, readyState, referer, replaceId, responseText, search, send,
    setRequestHeader, setVisibility, split, startTime, status, stopTimer,
    style, substr, text, timeoutTime, toString, trackIAI, type, url, value,
    visibility
*/
// Unknown where this is called from so not packaged into the FT.DRM namespace at this time.
function loginForgottenPassword()
{
    if (document.getElementById('username'))
    {
        var url = "https://registration.ft.com/registration/login/forgottenpassword?forgottenPasswordUsername=" + document.getElementById('username').value + "&location=" + escape(document.location);
        document.location = url;
    }
}

if (typeof FT === "undefined")
{
    // If the optimost page code is missing create a dummy object to prevent errors
    FT = { 'Optimise': { 'active': false, 'log': function (message) {} } };
}

// Store our settings / vars in an object to keep the global namespace clean.
// This is not a full-blown object, more like a structure for storing things.
FT.DRM = {
    'replaceId':      null,   // div id to replace with AJAX fetched content.
    'module':         'Main', // Optimost module code to invoke once loaded.
    'queryString':    '',     // query string from the article URL.
    'url':            '',     // URL for AJAX request.
    'XHR':            null,   // XHR object for AJAX request.
    'timeoutTime':    2000,   // Default timeout time
    'startTime':      null,   // when we started the clock
    'finished':       false,  // Flag indicates the optimost display is updated and visible.
    'howLong':        -1      // How long it took for optimost function to appear
};

// Get an XHR object in a browser compatible way
FT.DRM.getNewHTTPObject = function ()
{
    var rXHRLocal;
    try
    {
        if (window.XMLHttpRequest)
        {
            rXHRLocal = new XMLHttpRequest();
        }
        else if (window.ActiveXObject)
        {
            try
            {
                rXHRLocal = new ActiveXObject("Msxml2.XMLHTTP");
            }
            catch (err)
            {
                rXHRLocal = new ActiveXObject("Microsoft.XMLHTTP");
            }
        }
    }
    catch (err2)
    {
        rXHRLocal = false;
    }
    return rXHRLocal;
};

// Initialize XHR object so it is ready to make a request
FT.DRM.initHTTPObject = function ()
{
    if (FT.DRM.XHR)
    {
        try
        {
            if (window.XMLHttpRequest)
            {
                FT.DRM.XHR.open('GET', FT.DRM.url, true);
                FT.DRM.XHR.onreadystatechange = FT.DRM.callbackFunction;
                FT.DRM.XHR.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
                FT.DRM.XHR.send(null);
            }
            else if (window.ActiveXObject)
            {
                FT.DRM.XHR.open('GET', FT.DRM.url, true);
                FT.DRM.XHR.onreadystatechange = FT.DRM.callbackFunction;
                FT.DRM.XHR.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
                FT.DRM.XHR.send();
            }
        }
        catch (err)
        {
            FT.DRM.XHR = false;
        }
    }
};

// Perform AJAX call to get the IAI message box content and Optimost javascripts
FT.DRM.getDynamicData = function (replaceId)
{
    if (replaceId === null || replaceId === "")
    {
        return false;
    }
    FT.DRM.replaceId = replaceId;
    FT.DRM.initHTTPObject();
};

// Check if the Optimost Trial code javascript library has finished loading and
// that displayModule() is now ready to be called.
FT.DRM.isOptimostReady = function (key)
{
    if (typeof optimost !== 'undefined' && typeof optimost.M !== 'undefined' && typeof optimost.M[key] === "function" && typeof optimost.displayModule !== 'undefined')
    {
        return true;
    }
    return false;
};

// Set the visibility of the IAI message box.
// bVisible - true to make it visible
// rNode - optional element node to set visibility of.
//   if omitted it uses the ID in FT.DRM.replaceId
FT.DRM.setVisibility = function (bVisible, rNode)
{
    if (!rNode)
    {
        rNode = document.getElementById(FT.DRM.replaceId);
    }
    if (rNode)
    {
        rNode.style.visibility = bVisible ? 'visible' : 'hidden';
    }
};

// Evaluate all JavaScript elements under the freshly inserted HTML.
// Note this will leave two copies of each script tag in the DOM view
// though only one of them would actually be evaluated.
FT.DRM.evalScripts = function (rTargetNode)
{
    FT.Optimise.log("evalScripts");
    if (typeof is !== 'undefined' && is.ie) {
        FT.Optimise.log("evalScripts() - cancel because we are IE and have already run the script");
        return;
    }
    var raScripts = rTargetNode.getElementsByTagName("script");
    var num = raScripts.length;
    FT.Optimise.log("evalScripts num of scripts found " + num);
    for (var idx = 0; idx < num; idx++)
    {
        FT.Optimise.log(idx + " eval script " + raScripts[idx].text);
        try {
            eval(raScripts[idx].text);
        }
        catch (err)
        {
            FT.Optimise.log("Eval script exception: ");
            FT.Optimise.log(err);
        }
    }
};

FT.DRM.noOptimisationTestIAI = function ()
{
    FT.Optimise.log("Not applying creatives");
    FT.DRM.setVisibility(true);
};

FT.DRM.stopTimer = function (message)
{
    // Stop the interval timer
    var rDate = new Date();
    FT.DRM.howLong  = FT.DRM.getHiResTime() - FT.DRM.startTime;
    FT.Optimise.log(message + " " + FT.DRM.howLong + " ms");
};

FT.DRM.getHiResTime = function ()
{
    var rDate = new Date();
    var time = 1000 * rDate.getUTCSeconds() + rDate.getUTCMilliseconds();
    return time;
};

// Set up timers to invoke the Optimost module code so that the IAI message
// box content can be varied.
FT.DRM.optimisationTestIAI = function ()
{
    FT.Optimise.log("Applying creatives");
    // If the interval timer has not yet been set up, set one up to wait until
    // the optimost code arrives.
    FT.Optimise.log("Timeout: " + FT.DRM.timeoutTime);
    FT.DRM.finished = false;
    // Prevent the interval timer from carrying on forever if optimost doesn't seem to be there.
    FT.DRM.startTime = FT.DRM.getHiResTime();
    setTimeout(
        function ()
        {
            if (! FT.DRM.finished) {
                FT.DRM.stopTimer("optimisationTestIAI() - Timeout waiting for optimost ");
            }
            FT.DRM.finished = true;
            FT.DRM.setVisibility(true);
        }, FT.DRM.timeoutTime
    );
};

FT.DRM.onTrialCodeLoaded = function ()
{
    if (FT.DRM.finished)
    {
        FT.Optimise.log("Trial code loaded -- too late");
        return;
    }
    FT.DRM.finished = true;
    FT.DRM.stopTimer("Trial code loaded - Optimost called us at ");

    // Invoke the optimost module code and then make the message visible
    optimost.displayModule(FT.DRM.module);
    FT.DRM.setVisibility(true);
};

// Call Site Intelligence to Track the page now that the IAI content is loaded.
FT.DRM.trackIAI = function ()
{
    var rDivIAI = document.getElementById("iaiMain");
    if (rDivIAI)
    {
        var hurdleFromClassName = rDivIAI.className;
        if (hurdleFromClassName)
        {
            // HurdleType is a variable defined on the HTML page we were invoked from.
            HurdleType = rDivIAI.className;
            SiTrackData("HurdleType=" + HurdleType);
        }
    }
};

// We only turn on the optimisation if the FTQA cookie has been set
FT.DRM.isOptimisationActive = function ()
{
    // When killswitch is on, optimost.Enabled will be false.
    return (typeof optimost !== 'undefined' && optimost.Enabled);
};

// AJAX Callback function. We add the HTML to the page but hide it until we
// can get Optimost library to make changes to it.
FT.DRM.callbackFunction = function ()
{
    // Wait for AJAX to complete before we continue
    if (FT.DRM.XHR.readyState !== 4)
    {
        return;
    }
    FT.Optimise.log("AJAX complete.");
    var rTargetNode = document.getElementById(FT.DRM.replaceId);
    if (rTargetNode)
    {
        FT.DRM.setVisibility(false, rTargetNode);
        var result = FT.DRM.XHR.responseText;
        if (result === null || result === "" || FT.DRM.XHR.status !== 200)
        {
			FT.Optimise.log("FAIL Ajax: result,url,status,headers");
			FT.Optimise.log(result);
			FT.Optimise.log(FT.DRM.url);
			FT.Optimise.log(FT.DRM.XHR.status);
			FT.Optimise.log(FT.DRM.XHR.getAllResponseHeaders());					
        }
        else
        {
            rTargetNode.innerHTML = result;
            if (!FT.DRM.isOptimisationActive())
            {
                FT.DRM.noOptimisationTestIAI();
            }
            else
            {
                // Embedded script elements don't get executed and defer works on IE only
                // so we find the script elements present and add them with the DOM to force them
                FT.DRM.evalScripts(rTargetNode);
                FT.DRM.optimisationTestIAI();
            }
        }
    }

    // initiate tracking call again
    var rcCurrentOnLoad = window.onload;
    window.onload = function ()
    {
        FT.DRM.trackIAI();
        rcCurrentOnLoad();
    };
};

// Initialize AJAX and make the call to get the IAI message box content.
FT.DRM.init = function ()
{
    if (FT.Optimise.timeoutTime)
    {
        FT.DRM.timeoutTime = FT.Optimise.timeoutTime;
    }
    // Constructing the AJAX URL based on parameters in the page URL
    var serverAddress = window.location.protocol + "//" + window.location.hostname;
    var urlStem = "/regb/iab";
    var raParams = window.location.search.substr(1).split("&");
    var raQuery = [];
    for (var idx = 0; idx < raParams.length; idx++)
    {
        var raValues = raParams[idx].split("=");
        if (raValues[0].match("location"))
        {
            raQuery.location = raValues[1].toString();
        }
        else if (raValues[0].match("referer"))
        {
            var valueFromArray;
            if (raValues[2] && raValues[1].toString().indexOf('customer_id', 0) !== -1)
            {
                valueFromArray = raValues[1] + "=" + raValues[2];
            }
            else
            {
                valueFromArray = raValues[1];
            }
            raQuery.referer = valueFromArray.toString();
        }
    }
    FT.DRM.url = serverAddress + urlStem;
    if (raQuery.referer || raQuery.location)
    {
        var loopCount = 0;
        FT.DRM.queryString += "?";
        for (var key in raQuery)
        {
            if (typeof raQuery[key] === 'string')
            {
                if (loopCount > 0)
                {
                    FT.DRM.queryString += "&";
                }
                ++loopCount;
                FT.DRM.queryString += key + "=" + raQuery[key];
            }
        }
    }
    FT.DRM.url += FT.DRM.queryString;
    FT.DRM.XHR = FT.DRM.getNewHTTPObject();

    setTimeout(
        function ()
        {
            // Modify all Anchors within the IAI message box to also contain the
            // query string from the page
            var rDivIAIMain = document.getElementById("iaiMain");
            if (rDivIAIMain)
            {
                var raAnchors = rDivIAIMain.getElementsByTagName("a");
                if (raAnchors.length > 0)
                {
                    raAnchors[0].href = raAnchors[0].href + FT.DRM.queryString;
                }
            }
            FT.DRM.getDynamicData('DRMUpsell');
        }, 1
    );
};
FT.DRM.init();

