function bitArray(size){
  var n = Math.ceil(size/8)
  var tempString = '';
  for (var i = 0; i < n; i++) {
    tempString += '00';
  }
  this.buffer = tempString

  this.setBit = function(offset,value){
    var hexOffset = this.buffer.length-2*Math.floor((offset)/8)-2;
    var x = parseInt(this.buffer.substring(hexOffset,hexOffset+2),16);
    var y;
    var newHex;
    if (value == 0) {
      y = 1 << ((offset)%8);
      y = ~y;
      newHex = (x & y).toString(16);
    } else {
      y = 1 << ((offset)%8);
      newHex = (x | y).toString(16);
    }
    newHex =  ('0' + newHex).substring(('0' + newHex).length,('0' + newHex).length-2);
    this.buffer = this.buffer.substring(0,hexOffset) + newHex + this.buffer.substring(hexOffset+2,this.buffer.length);
  }
  this.getBit = function(offset){
    var hexOffset = this.buffer.length-2*Math.floor((offset)/8)-2;
    var x = parseInt(this.buffer.substring(hexOffset,hexOffset+2),16);
    var y = 1 << ((offset)%8);
    if (y & x) {
      return 1;
    }
    return 0;
  }
}

function bloomFilter(m, k) {
    this.k = k;
    this.m = m;
    this.hexStrBuffer = new bitArray(m);

    this.add = function(v) {
        var k = this.k;
        var m = this.m;
        var a = fnv_1a(v);
        var b = fnv_1a_b(a);
        var x = a % m;
        var i = -1;
        while (++i < k) {
          var bit = x < 0 ? (x + m) : x;
          this.hexStrBuffer.setBit(bit,1)
          x = (x + b) % m;
        }
    }

    this.test = function(v) {
        var k = this.k;
        var m = this.m;
        var a = fnv_1a(v);
        var b = fnv_1a_b(a);
        var x = a % m;
        var i = -1;
        while (++i < k) {
          var bit = x < 0 ? (x + m) : x;
          if (this.hexStrBuffer.getBit(bit) === 0) {
            return false;
          }
        x = (x + b) % m;
        }
      return true;
    }

    this.serialize = function() {
      return this.m + ':' + this.k + ':' + this.hexStrBuffer.buffer;
    }

    this.deserialize = function(str) {
      var strArr = str.split(':');
      if (strArr.length == 3) {
        this.m = parseInt(strArr[0]);
        this.k = parseInt(strArr[1]);
        this.hexStrBuffer.buffer = strArr[2];
      }
    }

}


function fnv_1a(v) {
  var n = v.length,
      a = 2166136261,
      c,
      d,
      i = -1;
  while (++i < n) {
    c = v.charCodeAt(i);
    if (d = c & 0xff000000) {
      a ^= d >> 24;
      a += (a << 1) + (a << 4) + (a << 7) + (a << 8) + (a << 24);
    }
    if (d = c & 0xff0000) {
      a ^= d >> 16;
      a += (a << 1) + (a << 4) + (a << 7) + (a << 8) + (a << 24);
    }
    if (d = c & 0xff00) {
      a ^= d >> 8;
      a += (a << 1) + (a << 4) + (a << 7) + (a << 8) + (a << 24);
    }
    a ^= c & 0xff;
    a += (a << 1) + (a << 4) + (a << 7) + (a << 8) + (a << 24);
  }
  // From http://home.comcast.net/~bretm/hash/6.html
  a += a << 13;
  a ^= a >> 7;
  a += a << 3;
  a ^= a >> 17;
  a += a << 5;
  return a & 0xffffffff;
}

// One additional iteration of FNV, given a hash.
function fnv_1a_b(a) {
  a += (a << 1) + (a << 4) + (a << 7) + (a << 8) + (a << 24);
  a += a << 13;
  a ^= a >> 7;
  a += a << 3;
  a ^= a >> 17;
  a += a << 5;
  return a & 0xffffffff;
}

function setCookie(c_name,value,exdays)
{
var exdate=new Date();
exdate.setDate(exdate.getDate() + exdays);
var c_value=escape(value) + '; path=/' + ((exdays==null) ? '' : '; expires='+exdate.toUTCString());
document.cookie=c_name + '=' + c_value;
}

function getCookie(c_name)
{
var i,x,y,ARRcookies=document.cookie.split(';');
for (i=0;i<ARRcookies.length;i++)
{
  x=ARRcookies[i].substr(0,ARRcookies[i].indexOf('='));
  y=ARRcookies[i].substr(ARRcookies[i].indexOf('=')+1);
  x=x.replace(/^\s+|\s+$/g,'');
  if (x==c_name)
    {
    return unescape(y);
    }
  }
}

var bloom = new bloomFilter(256,3);
var buffer=getCookie('bfTrckCK');
if (buffer!=null && buffer!='')
{
  bloom.deserialize(buffer);
}


function triggerTrack() {
  var href = document.location.href;
  href = href.substring(0,((href.indexOf('?')==-1) ? href.length : href.indexOf('?')));
  href = href.substring(0,((href.indexOf('#')==-1) ? href.length : href.indexOf('#')));
  var myReturn;
  if (bloom.test(href.toLowerCase())) {
    myReturn = true;
  } else {
    myReturn = false;
  }
  bloom.add(href.toLowerCase());
  setCookie('bfTrckCK',bloom.serialize(),null);

  if (Math.floor(Math.random()*100) == 1) {
      setCookie('bfTrckCK2',href,null);
  }

}

function getTrackbf() {
  return getCookie('bfTrckCK');
}

function getTrackhr() {
  return getCookie('bfTrckCK2');
}

function getTiming() {
  var timing = window.performance.timing
  var arrTiming = new Array();
  arrTiming[0] = 0;
  arrTiming[1] = timing.secureConnectionStart;
  arrTiming[2] = timing.domainLookupStart;
  arrTiming[3] = timing.domainLookupEnd;
  arrTiming[4] = timing.navigationStart;
  arrTiming[5] = timing.fetchStart;
  arrTiming[6] = timing.connectStart;
  arrTiming[7] = timing.connectEnd;
  arrTiming[8] = timing.requestStart;
  arrTiming[9] = timing.responseStart;
  arrTiming[10] = timing.responseEnd;

  var i = 0;
  var timingString = '';
  var lastTiming = 0;
  while (++i < arrTiming.length) {

    if (!isNaN(arrTiming[i])) {
      timingString += (arrTiming[i]-lastTiming).toString(10) + ':';
      lastTiming = arrTiming[i];
    } else {
      timingString += 'NAN:';
    }
  }
  return timingString;
}

function getBrowserCapabilities() {
  var strCap = '';
  var myDate = new Date();
  var strCap = strCap + ':dtlds:' + myDate.toLocaleDateString();
  var strCap = strCap +  ':scrh:' + screen.Height;
  var strCap = strCap + ':scrw:' + screen.Width;
  var strCap = strCap + ':scral:' + screen.availLeft;
  var strCap = strCap + ':scrat:' + screen.availTop;
  var strCap = strCap + ':scrah:' + screen.availHeight;
  var strCap = strCap + ':scraw:' + screen.availWidth;
  var strCap = strCap + ':scrcd:' + screen.colorDepth;
  var strCap = strCap + ':scrpd:' + screen.pixelDepth;
  var strCap = strCap + ':scrh:' + screen.height;
  var strCap = strCap + ':scrw:' + screen.width;
  var strCap = strCap + ':hstl:' + history.length;
  var strCap = strCap + ':winoh:' + window.outerHeight;
  var strCap = strCap + ':winow:' + window.outerWidth;
  var strCap = strCap + ':winih:' + window.innerHeight;
  var strCap = strCap + ':winiw:' + window.innerWidth;
  var strCap = strCap + ':winsx:' + window.screenX;
  var strCap = strCap + ':winsy:' + window.screenY;
  var strCap = strCap + ':winsx:' + window.scrollX;
  var strCap = strCap + ':winsy:' + window.scrollY;
  var strCap = strCap + ':navav:' + navigator.appVersion;
  var strCap = strCap + ':navpr:' + navigator.product;
  var strCap = strCap + ':navps:' + navigator.productSub;

  var navpln = new bloomFilter(256,4);
  var navsm = ''
  for (var i = 0; i < navigator.plugins.length; i++) {
    if (Math.floor(Math.random()*100) == 1) {
      navsm = navigator.plugins[i].name;
    }
      navpln.add(navigator.plugins[i].name)
  }

  var strCap = strCap +  ':navpln:' + navpln.serialize();
  var strCap = strCap + ':navplnsm:' + navsm;

  var navplf = new bloomFilter(256,4);
  var navsm = ''
  for (var i = 0; i < navigator.plugins.length; i++) {
    if (Math.floor(Math.random()*100) == 1) {
      navsm = navigator.plugins[i].filename;
    }
      navplf.add(navigator.plugins[i].filename)
  }

  var strCap = strCap + ':navplf:' + navplf.serialize();
  var strCap = strCap + ':navplfsm:' + navsm;

  var strCap = strCap + ':navua:' + navigator.userAgent;
  var strCap = strCap + ':navl:' + navigator.language;
  var strCap = strCap + ':navbl:' + navigator.browserLanguage;
  var strCap = strCap + ':navsl:' + navigator.systemLanguage;
  var strCap = strCap + ':navul:' + navigator.userLanguage;

  return strCap;
}

