//                       -*- mode: javascript -*-
//
// Author: Accenture 2009
//         All Rights Reserved.
//
// License: You may use and extend this library in accordance
//          with the terms of your ADO(TM) license.
//

if (!window.XOS) {              // FIXME: can we remove "window"?
  window.XOS = {};
  window.ADO = window.XOS;      // The "Grand Rebranding (TM)"
 }

(function () {

  var publicInterfaces = {};
  var QueryArray = null;
  var SCRIPT_PATH = null;
  var atLeastOneScriptReturned = false;
  var includeScriptsArgs = [];
  var contentInstructionThunks = [];
  var stoppedReason = null;

  var onloadHasRun = false;
  var cleanupHasRun = false;
  var contentHasRun = false;
  var cleanupThunks = [];
  var gotoLocation;

  /* constants */
  var xosTestCookie = "__ADO_TEST_COOKIE__";
  var xosCookieArg = "__ADO_COOKIE__=";
  var xosAllocatePArg = "__ALLOCATE_P__=T";
  var xosStoppedArg = "?ADO-STOPPED-P=T&ADO-STOPPED-REASON=";
  var changeLocationFired = "ADO-CHANGE-LOCATION-ACTION-FIRED";

  function cancelEvent(event) {
    event = event || window.event;
    // cater for IE
    event.cancelBubble=true;
    // Firefox
    if (event.stopPropagation) { event.stopPropagation(); }
  }

  function preventDefault(event) {
    event = event || window.event;
    if (event.preventDefault) {
      event.preventDefault();
    }
    else {
      event.returnValue = false;
    }
  }

  function createElement(tagName, attributes) {
    var element = document.createElement(tagName);
    for (var key in attributes) {
      element.setAttribute(key, attributes[key]);
    }
    return element;
  }

  function intersection(l1, l2) {
    var test = {};
    var result = [];
    var idx, key;

    for (idx = 0; idx < l1.length; idx += 1) {
      test[l1[idx]] = 1;
    }

    for (idx = 0; idx < l2.length; idx += 1) {
      if (test[l2[idx]]) {
        test[l2[idx]] = 2;
      }
    }

    for (key in test) {
      if (test[key] == 2) {
        result.push(key);
      }
    }
    return result;
  }

  function permutationP(a, b) {
    return (intersection(a, b).length == a.length) && (a.length == b.length);
  }

  //  An extremely simple map, treats each entry in the list as a
  //  arguments to the function.
  //
  //  Example Usage: mapApply( function( p ){ return p + 2; }, [1, 2, 3] );
  function mapApply(fn, list) {
    var result = [];
    var args   = null;
    for (var idx = 0; idx < list.length; idx++) {
      args = list[idx];

      //  If the args are already a list, assume that the caller knows
      //  what they are doing and wants these passed as arguments to the
      //  function.  However as a convenience if we only have a single
      //  argument for each call just wrap it in a list to stop JS from
      //  complaining.  We do this instead of just calling fn( args ) as
      //  we want to explicitly make this == null to avoid any crazy JS
      //  this wrangling and hence unexpected behaviour.
      if ((typeof(args)        == 'string') ||
          (typeof(args.length) != 'number')) {
        args = [args];
      }
      result.push( fn.apply( null, args ) );
    }
    return result;
  }

  //  The JS execution model means that each script is executed before
  //  the next one (if any) is loaded, this means that at the time the
  //  following bit of JS runs this script (ie, asp-toolkit.js) will be
  //  the last <script> element in the header.
  //
  //  We use this to remember the location of this script so we can
  //  dynamically add other scripts that are in the same location.

  function setupGlobalScriptPath() {
    var scripts = document.getElementsByTagName( "script" );
    if (scripts.length === 0) {
      throw new Error( "Failed to find the current script element." );
    }
    else {
      SCRIPT_PATH = scripts[scripts.length - 1].src;
      var pos         = SCRIPT_PATH.lastIndexOf( "/" );
      SCRIPT_PATH = (pos == -1) ? "" : SCRIPT_PATH.substring(0, pos + 1);
    }
  }

  function reallyIncludeScript( name, relative /*optional: defaults to false*/ ) {
    //  Can optionally load javascript relative to the location of this script.
    var url = relative ? SCRIPT_PATH + name : name;

    var result = document.createElement( "script" );
    result.setAttribute( "src", url );

    document.getElementsByTagName( "HEAD" )[0].appendChild( result );
    return result;
  }

  function includeScript( name, relative ) {

    if (atLeastOneScriptReturned) {
      reallyIncludeScript( name, relative );
      return;
    }

    includeScriptsArgs.push( [name, relative] );
    if (includeScriptsArgs.length == 1) {
      reallyIncludeScript( name, relative );
    }
  }

  function studlify( name ) {
    var components = name.toLowerCase().split('-');
    var result = components[0];
    var component;
    for (var i = 1; i < components.length; i++) {
      component = components[i];
      result += component.charAt(0).toUpperCase() + component.substring(1);
    }
    return result;
  }

  function cookieWorksP () {
    document.cookie = xosTestCookie + "=" + xosTestCookie;
    if (XOS.getCookie(xosTestCookie)) {
      return true;
    }
    else {
      return false;
    }
  }

  validXPathExpressionP = function( xpath ) {
    try {
      document.createExpression( xpath, null );
      return true;
    }
    /* squelch */
    catch (e) { }
    return false;
  };

  /* Undocumented, but exposed internals */

  publicInterfaces.runContentInstructionThunks = function() {
    if (onloadHasRun) return;
    onloadHasRun = true;

    if (cleanupHasRun) { return false; }

    for (var idx = 0; idx < contentInstructionThunks.length; idx++) {
      contentHasRun = true;
      XOS.runSafely( contentInstructionThunks[idx] );
    }
  }

  publicInterfaces.log = function () {
    if (window.console) {
      console.log.apply(console,arguments);
    }
  };

  publicInterfaces.stopEvent = function(event) {
    cancelEvent(event);
    preventDefault(event);
  };

  publicInterfaces.hasTagName = function( node, tagName ) {
    if (node && node.tagName) {
      return node.tagName.toLowerCase() == tagName.toLowerCase();
    }
    return false;
  };

  publicInterfaces.releaseAllScripts = function(xosCookie) {
    if (xosCookie) {
      document.cookie = xosCookie;
    }

    if (cleanupHasRun) { return; }

    atLeastOneScriptReturned = true;

    var scriptsToRelease = includeScriptsArgs.slice(1);

    includeScriptsArgs = [];

    mapApply( reallyIncludeScript, scriptsToRelease );
  };

  publicInterfaces.getCookie = function(name) {
    var documentCookie = document.cookie;

    if (!documentCookie) {
      return null;
    }

    var cookieArray = documentCookie.split(';');
    var target = name + '=';

    for (var i = 0; i < cookieArray.length; i++) {
      var cookieStr = cookieArray[i].replace(/^\s+|\s+$/g, '');
      var start = cookieStr.indexOf(target);
      if (start == 0) {
        return cookieStr.substring(target.length);
      }
    }
    return null;
  };

  publicInterfaces.getCookieValue = function( name, defaultVal ) {
    return XOS.getCookie( name ) || defaultVal;
  };

  publicInterfaces.makeVisible = function( element ) {
    element = XOS.getElement( element );
    element.style.visibility = "visible";
  };

  publicInterfaces.makeVisibleWhenElementLoaded = function( element ) {
    // NOTE: This function will work as expected for element that fire
    // an onload event, such as images, iframes, etc.
    XOS.addEvent(element, "load", function () { XOS.makeVisible( element ); } );
  };

  publicInterfaces.registerContentThunk = function( thunk ) {
    if (cleanupHasRun) { return false; }

    if (onloadHasRun) {
      contentHasRun = true;
      XOS.runSafely( thunk );
    }
    else {
      contentInstructionThunks.push( thunk );
    }
  };

  publicInterfaces.makeVisibleWhenBodyLoaded = function( element ) {
    XOS.registerContentThunk( function () {
        XOS.makeVisible( element );
      } );
  };


  publicInterfaces.changeDocumentLocationHrefSafely = function( href ) {
    var delimeter;

    if (! XOS.getQueryStringValue( changeLocationFired )) {
      delimeter = href.search("\\?") > 0 ? "&" : "?";

      if (document.location.search) {
        href = href + delimeter + document.location.search.substring(1);
        delimeter = "&";
      }

      document.location.href = href + delimeter + changeLocationFired + "=T";
    }
  };

  publicInterfaces.stop = function(reason) {
    if (!XOS.stoppedP) {
      XOS.stoppedP      = true;
      stoppedReason = reason;
    }
  };

  publicInterfaces.registerCleanupThunk = function( thunk ) {
    if (contentHasRun) { return false; }

    if (cleanupHasRun) {
      XOS.runSafely( thunk );
    }
    else {
      cleanupThunks.push( thunk );
    }
  };

  publicInterfaces.runCleanupThunks = function() {
    if (contentHasRun) { return false; }
    XOS.doDefaults();
  };

  publicInterfaces.doDefaults = function() {
    if (cleanupHasRun) { return false; }
    cleanupHasRun = true;
    for (var idx = 0; idx < cleanupThunks.length; idx++) {
      XOS.runSafely( cleanupThunks[idx] );
    }
  };

  publicInterfaces.runSafely = function( thunk ) {
    try {
      return thunk.apply( null, [] );
    }
    //  ignore any errors
    catch (e) { }
  };

  publicInterfaces.setStyle = function( elem, style ) {
    // opacity not treated handled gracefully at this point.
    // opacity for IE requires alpha:filter, etc.
    for (var name in style) {
      if (style.hasOwnProperty(name)) {
        elem.style[studlify(name)] = style[name] || "";
      }
    }
  };

  publicInterfaces.setRawCss = function( elem, css ) {
    if (css) { 
      if (elem.style.cssText) {
        elem.style.cssText += ";"+css; 
      } else {
        elem.style.cssText = css; 
      }
    }
  };

  publicInterfaces.addStylesheet = function( contents, elementId /*optional*/ ) {
    var style = document.createElement("style");
    style.setAttribute("type", "text/css");
    if (elementId) {
      style.setAttribute("id", elementId);
    }

    // IE
    if(style.styleSheet){
      style.styleSheet.cssText = contents;
    }
    //..w3c
    else {
      style.appendChild(document.createTextNode(contents));
    }

    //  Finally add it into the head of the document
    var head = document.getElementsByTagName("head").item(0);
    head.appendChild( style );
  };

  publicInterfaces.maybeGotoStoredLocation = function () {
    if (gotoLocation !== undefined) {
      document.location.href = gotoLocation;
    }
  };

  publicInterfaces.encodeRecipes = function (recipe) {
    var results = [];
    for (key in recipe) {
      results.push([key, "" + XOS.runSafely(recipe[key])]);
    }
    return encodeURIComponent(JSON.stringify(results));
  };

  publicInterfaces.storeData = function (storageUrl, queryStringMaker, xosCookieName) {
    /* Running segmentPartsMaker or outcomePartsMaker returns json stringified array like "[[n1 v1] [n2 v2]]" */
    var xosCookie = xosCookieName ? XOS.getCookie(xosCookieName) : null;
    var cookieOkP = cookieWorksP();
    var allocateP = (xosCookie || cookieOkP);
    var args = queryStringMaker(); /* All the data captures, then tack on our "control" bits. */
    var result = (args || allocateP) ? storageUrl + "?" : storageUrl;

    /* All the unknown URI components must be wrapped with encodeURIComponent */

    if (xosCookie) {
      if (args !== "") {
        args = args + "&";
      }
      args = args + xosCookieArg + encodeURIComponent(xosCookieName + "=" + xosCookie);
    }

    if (allocateP) {
      if (args !== "") {
        args = args + "&";
      }
      args = args + xosAllocatePArg;
    }
    includeScript(result + args, true);
  };

  publicInterfaces.storeStopped = function( storageUrl ) {
    includeScript(storageUrl + xosStoppedArg + encodeURIComponent(stoppedReason),
                      true);
  };

  publicInterfaces.findClickCaptureHref = function (elem) {
    //  Find the first available href attribute either on the elem or
    //  on a parent.  NOTE: this function does not care what type of
    //  elem it is given so a DIV with an href will work just as well
    //  as an anchor with an href.
    var attr = null;
    while(elem) {
      //  We want a rigorous test for the existence of the attribute
      //  node called 'href', if we use elem.href then in IE6,7 for
      //  IMG elements we get the value of the SRC attribute returned.
      attr = elem.attributes.getNamedItem('href');
      if (attr) { return attr.value; }
      elem = elem.parentNode;
    }
    return null;
  };

  publicInterfaces.captureClick = function (storageUrl, location, queryStringMaker, xosCookieName) {
    //  Goto the specified location and back to the current location
    //  in the case where we dont have a location, we should _always_
    //  have a location so this just caters for very peculiar corner
    //  cases and ensures we don't let a user see a 404.
    gotoLocation = location;
    setTimeout( function() { document.location.href = location; }, 4000 );
    XOS.storeData(storageUrl, queryStringMaker, xosCookieName);
  };

  /* Documented public interfaces */
  /* FIXME: Revise documentation */
  publicInterfaces.addEvent = function(o,e,f) {
    if (o.addEventListener){
      //  The third parameter below indicates whether the event
      //  should be handled during the event capturing phase or the
      //  event bubble phase.  The generally recommended is to use
      //  bubbling in order mimic IE's behaviour which is what we do
      //  below.  NOTE: that for historical reasons we used to do the
      //  opposite but have since discovered that this caused some
      //  subtle inconsistencies between browsers.
      o.addEventListener(e,f,false); return true;
    }
    else if (o.attachEvent){ return o.attachEvent("on"+e,f); }
    else { return false; }
  };

  publicInterfaces.isNullOrUndefined = function( thing ) {
    return (thing === null) || (thing === undefined);
  };

  publicInterfaces.hasProperties = function( obj ) {
    for (var key in obj) {
      if (Object.hasOwnProperty.call(obj, key)) {
        return true;
      }
    }
    return false;
  };

  publicInterfaces.getElement = function( elementOrId ) {
    return (typeof(elementOrId) == "string") ? document.getElementById( elementOrId ) : elementOrId;
  };

  publicInterfaces.getQueryStringValue = function( val, defaultVal ) {
    if (QueryArray === null) {
      QueryArray = [];
      var pos = null;
      // Use decodeURIComponent instead of decodeURI or unescape
      var pairs = decodeURIComponent(window.location.search.substring(1)).split('&');
      for (var i = 0; i < pairs.length; i++) {
        pos = pairs[i].indexOf('=');
        if (pos > 0) {
          QueryArray[pairs[i].substring(0,pos)] = pairs[i].substring(pos+1);
        }
      }
    }
    return (QueryArray[val] || defaultVal);
  };

  publicInterfaces.getDomNodeContent = function(domId, defaultValue) {
    var element = XOS.getElement( domId );
    if (element) {
      var tag = element.tagName.toUpperCase();
      if (tag == 'TEXTAREA') {
        return element.value;
      }
      else if (tag == 'INPUT') {
        var type = element.type.toUpperCase();
        if ((type == 'RADIO') || (type == 'CHECKBOX')) {
          // return the value if it is checked, empty string otherwise
          return element.checked ? element.value : "";
        }
        return element.value;
      }
      return element.innerHTML;
    }
    return defaultValue;
  };

  publicInterfaces.getQueryString = function() {
    var result = document.location.search;
    return result.charAt(0) == '?' ? result.substring(1) : result;
  };

  publicInterfaces.reorderElements = function (originalOrder, newOrder) {
    if (!permutationP(originalOrder, newOrder)) {
      XOS.log(originalOrder, ' is not a permuation of ', newOrder, ', cannot reorder DOM elements.');
      return null;
    }

    var originalElement, newElement, dummy, idx;

    originalOrder = mapApply(XOS.getElement, originalOrder);
    newOrder      = mapApply(XOS.getElement, newOrder);

    for (idx = 0; idx < originalOrder.length; idx = idx + 1) {
      originalElement = originalOrder[idx];
      newElement      = newOrder[idx];
      dummy = createElement('div', { id : newElement.id });
      originalElement.parentNode.replaceChild(dummy, originalElement);
    }

    for (idx = 0; idx < newOrder.length; idx = idx + 1) {
      newElement = newOrder[idx];
      dummy = XOS.getElement(newElement.id);
      dummy.parentNode.replaceChild(newElement, dummy);
    }
  };
  publicInterfaces.getElementByXPath = function( xpath ) {
    if (validXPathExpressionP(xpath)) {
      var result = document.evaluate(xpath, document, null, 7, null);
      return result ? result.snapshotItem(0) : null;
    }
    return null;
  };

  XOS.stoppedP = false; // Public variables

  // Populate public interface functions
  for(var key in publicInterfaces) {
    if (typeof XOS[key] !== 'function') {
      XOS[key] = publicInterfaces[key];
    }
  }

  publicInterfaces = null;

  setupGlobalScriptPath();

  //  Equivalent of the onload handler for content instructions
  setTimeout( XOS.runCleanupThunks, 20000);

  //  Hook the onload to try and ensure our thunks are all run.
  if ((document.all) && (!document.opera)) {
    if ((document.documentElement.doScroll) && (window == window.top)) {
      // As long as this isn't an iFrame we can use the doScroll technique
      (function () {
        try { document.documentElement.doScroll('left'); }
        catch (e) {
          setTimeout(arguments.callee, 5);
          return;
        }
        XOS.runContentInstructionThunks();
      })();
    } else {
      // Use script=defer as a fallback
      // Do NOT change this implementation! The 'defer' attribute can NOT be set via JavaScript/DHTML methods!
      // This MUST be done using document.write only.
      document.write("<scr"+"ipt id=\"ieDOMReady\" defer src=\"//:\" onreadystatechange=\"if (this.readyState=='complete') XOS.runContentInstructionThunks();\"><\/scr"+"ipt>");
    }
  } else {
    // This should work for all non-IE (Firefox, Safari, Opera, Chrome) browsers.
    if (document.addEventListener) document.addEventListener("DOMContentLoaded",XOS.runContentInstructionThunks,false);
  }

  XOS.addEvent( window, 'load', XOS.runContentInstructionThunks );

  // FIXME: not get called??
  //  XOS.setupContentInstructionThunks = function( preThunk, contentThunks, postThunk ) {

 })();

/* JSON2 without parser */
if(!this.JSON){JSON={};}
(function(){function f(n){return n<10?'0'+n:n;}
if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return this.getUTCFullYear()+'-'+
f(this.getUTCMonth()+1)+'-'+
f(this.getUTCDate())+'T'+
f(this.getUTCHours())+':'+
f(this.getUTCMinutes())+':'+
f(this.getUTCSeconds())+'Z';};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf();};}
var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';}
function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key);}
if(typeof rep==='function'){value=rep.call(holder,key,value);}
switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';}
gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||'null';}
v=partial.length===0?'[]':gap?'[\n'+gap+
partial.join(',\n'+gap)+'\n'+
mind+']':'['+partial.join(',')+']';gap=mind;return v;}
if(rep&&typeof rep==='object'){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==='string'){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}
v=partial.length===0?'{}':gap?'{\n'+gap+partial.join(',\n'+gap)+'\n'+
mind+'}':'{'+partial.join(',')+'}';gap=mind;return v;}}
if(typeof JSON.stringify!=='function'){JSON.stringify=function(value,replacer,space){var i;gap='';indent='';if(typeof space==='number'){for(i=0;i<space;i+=1){indent+=' ';}}else if(typeof space==='string'){indent=space;}
rep=replacer;if(replacer&&typeof replacer!=='function'&&(typeof replacer!=='object'||typeof replacer.length!=='number')){throw new Error('JSON.stringify');}
return str('',{'':value});};}})();
XOS.registerContentThunk(function () {
    function qsThunks() {
        var facts = {  };
        var chars = { 'brandedPPCOutcomePgTtl' : function(){
try{
	var _tmpNodeArray = null;
	var _tmpText = "unknown";
	_tmpNodeArray = document.getElementsByTagName("title");
	if(_tmpNodeArray)
	_tmpText = _tmpNodeArray[0].innerHTML;
	if (_tmpText!="unknown")
	{
		if (_tmpText.indexOf("Car breakdown cover in the UK by RAC")>-1)
			_tmpText = "REACHED_UK_BREAKDOWN_LP";
		else if (_tmpText.indexOf("Car Insurance provided by RAC offering motor insurance quotes")>-1)
			_tmpText = "CAR_INSURANCE_LP";
		else if (_tmpText.indexOf("European breakdown cover and assistance by RAC")>-1)
			_tmpText = "EUROPEAN_BREAKDOWN_LP";
		else if (_tmpText.indexOf("Home insurance with flexible cover available from RAC")>-1)
			_tmpText = "HOME_INSURANCE_LP";
		else if (_tmpText.indexOf("Personal Injury")>-1)
			_tmpText = "LEGAL_CARE_LP";			
		else if (_tmpText.indexOf("Route Planner")>-1 && _tmpText.indexOf("European Driving Directions")>-1)
			_tmpText = "ROUTE_PLANNER_LP";
		else if (_tmpText.indexOf("Travel insurance for single and multi trip with various cover options offered by RAC")>-1)
			_tmpText = "TRAVEL_INSURANCE_LP";
		else if (_tmpText.indexOf("Car history report and vehicle data check available from RAC")>-1)
			_tmpText = "VEHICLE_CHECK_LP";
		else if (_tmpText.indexOf("RAC Route planner - your route map")>-1)
			_tmpText = "ROUTE_PLANER_DETAIL_PG";
	}
	return _tmpText;
}catch(err)
{return "error";}} };
        return '__ADO_CHARS__=' + XOS.encodeRecipes(chars) + '&' + '__ADO_FACTS__=' + XOS.encodeRecipes(facts);
    };
    XOS.storeData('../hidden-execute/' + '8333019979032464238', qsThunks, 'SESSION_INFO[RAC]');
});