/**
 * This common JavaScript library is dependent on the Prototype JavaScript Framework.
 * See: http://www.prototypejs.org/
 */

/**
 * Create the mfos namespace.
 */
var mfos = {};

/**
 * Create the OpenX output array.
 */
var OA_output = new Array();

/**
 * Add a listener to the dom:loaded or DOM Ready event. This event fires when
 * the JavaScript DOM is ready to be used. dom:loaded is a special prototype
 * event see here: http://www.prototypejs.org/api/document/observe It is cross
 * browser compatible. For compatibility sake the function name remains as
 * addOnLoadListener even though it is not technically correct.
 *
 * @param fn
 *            The function to callback when the DOM has loaded.
 */
function addOnLoadListener(fn) {
   // If the DOM is already done, then execute the function straight away.
   if (document.loaded) {
      fn();
   } else {
      document.observe("dom:loaded", fn);
   }
}

/*
 * Add a listener to the unload event.
 */
function addOnUnloadListener(fn)
{
   if (typeof window.addEventListener != 'undefined') {
      window.addEventListener('unload', fn, false);
   }
   else if (typeof document.addEventListener != 'undefined') {
      document.addEventListener('unload', fn, false);
   }
   else if (typeof window.attachEvent != 'undefined') {
      window.attachEvent('onunload', fn);
   }
   else {
      var oldfn = window.onunload;
      if (typeof window.onunload != 'function') {
         window.onunload = fn;
      }
      else {
         window.onunload = function() {
            oldfn();
            fn();
         };
      }
   }
}

/*
 * Functions to be called when an allhomes public pages DOM has been loaded.
 */
function loadHomesPublic(location) {
   searchBoxDefault();
   newMyAllhomesUserRequest();
}

/*
 * Returns a new HTTP Request for the purpose of requesting an XML document.
 */
function createXmlRequest() {
   var httpRequest;

   if (window.XMLHttpRequest) {
      // Mozilla and Safari
      httpRequest = new XMLHttpRequest();
      if (httpRequest.overrideMimeType) {
         //
         httpRequest.overrideMimeType('text/xml');
      }
   }
   else if (window.ActiveXObject) {
      // IE
      try {
         httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
      }
      catch (e) {
         try {
            httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
         }
         catch (e) {}
      }
   }
   return httpRequest;
}

// http://support.internetconnection.net/CODE_LIBRARY/Javascript_Open_Window_Script.shtml
function openCenteredWindow(mypage,w,h,myname,features) {
   if(screen.width){
      var winl = (screen.width-w)/2;
      var wint = (screen.height-h)/2;
   }else{
      winl = 0;wint =0;
   }

   if (winl < 0) winl = 0;
   if (wint < 0) wint = 0;
   var settings = 'height=' + h + ',';
   settings += 'width=' + w + ',';
   settings += 'top=' + wint + ',';
   settings += 'left=' + winl + ',';
   settings += features;
   win = window.open(mypage,myname,settings);
   win.window.focus();
}

/*
 * Send an asynchronous request for My allhomes user username.
 * The response will be an XML document containing the myallhomes user username or
 * a casual user identification number.
 */
function newMyAllhomesUserRequest() {

   new Ajax.Request('/ah/ahtwyli', {
      method: 'get',
      onSuccess: updateMyAllhomesUserDisplay
   });

}

/*
 * Callback function used to process the response of the new bannerad request.
 * It parses the XML document and inserts the myallhomes logon or casual user id xhtml.
 *
 * Only one parameter should be filled out at the same moment, either "myallhomesuser"
 * or "casualallhomesuser".
 */
function updateMyAllhomesUserDisplay(transport) {

   var userState = transport.responseJSON;

   if (userState) {

      // Update href and image source
      var mahLoginLinks = document.getElementById('mahLogin');
      var mahMainLinks = document.getElementById('mahMain');

      var isActOrNsw;
      var isUserLoggedIn;
      var localityState;

      // The user is logged in
      if (userState.myAllHomesUserEmail != null) {
         isUserLoggedIn = true;
         // Set the state that we're interested in to the My allhomes user's registered state.
         localityState = userState.stateAbbreviation;
      }      // The user is not logged in
      else {
         isUserLoggedIn = false;
         // Set the state that we're interested in to the value of the state picker drop down.
         localityState = allhomes.stateDropDown.activeState;
      }

      if (localityState != null) {
         // Convert the state abbreviation to lowercase to use in URLs
         localityState = localityState.toLowerCase();

         // Store whether the state is ACT or NSW as functionality of the My allhomes navigation links
         // is different for ACT and NSW users
         if (localityState == "act" || localityState == "nsw") {
            isActOrNsw = true;
         }
         else {
            isActOrNsw = false;
         }

         if (localityState == "tas") {
		   	  // Sub in our own ad
		   	  var mainAddDiv = document.getElementById('allhomes_oa');
		   	  mainAddDiv.innerHTML = "<img src='/tas_banner.gif' />";
         }         
      }

      // User is logged in
      if (isUserLoggedIn) {

         // Set the login links appropriately
         mahLoginLinks.innerHTML =
            '<strong>' + userState.myAllHomesUserEmail + '</strong>&nbsp;|&nbsp;' +
            '<a target="_parent" href="/ah/myallhomes/secure/welcome/view">My Account</a>&nbsp;|&nbsp;' +
            '<a target="_parent" href="/ah/myallhomes/secure/logout">Sign out</a>';

         // My allhomes users from the ACT or NSW can access the OLD EmailDirect+
         if (isActOrNsw) {
            mahMainLinks.innerHTML =
               '<ol id="myah"><li><span class="wrap">' +
               '<span class="myah_tm"><a target="_parent" href="/ah/myallhomes/secure/welcome/view"><span class="my">My&nbsp;</span><span class="all">all</span><span class="homes">homes</span></a></span>&nbsp;|&nbsp;' +
               '<a href="/ah/myallhomes/watch-list/view">Watch List</a>&nbsp;|&nbsp;' +
               '<a href="/ah/myallhomes/trip-plan/view">Trip Plan</a>&nbsp;|&nbsp;' +
               '<a href="/ah/myallhomes/secure/email-direct-plus/view">EmailDirect+</a>' +
               '</span></li></ol>';
         }
         // My allhomes users not from the ACT or NSW (TAS atm) can only access NEW EmailDirect
         else {
            mahMainLinks.innerHTML =
                '<ol id="myah"><li><span class="wrap">'+
                '<span class="myah_tm"><a target="_parent" href="/ah/myallhomes/secure/welcome/view"><span class="my">My&nbsp;</span><span class="all">all</span><span class="homes">homes</span></a></span>&nbsp;|&nbsp;' +
                '<a href="/ah/myallhomes/watch-list/view">Watch List</a>&nbsp;|&nbsp;' +
                '<a href="/ah/myallhomes/trip-plan/view">Trip Plan</a>&nbsp;|&nbsp;' +
                '<a href="/ah/myallhomes/email-direct/about.ade">EmailDirect</a>' + 
                '</span></li></ol>';
         }
      }
      // User is not logged in
      else {

         // Set the login links appropriately.
         mahLoginLinks.innerHTML =
            '<span class="myah_tm"><a target="_parent" href="/ah/myallhomes/secure/welcome/view">' +
            '<span class="my">My&nbsp;</span><span class="all">all</span><span class="homes">homes</span></a></span>&nbsp;&nbsp;' +
            '<a target="_parent" href="/ah/myallhomes/secure/welcome/view">Sign in</a>';

         // Public users from the ACT or NSW can access OLD EmailDirect
         if (isActOrNsw) {
            mahMainLinks.innerHTML =
               '<ol id="myah"><li><span class="wrap">'+
               '<a href="/ah/myallhomes/watch-list/view">Watch List</a>&nbsp;|&nbsp;' +
               '<a href="/ah/myallhomes/trip-plan/view">Trip Plan</a>&nbsp;|&nbsp;' +
               '<a href="/ah/myallhomes/email-direct/view">EmailDirect</a>' +
               '</span></li></ol>';
         }
         // Public users not from the ACT or NSW can access NEW EmailDirect
         else {
            mahMainLinks.innerHTML =
                '<ol id="myah"><li><span class="wrap">'+
                '<a href="/ah/myallhomes/watch-list/view">Watch List</a>&nbsp;|&nbsp;' +
                '<a href="/ah/myallhomes/trip-plan/view">Trip Plan</a>&nbsp;|&nbsp;' +
                '<a href="/ah/myallhomes/email-direct/about.ade">EmailDirect</a>' +
                '</span></li></ol>';
         }

      }

      document.fire("allhomes:userstatus", {isUserLoggedIn: isUserLoggedIn});
   }
}

 /**
  * Generate the State Drop Down.  It uses JSON to configure it, which is injected as a global allhomes.stateDropDown variable.
  * @return
  */
function generateStateDropDown() {
   var states = $H(allhomes.stateDropDown.otherStates);
   var curState = allhomes.stateDropDown.activeState;

   // Show the allclassifieds/capital jobs link if we are in ACT or NSW
   if (curState == 'ACT' || curState == 'NSW'){
      $('capitalJobsLink').show();
      $('allclassifiedsLink').show();
   }

   var selector = new Element('span').update('&nbsp;&nbsp;<a href="#" id="stateSelector"><u>' + curState + '</u> <small>&#9660;</small></a>&nbsp;');

   var tNav = $('tertiary_navigation');
   tNav.select('div.header_left strong')[0].insert({after: selector});

   var dropDown = new Element('div', {id: 'stateDropDown', style: 'display: none;'});

   // Create the links for the remaining states.
   states.each(function(pair) {
      var state = new Element('a', {href: pair.value}).update(pair.key);
      dropDown.insert(state);
   });

   tNav.insert(dropDown);

   var navDim = tNav.getDimensions();
   var navOff = tNav.positionedOffset();
   var offset = $('stateSelector').positionedOffset();
   $('stateDropDown').setStyle({
      left: (offset.left - 6) + 'px', // - 6 is 5px padding - 1px border
      top: (navDim.height + navOff.top - 1) + 'px'
   });
   $('stateSelector').observe('click', function(event) {
      var sdd = $('stateDropDown');

      if (sdd.visible() == false) {
         // Setup click close handler
         document.observe('click', handleSelectorClick);
         sdd.show();
      }
      else {
         sdd.hide();
      }

      // We don't want to follow the href, because it is just a toggle switch.
      Event.stop(event);
   });   
   
   // Save the current State to the Cookie.
   setStateCookie(allhomes.stateDropDown.activeState);
}

function handleSelectorClick(event) {
   $('stateDropDown').hide();
   
   // We only want to save the Cookie again if the click came from a child (which will only be an <a> tag) of the stateDropDown div.
   var element = event.findElement();
   var parentNode = element.parentNode;
   if (parentNode != undefined && parentNode.id == 'stateDropDown'){
       setStateCookie(element.innerHTML);
   }
   // Unregister the click handler as we don't need to accept clicks anymore.
   document.stopObserving('click', handleSelectorClick);
}

/**
 * Set the given State in a cookie. Which is used when there is no State in personalisation.
 */
function setStateCookie(state) {
    // Expire the cookie in 1 year.
    var days = 365;
    var today = new Date();
    var expires = days * 86400000;
    expires = ';expires=' + new Date(today.getTime() + expires);
    // Write the cookie to the browser.
    document.cookie = allhomes.stateCookieName + '=' + encodeURIComponent(state) + ';path=/' + expires;
}

/*
 * Focus event handler for the search box
 */
function searchBoxFocus() {
   var sb = document.getElementById('searchBox');
   //toggleSBSize(sb, true);
   toggleSBAutoClear(sb,true);
}

function searchBoxFocusById(id) {
   var sb = document.getElementById(id);
   toggleSBAutoClear(sb,true);
}

/*
 * Blur event handler for the search box
 */
function searchBoxBlur() {
   var sb = document.getElementById('searchBox');
   //toggleSBSize(sb, false);
   toggleSBAutoClear(sb,false);
}

function searchBoxBlurById(id) {
   var sb = document.getElementById(id);
   //toggleSBSize(sb, false);
   toggleSBAutoClear(sb,false);
}

/*
 * Change the size of the Search Box when it gets or looses focus
 */
function toggleSBSize(sb, big) {
    if (big) {
        sb.style.width = '25em';
    }
    else {
        sb.style.width = '8em';
    }
}

/*
 * Remove the default search text when the search box gets focus and
 * replace the default serach text when the search box looses focus.
 * But only if the value of the search box is empty.
 *
 * Based on http://lab.dotjay.co.uk/experiments/forms/input-placeholder-text/
 */
function toggleSBAutoClear(sb, focus) {
   sb = $(sb);
   if (focus) {
      if (sb.value == sb.title) {
         sb.value = '';
         sb.removeClassName('inputFieldEmpty');
      }
   }
   else {
      if (sb.value == '') {
         sb.value = sb.title;
         if (!sb.hasClassName('inputFieldEmpty')) {
            sb.addClassName('inputFieldEmpty');
         }
      }
   }
}

/*
 * Set the default Search Box text from the title tag if the value is empty.
 */
function searchBoxDefault() {
   var sb = $('searchBox');
   if (sb) {
      if (sb.value == '') {
         sb.value = sb.title;
         sb.addClassName('inputFieldEmpty');
      }
   }
}

/**
 * Register a region on the page where you want an OpenX ad to go.
 * This function must be called before requestOAValues otherwise the ad will not be fetched.
 *
 * @param element - The HTML Element where the ad should be placed.
 * @param zoneid - The OpenX zone id of the ad to fetch.
 */
function registerOA(element, zoneid) {
   if (typeof mfos.adRegister == "undefined") {
      mfos.adRegister = new Hash();
   }
   mfos.adRegister.set(zoneid, element);
}

/**
 * Add an ad variable context for the request.
 * This function must be called before requestOAValues otherwise the context will not
 * be included in the determinations of ad's.
 *
 * @param name - The openx variable name to include in all requests
 * @param value - The value of the variable
 */
function registerOAVariableContext(name, value) {
   if (typeof mfos.adVariableContext == "undefined") {
      mfos.adVariableContext = new Hash();
   }
   mfos.adVariableContext.set(name, value);
}

/**
 * Generate a url that will fetch ads for the given zone ids.
 * Makes use of the mfos.basURL global variable. And the list of ad context variables
 *
 * This function is based on the OpenX JavaScript in the following file:
 * /openx/www/delivery/spcjs.php?id=3
 * If OpenX undergoes major upgrades this may need to be updated.
 *
 * @param zoneidArray - An array of zone ids that ads are required for.
 * @return A url that will return the ads for the given zones in a JavaScript array.
 */
function generateOAUrl(zoneidArray) {
   var zoneids = escape(zoneidArray.join('|'));
   var proto = (("https:" == document.location.protocol) ? "https://" : "http://");
   var url = proto + mfos.baseURL + "/delivery/spc.php?zones=" + zoneids;

   // Insert the ad context
   if (typeof mfos.adVariableContext != "undefined") {
      mfos.adVariableContext.each(function(pair) {
         url += "&" + escape(pair.key) + "=" + escape(pair.value);
      });
   }

   url += "&r=" + Math.floor(Math.random() * 99999999999);
   url += (document.charset ? '&charset=' + document.charset
         : (document.characterSet ? '&charset=' + document.characterSet
               : ''));
   if (window.location)
      url += "&loc=" + escape(window.location);
   if (document.referrer)
      url += "&referer=" + escape(document.referrer);

   return url;
}

/**
 * Request all the ads that have been registered on the page from the OpenX ad server and display the ads.
 *
 * This function uses the mfos.adRegister Hash table.
 * Only ads that have been registered with registerOA will be used.
 */
function requestOAValues() {
   // Disable ads for tasmania
   if (allhomes.stateDropDown != undefined && allhomes.stateDropDown.activeState == 'TAS') {
      return false;
   }

   // Check that we have the mfos openx base url and the adRegister has something in it.
   if (!(mfos.baseURL || (mfos.adRegister && mfos.adRegister.length == 0))) {
      return false;
   }

   var zoneids = mfos.adRegister.keys();

   var url = generateOAUrl(zoneids);

   // For Safari <= 3.x compatibility
   var legacy = {
      expression: function() {
         if (OA_output.length > 0) {
            return true;
         }
         else {
            return false;
         }
      }
   };

   // Get the Ads from the OpenX Ad Server.
   loadScript(url, function() {
      // Insert the ad content into the HTML elements registered with registerOA.
      mfos.adRegister.each(function(pair) {
         $(pair.value).update(OA_output[pair.key]);
      });
   }, legacy);
}

/**
 * Refresh the OpenX banner on demand. This function allows pages to refresh the
 * banner when refreshing parts of the page via ajax like callbacks.
 *
 * @param element - The HTML Element where the ad should be placed.
 * @param zoneid - The OpenX zone id of the ad to fetch.
 */
function refreshOA(element, zoneid) {
   // Disable ads for tasmania
   if (allhomes.stateDropDown != undefined && allhomes.stateDropDown.activeState == 'TAS') {
	  return false;
   }

   // Check that we have the mfos openx base url, if not get us out of here.
   if (!(mfos.baseURL)) {
      return false;
   }

   // Get the OpenX URL for getting data from one zone, generateOAUrl expects an array which is why zoneid is surrounded in [].
   var url = generateOAUrl([zoneid]);

   // Clear out the old ad data for the given zoneid. This is required for compatibility with old Safari 3.x
   OA_output[zoneid] = null;

   // Compatibility with old Safari < 3.x
   var legacy = {
      expression: function() {
         var args = $A(arguments);
         if (OA_output[args[0]] != null) {
            return true;
         }
         else {
            return false;
         }
      }.bind(this,zoneid)
   };

   // Get the Ad from the OpenX Ad Server.
   loadScript(url, function(element, zoneid) {
      // Insert the ad content into the HTML elements registered with registerOA.
      $(element).update(OA_output[zoneid]);
   }.bind(this,element,zoneid), legacy);
}

/**
 * Update a URL's protocol with the current locations protocol.
 * This function will normally be used to change the protocol on
 * resources to match the requested location.
 *
 * @param URL to update
 * @return updated URL
 */
function updateProtocol(url) {
   var protocol=location.protocol=='https:'?'https:':'http:';
   return url.replace(/http(s){0,1}:/, protocol);
}

/**
 * Create allhomes.legacy object.
 */
var allhomes = {};
allhomes.legacy = {};
/**
 * Used for Safari < 3.x compatibility.
 * timeout: number of milliseconds because the request is discarded.
 * frequency: how often to check if the request has completed.
 */
allhomes.legacy.timeout = 10000;
allhomes.legacy.frequency = 50;

// Find the WebKit version, we need it to filter out content for old Safari < 3.x users.
if (Prototype.Browser.WebKit) {
   Prototype.Browser.WebKitVersion = 0;
   var m = navigator.userAgent.match(/AppleWebKit\/([^\s]*)/);
   if (m && m[1]) {
      Prototype.Browser.WebKitVersion = parseFloat(m[1]);
   }
}

/**
 * Load the given script via a <script> element, which allows for cross site
 * scripting.
 *
 * @param scriptSrc - The script to call.
 * @param callBack - The function to call back after the script has loaded. Optional
 * @param legacy - Object that contains options for detecting callback completion with Safari < 3.x.  Optional
 */
function loadScript(scriptSrc, callBack, legacy) {
   var n = new Element("script", {
      type :"text/javascript",
      src :scriptSrc
   });

   // Only register the callBack if a callBack function was actually provided!
   if (typeof callBack != "undefined") {
      // Now we need to handle the various browser callbacks that happen when the
      // script has loaded.

      // Internet Explorer
      if (Prototype.Browser.IE) {
         n.onreadystatechange = function() {
            var rs = this.readyState;
            if ("loaded" === rs || "complete" === rs) {
               // Stop the event firing twice.
               n.onreadystatechange = null;
               callBack();
            }
         };
      }
      // Safari and probably Google Chrome
      // Safari < 3.x won't work so we will skip them (webkit version < 420)
      else if (Prototype.Browser.WebKit) {
         var webkitVersion = Prototype.Browser.WebKitVersion;
         if (webkitVersion == 0 || webkitVersion >= 420) {
            n.addEventListener("load", function() {
               callBack();
            });
         }
         // Don't register an event for old Safari (< 3.x), use legacy detection
         else {
            if (legacy.varName || legacy.expression) {
               legacyCallBackTimer(legacy, callBack, allhomes.legacy.timeout / allhomes.legacy.frequency);
            }
         }
      }
      // Firefox, Opera and everyone else.
      else {
         n.onload = function() {
            callBack();
         };
      }
   }

   // Insert the script into the HTML HEAD.
   $$("head")[0].insert(n);
}

/**
 * A timer for use with old Safari browsers < 3.x, that looks for a variable to exist or an expression to be true.
 * Once that exists the callBack method is executed.  This method will keep trying until retries is 0.
 *
 * @param legacy - An Object that has 2 potential options: expression or varName, 'expression' contains a function
 *                that must return true or false. 'varName' contains a variable name that when it exists means
 *                that the script has completed.
 * @param callBack - The function to call back on completion of script.
 * @param retries - The number of times to retry before giving up.
 */
function legacyCallBackTimer(legacy, callBack, retries) {
   if (typeof legacy.expression != "undefined" && legacy.expression()) {
      callBack();
      return;
   }
   else if (typeof legacy.varName != "undefined" && typeof window[legacy.varName] != "undefined") {
      callBack();
      return;
   }

   if (retries > 0) {
      retries--;
      window.setTimeout(function() {
         legacyCallBackTimer(legacy, callBack, retries)
      }, allhomes.legacy.frequency);
   }
}
