if (!ReevooMark) {
  
var ReevooMark = {};

ReevooMark.Service = function() {
  this.uri = this.defaultRevieworldURI();
}
ReevooMark.Service.prototype = {
  updateHostName: function(hostName) {
    this.uri = this.uri.replace(/:\/\/[^\/]+\//, "://" + hostName + "/");
  },
  
  defaultRevieworldURI: function() {
    scriptTags = ReevooMark.Utils.reevooMarkScriptNodes();
    for (var i = 0; i < scriptTags.length; i ++) {
      var uriRegex = /(https?:\/\/.*?\/)/;
      var matches = uriRegex.exec(scriptTags[i].src);
      if(matches) {
        if (matches.length > 0) {
          return matches[1];
        } else {
          matches = uriRegex.exec(document.location);
          return matches[1];
        }
      }
    }
  }  
}

ReevooMark.markIndex = 0;
ReevooMark.executionIndex = 0;
ReevooMark.perMarkSettings = {};

// basic utility functions
//----------------------------------------------------------------------------/

ReevooMark.Utils = {
  unescapeHtml: function(value) {
    if(typeof value != 'string') { return value }
    var replace_regex = /&#(\d+);/g
    var replace_function = function(matched_string, character_code) {
      return String.fromCharCode(character_code);
    }
    return value.replace(replace_regex, replace_function);
  },

  isAvailable: function(value) {
    return (value !== undefined && value !== '' && typeof value != 'function');
  },

  launchPopupWindow: function(url, width, height, scroll) {
    var scrollBars = (scroll ? 'yes' : 'no')
    popupSettings = 'top=100,left=100,resizable=yes,scrollbars='+scrollBars+',menubar=no,toolbar=no,status=no,location=no';
    window.open(url,"_reviews","width="+width+",height="+height+","+popupSettings);
    this.registerClick();
  },
  
  launchLightbox: function(url, width, height) {
    try {
      RvoThickbox.show('Real world reviews', url, width, height);
      this.registerClick();
    } catch(e) {
      // fall back to the normal popup if lightbox fails
      this.launchPopupWindow(url, width, height);
    }
  },

  registerClick: function() {
    if (typeof(rvo_onclick) != 'undefined') {
      try {
         rvo_onclick();
      } catch(e) {
        // do nothing
      }
    }
  },
  
  registerLoad: function(rvmWasDisplayed) {
    if (typeof(rvo_onload) != 'undefined') {
      try {
         rvo_onload(rvmWasDisplayed);
      } catch(e) {
        // do nothing
      }
    }
  },
  
  dcsMultiTrack: function(param1_key, param1_value, param2_key, param2_value) {
    try {
      dcsMultiTrack(param1_key, param1_value, param2_key, param2_value);
    } catch(e) {
      // do nothing
    }
  },
  
  insertAfter: function(element, referenceElement) {
    var parent = referenceElement.parentNode;
    
    if(parent.lastchild == referenceElement) {
      parent.appendChild(element);
    } else {
      parent.insertBefore(element, referenceElement.nextSibling);
    }
  },
  
  insertReevooMark: function(index, element) {
    this.insertAfter(element, this.reevooMarkScriptNodes()[index]);
  },
  
  insertReevooMarkInContainer: function(index, element, containerID) {
    var container = document.getElementById(containerID);
    container.appendChild(element);
  },
  
  reevooMarkScriptNodes: function() {
    var scriptNodes = document.getElementsByTagName('script');
    var rvmScriptNodes = [];
    for (var i=0; i<scriptNodes.length; i++) { 
      if(scriptNodes[i].src.match(/(https?:\/\/)(.*)\/(reevoomark|review_mark_1|review_mark_ong).*\.js$/)) { 
        rvmScriptNodes.push(scriptNodes[i]);
      } 
    }
    return rvmScriptNodes;
  },
  
  browserDimensions: function() {
    var dimensions = new Object();
    dimensions.width = window.innerWidth || (window.document.documentElement.clientWidth || window.document.body.clientWidth);
    dimensions.height = window.innerHeight || (window.document.documentElement.clientHeight || window.document.body.clientHeight);
    return dimensions;
  },
  
  addWindowLoadEvent: function(func) {
    var oldonload = window.onload;
    if (typeof window.onload != 'function') {
      window.onload = func;
    } else {
      window.onload = function() {
        oldonload();
        func();
      }
    }
  },
  
  loadExternalScript: function(uri) {
    var head = document.getElementsByTagName("head")[0];
    var script = document.createElement('script');
    script.src = uri;
    script.type = 'text/javascript';
    head.appendChild(script);
  },
  
  loadExternalStylesheet: function(uri) {
    var head = document.getElementsByTagName("head")[0];
    var style = document.createElement('link');
    style.href = uri;
    style.rel = 'stylesheet';
    style.type = 'text/css';
    head.appendChild(style);
  },
  
  mergeObjects: function(a, b) {
    var merged = {};
    for (var i = 0, obj, key; i < arguments.length; i++) { 
      obj = arguments[i];
      for (key in obj) {
        if (typeof obj[key] != 'undefined') {
          merged[key] = obj[key]; 
        }
      }
    }
    return merged; 
  }
}

// manage the reevoomark settings: global() creates settings using embedded
// settings from the retailers page (the rvo_xxx attributes).
//----------------------------------------------------------------------------/

ReevooMark.Settings = function(settings) {
    this.format = settings['format'];
    this.retailerReference = settings['retailer_ref'];
    if(typeof settings['lightbox'] == 'undefined') {
      this.lightboxSetting = true;
    } else {
      this.lightboxSetting = settings['lightbox'];
    }
    this.unescapeValues = settings['unescape_values'];
    this.containerID = settings['container_id'];
    this.reevooMarkVersion = settings['version'];
    this.productIdentifiers = {
      'id': settings['product_id'],
      'manufacturer': settings['manufacturer'],
      'model': settings['model'],
      'sku': settings['sku']
    };
    this.locale = settings['locale'];
    this.image_title = settings['image_title'];
}
  ReevooMark.Settings.global = function(){
    return {
      'format': window.rvo_format,
      'retailer_ref': window.rvo_retailer_ref,
      'lightbox': window.rvo_lightbox,
      'unescape_values': window.rvo_unescape_values,
      'product_id': window.rvo_product_id,
      'manufacturer': window.rvo_manufacturer,
      'model': window.rvo_model,
      'sku': window.rvo_sku,
      'container_id': window.rvo_container_id,
      'version': (window.rvo_version || 2),
      'locale': (window.rvo_locale || 'en_GB')
    }
  }
  
  ReevooMark.Settings.loadExternalConfig = function() {
    label = window.rvo_label || 'default';
    externalScriptUri = ReevooMark.revieworldURI()+'reevoo_mark/settings/'+window.rvo_retailer_ref+'/'+label+'.js';
    ReevooMark.Utils.loadExternalScript(externalScriptUri)
  }
  
  ReevooMark.Settings.prototype = {
    useLightbox: function() {
      return (this.lightboxSetting == true || this.lightboxSetting == 'true');
    },
    
    container: function() {
      if(this.containerID) {
        return document.getElementById(this.containerID);
      }
      return null;
    },
    
    updateSku: function(newSku) {
      this.productIdentifiers['sku'] = newSku;
    },
    
    url: function() {
      var url = ReevooMark.revieworldURI() + this.locale + '/affiliate/reevoo_mark/' + this.retailerReference + '?' + this.paramString();
      return url + '&format=' + encodeURIComponent(this.format);
    },
    
    popupUrl: function() {
      var url = ReevooMark.revieworldURI() + this.locale + "/affiliate/reviews/" + this.retailerReference + '?' + this.paramString();
      return url + '&format=' + encodeURIComponent(this.format);
    },
    
    previewUrl: function() {
      return ReevooMark.revieworldURI() + "reevoo_mark/preview/" + this.retailerReference + '?' + this.paramString();
    },
    
    popupFunction: function() {
      var url = this.popupUrl();
      var settings = this;
      return function(){
        var reviewsDimensions = settings.reviewsDimensions();
        
        if(settings.reevooMarkVersion == 1) {
          ReevooMark.Utils.launchPopupWindow(url, reviewsDimensions.width, reviewsDimensions.height, true);
        } else {
          if(settings.useLightbox() && settings.bigEnoughForLightbox()) {
            ReevooMark.Utils.launchLightbox(url, reviewsDimensions.width, reviewsDimensions.height);
          } else {
            ReevooMark.Utils.launchPopupWindow(url, reviewsDimensions.width, reviewsDimensions.height, true);
          }
        }
        return false;
      }
    },
    
    reviewsDimensions: function() {
      if (this.reevooMarkVersion == 1) {
        return {'width':400, 'height':600};
      } else {
        return {'width':758, 'height':580};
      }
    },
    
    bigEnoughForLightbox: function() {
      var browserDimensions = ReevooMark.Utils.browserDimensions();
      var reviewsDimensions = this.reviewsDimensions();
      return (browserDimensions.width > reviewsDimensions.width && browserDimensions.height > reviewsDimensions.height);
    },
    
    shouldUnescapeValues: function() {
      return (ReevooMark.Utils.isAvailable(this.unescapeValues) && this.unescapeValues == true);
    },
    
    requestParams: function() {
      var params = new Array;
      for (var identifier in this.productIdentifiers) {
        var value = this.productIdentifiers[identifier];
        if(ReevooMark.Utils.isAvailable(value)) {
          if (this.shouldUnescapeValues()) {
            value = ReevooMark.Utils.unescapeHtml(value);
          }
          params.push(identifier + '=' + encodeURIComponent(value));
        }
      }
      params.push('version='+this.reevooMarkVersion);
      return params;
    },
    
    paramString: function() {
      return this.requestParams().join('&');
    },
    
    
    loadThickboxIfNeeded: function() {
      if(this.useLightbox()) {
        ReevooMark.Utils.loadExternalScript(ReevooMark.revieworldURI() + 'javascripts/thickbox-lite.js');
        ReevooMark.Utils.loadExternalStylesheet(ReevooMark.revieworldURI() + 'stylesheets/thickbox.css');
      }
    },
    
    loadToolTipLibrary: function() {
      ReevooMark.Utils.loadExternalScript(ReevooMark.revieworldURI() + 'javascripts/wz_tooltip.js');
    },
    
    loadRemotePreview: function() {
      ReevooMark.Utils.loadExternalScript(this.previewUrl());
    },
    
    loadLocalizedStyles: function() {
      ReevooMark.Utils.loadExternalStylesheet(ReevooMark.revieworldURI() + 'stylesheets/localized/' + this.locale + '.css');
    },
    
    // temporary fix
    setCallbackForOrange: function(popupUrl) {
      var tracked_title = 'ReevooMark clickthru for ' + window.rvo_sku;
      window.rvo_onclick = function() {
        ReevooMark.Utils.dcsMultiTrack('WT.ti', tracked_title, 'DCS.dcsuri', popupUrl);
      }
    }
}

// the reevoomark itself: brings everything together
//----------------------------------------------------------------------------/

ReevooMark.Mark = function(url, renderer, popupFunction, index) {
    this.url = url;
    this.renderer = renderer;
    this.popupFunction = popupFunction;
    this.index = index;
  }
  ReevooMark.Mark.prototype = {
    draw: function() {
      this.renderer.render(this.index, this.url, this.popupFunction);
    }
}

// individual renderer objects: image
//----------------------------------------------------------------------------/

ReevooMark.ImageRenderer = function(settings) {
    this.settings = settings;
  }
  ReevooMark.ImageRenderer.prototype = {
    render: function(index, url, popupFunction) {
      var link = this.createLink(popupFunction);
      var image = this.createImage(url);
      link.appendChild(image);
      if(this.settings.containerID) {
        ReevooMark.Utils.insertReevooMarkInContainer(index, link, this.settings.containerID);
      } else {
        ReevooMark.Utils.insertReevooMark(index, link);
      }
    },
    
    createLink: function(popupFunction) {
      var link = document.createElement('a');
      link.name = 'review_mark';
      link.href = '#';
      link.onclick = popupFunction;
      return link;
    },
    
    createImage: function(src, onloadCallbackFunction) {
      var version = this.settings.reevooMarkVersion;
      var img = document.createElement('img');
      img.alt = 'ReevooMark Image';
      img.title = this.settings.image_title || 'Click to read impartial reviews';
      img.border = '0';
      img.onload = function() {
        var rvmWasDisplayed = (img.width > 1);
        if(rvmWasDisplayed) {
          img.className = 'reevooMarkPresent'
        } else {
          img.className = 'reevooMarkAbsent'
        }
        if (typeof onloadCallbackFunction != 'undefined') {
          onloadCallbackFunction(img, rvmWasDisplayed);
        }
        ReevooMark.Utils.registerLoad(rvmWasDisplayed)
      }
      img.src = src;
      return img;
    }
}

// simple builder object, gets the correct renderer and creates the reevoomark
//----------------------------------------------------------------------------/

ReevooMark.Builder = function(settings) {
    this.settings = settings;
    this.settings.loadThickboxIfNeeded(); // need to do this here to stop firefox crashing
    this.settings.loadLocalizedStyles();
  }
  ReevooMark.Builder.prototype = {
    buildReevooMark: function(index) {
      return new ReevooMark.Mark(this.settings.url(), this.getRenderer(), this.settings.popupFunction(), index);
    },
    
    getRenderer: function() {
      var format = this.settings.format.split('_')[0];
      switch(format) {
        case 'imagescoresonly':
          return new ReevooMark.ImageRenderer(this.settings);
      }
    }
}

} // if (!ReevooMark)

ReevooMark.perMarkSettings[ReevooMark.markIndex] = ReevooMark.Settings.global();
ReevooMark.markIndex++;

ReevooMark.service = new ReevooMark.Service();
ReevooMark.revieworldURI = function() {
  return this.service.uri;
}

// create the reevoomark
//----------------------------------------------------------------------------/

if(!window.rvo_noExecute) {
  ReevooMark.Settings.loadExternalConfig();
}

ReevooMark.execute = function(serverSideSettings) {
  try {
    if(serverSideSettings['hostName']) {
      ReevooMark.service.updateHostName(serverSideSettings['hostName']);
    }      
    var mergedSettings = ReevooMark.Utils.mergeObjects(ReevooMark.perMarkSettings[ReevooMark.executionIndex], serverSideSettings);
    var reevooMark_settings = new ReevooMark.Settings(mergedSettings);
    var reevooMark = new ReevooMark.Builder(reevooMark_settings).buildReevooMark(ReevooMark.executionIndex);

    if(window.rvo_retailer_ref == 'ONG') {
      reevooMark_settings.setCallbackForOrange(reevooMark_settings.popupUrl());
      ReevooMark.Utils.addWindowLoadEvent(function(){
        reevooMark.draw();
      });
    } else {
      reevooMark.draw();
    }  
  } catch(e) {
    // Fail gracefully
  }
  ReevooMark.executionIndex++; 
}
