/**
 * Provides an abstraction layer to all sitestat measurements. Does client
 * specific preprocessing of the information so the JavaScript within the HTML
 * is minimized. For the sitestat calls it and delegates to statestat.js.
 */
var sitestatService = {

  /** The account URL, overridden during initialization. */
  accountUrl : "http://nl.sitestat.com/nn/nn/s",

  pageUrl : null,

  pageCounterName : null,

  counterSeparator : ".",

  counterPrefix : "nnpubliek",

  softclickTypeClickin : "clickin",

  softclickTypeClickout : "clickout",

  softclickTypeDownload : "pdf",

  softclickCounterNamePrefixClickin : "clickin",

  softclickCounterNamePrefixClickout : "clickout",

  softclickCounterNamePrefixDownload : "download",

  infoIconCounterNameSuffix : "info",
  
  unNamedObjectCounter : 0, 


  bindMeasurements : function(accountUrl, pageCounterName, pageUrl) {
    this.accountUrl = accountUrl;
    this.pageCounterName = pageCounterName;
    this.pageUrl = pageUrl;

    this.bindClickouts();
    this.bindDownloads();
    this.bindClickins();
    this.bindSubmits();
    this.bindInteractiveBlocks();
    this.bindLightbox();

    // Forms bindings, enable the sitestat debug mode when debug mode is on
    ns_API.forms.DEBUG = debugmodeon;
    this.bindFormInfoIcons();
  },

  /**
   * Calls the sitestat standard measurement by adding the counterName to the sitestat account.
   * @param counterName The name uniquely identifying the page measured.
   */
  measureStandard : function(counterName) {

    var sitestatUrl = this.accountUrl + "?" + counterName;

    //check for targetgroup property
    var targetgroup = $("meta[name=targetgroup]");
    if (targetgroup.length > 0) {
      sitestatUrl += "&nn_doelgroep="+targetgroup.attr("content");
    } else {
      sitestatUrl += "&nn_doelgroep=client";
    }

    //check for sslabels property
    var sslabels = $("meta[name=sslabels]");
    if (sslabels.length > 0) {
      sitestatUrl += "&"+sslabels.attr("content");
    }
    
    //add ccfid parameter
    if (this.getQueryParameter("ccfid") != "") {
      sitestatUrl += "&ccfid="+this.getQueryParameter("ccfid");
    }
    
    //add all metatags which names start with sitestat_ (and not sitestat_indirect_)
    $("meta[name^=sitestat_]:not([name^=sitestat_indirect_])").each(function() {      
      sitestatUrl += "&"+$(this).attr("name").substr(9)+"="+$(this).attr("content");  
    });

    segment = $("meta[name=nn_branche]").attr("content");
    if (segment == 'deelmijnietin') {
      segment = 'deel+mij+niet+in';
    } else if (segment == '') {
      segment = 'anonymous';
    }
    sitestatUrl += "&nn_segment="+segment;
    $.log("Measuring standard measurement for URL: " + sitestatUrl);
    return sitestat(sitestatUrl);
  },

  measureTechnical : function() {
    $.log("Measuring technical information.");
    return sitestatMeasureTechnical();
  },

  /**
   * Calls the sitestat softclick measurement.
   * @param link The link DOM object.
   * @param counterName The name uniquely identifying the page measured.
   * @param linkType The type of link (pdf, clickout, or clickin)
   */
  measureSoftclick : function(link, counterName, linkType) {
    $.log("Measuring softclick for counter with name: " + counterName);
    ns_onclick(link, '', counterName, linkType);
    return false;
  },

  /**
   * Gets all external links and binds sitestat softclicks to them.
   */
  bindClickouts : function() {

    // Get absolute URLs
    var absoluteLinks = $("a[href^='http']");
    $.log("Number of external links found to bind the softclick to: " + absoluteLinks.length);
    absoluteLinks.each(function(index) {

      var absoluteLink = $(this);
      var href = absoluteLink.attr("href");

      // Strip protocol. Remove *://
      var hrefMinusProtol = href.replace(/^.*:\/\//,'');

      // Strip querystring. Remove from start of port (:), path (/) or querystring parameter (?) to the end of the line.
      var hostName = hrefMinusProtol.replace(/[:|\/|?].*$/,'');

      // Don't add clickouts to absolute URLs to the same hostname as the page, because they are actually clickins.
      if (pageUrl.indexOf(hostName) == -1) {

        var clickoutCounterName = sitestatService.createClickoutCounterName(hostName);
        $.log("Binding clickout with counter name: " + clickoutCounterName);
        sitestatService.bindSoftclick(absoluteLink, clickoutCounterName, sitestatService.softclickTypeClickout);
      }
    });
  },

  /**
   * Binds a softclick to the link provided with the given linkType. When the link is opened in a popup, a second navigation caused by sitestat is prevented.
   */
  bindSoftclick : function(link, counterName, linkType) {

    // When the link is openened in a popup, remove the onclick function and save it to reuse it within the new click function.
    var onclickFunction = link.attr("onclick");
    var onclickFunctionString = onclickFunction ? new String(onclickFunction) : null;
    var openInPopup = onclickFunctionString != null && onclickFunctionString.indexOf(".open") > -1;
    if (openInPopup) {
      link.removeAttr("onclick", null)
      $.log("Removed click attribute for popup");
    }

    link.click(function(event) {

      /*
       * When the link is openened in a popup, execute the onclick function saved earlier.
       * Setting the target to "_" prevents the softclick to do a second navigation.
       */
      var targetWhichPreventSoftclickNavigation = "_";
      var target = link.attr("target");
      if (openInPopup) {
        onclickFunction(event);
        link.attr("target", targetWhichPreventSoftclickNavigation);
      }

      // Pass the anchor dom element to the softclick method (and not the JQuery element).
      var linkDomElement = link.context;
      sitestatService.measureSoftclick(linkDomElement, counterName, linkType);

      // After executing the softclick, either remove the temporary target, or restore the old target.
      if (openInPopup) {
        if (target) {
          link.attr("target", targetWhichPreventSoftclickNavigation);
        } else {
          link.removeAttr("target");
        }
      }
      return false;
    });

  },

  /**
   * Creates a clickout countername based on the following convention: nnpubliek.clickout.<target location>
   * The target location should only contain the target hostname with underscores instead of points (e.g. www-belastingdienst-nl)
   * @param targetLocation The location (href) of the external link
   */
  createClickoutCounterName : function(targetLocation) {
    var clickoutCounterName = this.counterPrefix;
    clickoutCounterName += this.counterSeparator;
    clickoutCounterName += this.softclickCounterNamePrefixClickout;
    clickoutCounterName += this.counterSeparator;

    // Replace all dots by underscores
    var targetLocationWithUnderscores = targetLocation.replace(/\./g,'_');
    clickoutCounterName += targetLocationWithUnderscores;
    clickoutCounterName = this.formatCounterName(clickoutCounterName);
    return clickoutCounterName;
  },

  /**
   * Gets all download links and binds sitestat softclicks to them.
   */
  bindDownloads : function() {

    // A link is a download when its href contains file?uuid
    var downloadLinks = $("a[href*='file?uuid']");
    $.log("Number of download links found to bind the softclick to: " + downloadLinks.length);
    downloadLinks.each(function(index) {
      var downloadLink = $(this);

      // For downloads WebManager sets the filename within the title.
      var title = downloadLink.attr("title");
      var extensionSeparatorIndex = title ? title.lastIndexOf(".") : -1;
      var extensionIndex = extensionSeparatorIndex + 1;

      // If the extension seperator (.) has been found and not is the first or the last character, we have both a filename and an extension.
      if (extensionSeparatorIndex > 0 && extensionIndex <= title.length) {
        var fileName = title.substr(0, extensionSeparatorIndex);
        var extension = title.substr(extensionIndex);
        var downloadCounterName = sitestatService.createDownloadCounterName(fileName, extension);

        $.log("Binding download with counter name: " + downloadCounterName);
        sitestatService.bindSoftclick(downloadLink, downloadCounterName, sitestatService.softclickTypeDownload);
      }

    });
  },

  /**
   * Creates a download countername based on the following convention: nnpubliek.download.<extension>.<filename>
   * @param fileName The filename of the download.
   * @param extension The extension of the download.
   */
  createDownloadCounterName : function(fileName, extension) {
    var clickoutCounterName = this.counterPrefix;
    clickoutCounterName += this.counterSeparator;
    clickoutCounterName += this.softclickCounterNamePrefixDownload;
    clickoutCounterName += this.counterSeparator;
    clickoutCounterName += extension;
    clickoutCounterName += this.counterSeparator;
    clickoutCounterName += fileName;
    clickoutCounterName = this.formatCounterName(clickoutCounterName);
    return clickoutCounterName;
  },

  /**
   * Gets all banners and binds sitestat softclicks to them.
   */
  bindClickins : function() {

    // Links are added A link is a download when its href contains file?uuid
    var clickinLinks = $("a[href]:not([href^='http']) img.jq_banner[alt]");
    $.log("Number of banners found to bind the softclick to: " + clickinLinks.length);
    clickinLinks.each(function(index) {

      var clickinImage = $(this);
      var clickinLinks = clickinImage.parents("a");
      clickinLink = $(clickinLinks.get(0));

      // For clickins the alternative text is part of the counterName (the uitingnaam)
      var alternativeText = clickinImage.attr("alt");
      var clickinCounterName = sitestatService.createClickinCounterName(alternativeText);
      $.log("Binding clickin with counter name: " + clickinCounterName);
      sitestatService.bindSoftclick(clickinLink, clickinCounterName, sitestatService.softclickTypeClickin);
    });
  },

  /**
   * Gets all submit buttons and binds sitestat softclicks to them.
   */
  bindAjaxLinks : function(domplace) {
    var clickinLinks;

    // Links in generated result columns
    clickinLinks = $(domplace + ' a');
    $.log("Number of result links found to bind the softclick to: " + clickinLinks.length);
    clickinLinks.each(function() {
      var thisitem = $(this);
      //alert('[GX] XANDERL DEBUG: ' + thisitem.attr('innerHTML'));
      var clickinCounterName = sitestatService.createClickinCounterName(thisitem.attr('innerHTML'));
      $(this).click(function(event) {
        sitestatService.measureSoftclick(thisitem, clickinCounterName, sitestatService.softclickTypeClickin);
      });
    });

  },

  /**
   * Gets all submit buttons and binds sitestat softclicks to them.
   */
  bindSubmits : function() {
    var clickinLinks;

    // Links are added (A:javascript)
    clickinLinks = $("form a[href^='javascript']");
    $.log("Number of submit links found to bind the softclick to: " + clickinLinks.length);
    clickinLinks.each(function() {
      var thisitem = $(this);
      var clickinCounterName = sitestatService.createClickinCounterName(thisitem.attr('innerHTML'));
      sitestatService.bindSoftclick(thisitem, clickinCounterName, sitestatService.softclickTypeClickin);
    });

    // Buttons are added (input:submit)
    clickinLinks = $("form :submit");
    $.log("Number of submitbuttons  found to bind the softclick to: " + clickinLinks.length);
    clickinLinks.each(function() {
      var thisitem = $(this);
      var clickinCounterName = sitestatService.createClickinCounterName(thisitem.attr('value'));
      $(this).click(function(event) {
        sitestatService.measureSoftclick(thisitem.context, clickinCounterName, sitestatService.softclickTypeClickin);
      });
    });

  },

  /**
   * Creates a clickin countername based on the following convention: nnpubliek.<pagepath>.<page title>.<alternative text>
   * @param alternativeText The alternative text of the image within the anchor element.
   */
  createClickinCounterName : function(alternativeText) {
    var clickinCounterName = this.pageCounterName.replace(".index", "");
    clickinCounterName += this.counterSeparator;
    clickinCounterName += this.softclickCounterNamePrefixClickin;
    clickinCounterName += this.counterSeparator;
    clickinCounterName += alternativeText;
    clickinCounterName = this.formatCounterName(clickinCounterName);
    return clickinCounterName;
  },

  /**
   * Gets all interactive blocks and bind banners and binds sitestat measurements to them.
   */
  bindInteractiveBlocks : function() {

    var interactiveBlocks = $(".flippable-component");
    $.log("Number of interactive blocks found to bind the standard measurement to: " + interactiveBlocks.length);
    interactiveBlocks.each(function(index) {

      var interactiveBlock = $(this);

      // Use the html within the part1-title span to
      var frontSideBlock = interactiveBlock.find(".component-front-side");
      var frontSideBlockName = frontSideBlock.find("#part1-title").html();
      if (!frontSideBlockName) {
        frontSideBlockName = "block";
      }
      var interactiveBlockCounterName = sitestatService.createInteractiveBlockCounterName(frontSideBlockName);
      $.log("Binding interactive block with counter name: " + interactiveBlockCounterName);

      interactiveBlock.click(function(event) {

        // The frontside block in IE does not initially have a visibility attribute, therefore check whether it's not hidden
        var frontSideBlockVisibleAttribute = $(this).find(".component-front-side").css("visibility");
        if ("hidden" != frontSideBlockVisibleAttribute) {
          sitestatService.measureStandard(interactiveBlockCounterName);
        } else {
          $.log("Not measuring because the interactive block was turned backwards.");
        }
      });

    });


    $("a[href^='#tab:']").live("mouseup", function() {
      var tab = $(this);

      // Use the linkText as tab title
      var tabTitle = tab.text();
      var tabCounterName = sitestatService.createTabCounterName(tabTitle);
      $.log("Binding tab with counter name: " + tabCounterName);

      tab.unbind("click.sitestatgx");
      tab.bind("click.sitestatgx", function(event) {
        sitestatService.measureStandard(tabCounterName);
      });
    });
  },

  /**
   * Creates an interactive block countername based on the following convention: nnpubliek.<pagepath>.<page title>.<block>.aan
   * @param block  The block uniquely identifies the interactive block.
   */
  createInteractiveBlockCounterName : function(block) {
    var interactiveBlockCounterName = this.pageCounterName.replace(".index", "");
    interactiveBlockCounterName += this.counterSeparator;
    interactiveBlockCounterName += block;
    interactiveBlockCounterName += this.counterSeparator;
    interactiveBlockCounterName += "aan";
    interactiveBlockCounterName = this.formatCounterName(interactiveBlockCounterName);
    return interactiveBlockCounterName;
  },

  /**
   * Creates an tab countername based on the following convention: nnpubliek.<pagepath>.<page title>.tab_<tabTitle>
   * @param block  The block uniquely identifies the interactive block.
   */
  createTabCounterName : function(tabTitle) {
    var tabCounterName = this.pageCounterName.replace(".index", "");
    tabCounterName += this.counterSeparator;
    tabCounterName += "tab";
    tabCounterName += "_";
    tabCounterName += tabTitle;
    tabCounterName = this.formatCounterName(tabCounterName);
    return tabCounterName;
  },

  /**
   * Gets all interactive blocks and bind banners and binds sitestat measurements to them.
   */
  bindLightbox : function() {

    var lightboxes = $('a[rel=ajax-dialog]');

    $.log("Number of lightbox links found to bind the standard measurement to: " + lightboxes.length);
    lightboxes.each(function(index) {

      var lightbox = $(this);

      var lightboxTitle = lightbox.text();

      var lightboxName = sitestatService.createLightboxCounterName(lightboxTitle);
      $.log("Binding lightbox link with counter name: " + lightboxName);

      lightbox.unbind("click.sitestatgx");
      lightbox.bind("click.sitestatgx", function(event) {
        sitestatService.measureStandard(lightboxName);
        $("body").data("activeLightBoxSiteStatCounterName",lightboxName);
        
        $("div.ajax-dialog form").die("NNAfterShowFormStep");
        $("div.ajax-dialog form").live("NNAfterShowFormStep", function (event, formStep) {
          sitestatService.measureStandard(lightboxName+"."+formStep);
        });

      });
    });
  },

  /**
   * Creates an interactive block countername based on the following convention: nnpubliek.<pagepath>.<page title>.<block>.aan
   * @param block  The block uniquely identifies the interactive block.
   */
  createLightboxCounterName : function(block) {
    var lightboxCounterName = this.pageCounterName.replace(".index", "");
    lightboxCounterName += this.counterSeparator;
    lightboxCounterName += "lightbox";
    lightboxCounterName += "_";
    lightboxCounterName += block;
    lightboxCounterName = this.formatCounterName(lightboxCounterName);
    return lightboxCounterName;
  },

  /**
   * Binds sitestat measurements to form submit and abandon events.
   */
  bindForms : function(rootElement) {    
    var forms = $(".nn_form[name]", rootElement);
    var numberOfForms = forms.length;
    $.log("Number of forms found to bind the forms measurement to: " + numberOfForms);
    if (numberOfForms > 1) {
      $.log("Multiple forms found, the sitestat form measurement will probably function incorrectly.");
    }
    forms.each(function(index) {
      var formName = $(this).attr("name");
      $.log("Binding sitestat form measurements to form with name: " + formName);

      form = new ns_API.form(formName);
      form.addSubmitEvent("*","","");
      form.addAbandonEvent("*","","");
    });
  },

  /**
   * Binds sitestat measurements to form submit and abandon events.
   */
  bindFormInfoIcons : function() {

    var infoIcons = $(".nn_form[name] div.field .information-dialog");
    $.log("Number of info icons found to bind the standard measurement to: " + infoIcons.length);

    infoIcons.each(function(index) {
      var infoIcon = $(this);
      var infoIconForm = infoIcon.parents(".nn_form[name]").get(0);
      var formName = $(infoIconForm).attr("name");

      var infoIconField = infoIcon.parents("div.field").get(0);
      var fieldName = $(infoIconField).attr("id");

      var infoIconCounterName = sitestatService.createInfoIconCounterName(formName, fieldName);
      $.log("Binding sitestat form measurements to info icon for field: " + fieldName);
      infoIcon.click(function(event) {
        sitestatService.measureStandard(infoIconCounterName);
      });

    });
  },

  /**
   * Creates an info icon countername based on the following convention: nnpubliek.<formname>.<fieldname>.info
   * @param formName The form name.
   * @param fieldName The field name uniquely identifying the info icon.
   */
  createInfoIconCounterName : function(formName, fieldName) {
    var infoIconCounterName =  this.counterPrefix;
    infoIconCounterName += this.counterSeparator;
    infoIconCounterName += formName;
    infoIconCounterName += this.counterSeparator;
    infoIconCounterName += fieldName;
    infoIconCounterName += this.counterSeparator;
    infoIconCounterName += this.infoIconCounterNameSuffix;
    infoIconCounterName = this.formatCounterName(infoIconCounterName);
    return infoIconCounterName;
  },

  /**
   * Formats the counter name so it adheres the following rules:
   * Legal characers: 0123456789 abcdfghhijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ - . _
   * Illegal characters: & = / \ < > + %2F %5C %3C %3E
   * Not guaranteed: Any remaining characters.
   *
   * The illegal characters, and the following unguaranteed characters are removed: ,!?()%:
   * @param counterName the counterName to format.
   */
  formatCounterName : function(counterName) {
    var formattedCounterName = counterName;
    formattedCounterName = formattedCounterName.replace(/(%2F|%5C|%3C|%3E)/g,'');
    formattedCounterName = formattedCounterName.replace(/[&=\/\\<>+,!?()%:]/g,'');
    formattedCounterName = formattedCounterName.replace(/\s/g,'_');
    formattedCounterName = formattedCounterName.toLowerCase();
  //a countername must never end with a dot (.) 
  if (formattedCounterName.slice(-1) == '.'){
    formattedCounterName += 'unNamedObject' + this.unNamedObjectCounter;
    this.unNamedObjectCounter++;
  }
    return formattedCounterName;
  },
  
  getQueryParameter: function( parameterName ) {
    var queryString = window.top.location.search.substring(1);
    var parameterName = parameterName + "=";
    if ( queryString.length > 0 ) {
      begin = queryString.indexOf ( parameterName );
      if ( begin != -1 ) {
        begin += parameterName.length;
        end = queryString.indexOf ( "&" , begin );
          if ( end == -1 ) {
          end = queryString.length
        }
        return unescape ( queryString.substring ( begin, end ) );
      }
    }
    return "";
}
}





