
'function'==typeof bexLoad ? bexLoad() : (function(w,doc) {
  
  w._contentExchange = w._contentExchange || {};
  var cx = w._contentExchange,
      cx_base = 'https://tracker.contentexchange.me/widget/',
      bex_base = 'https://analytics.contentexchange.me/bex/widget/',
      _callback_widgets = {},
      perf = (typeof performance !== 'undefined' && typeof performance.now === 'function') || false,
      guid = function() {return Math.random().toString(36).substr(2)},
      uuid = function uuid() {
        var d = Date.now();
        if (perf) d += performance.now();
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            var r = (d + Math.random() * 16) % 16 | 0;
            d = Math.floor(d / 16);
            return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
        });
      },
      is_frame = parent!=w,
      hasStore = (function () {try { return !!w.localStorage;} catch (e) {return false; }})(),
	    canStore = hasStore && (function(mod) {
	      try {localStorage.setItem(mod, mod);localStorage.removeItem(mod);return true;}
	      catch(e) {return false;}
	    })('modernizr'),
			statusTimer = false,
			statusTiming = [1,1,1,2,3,5,8,13,21,34], //1 2 3 5 8 13 21 34 55
			statusStep = 0,
      sendStatus = function() {
        var scrollTop = window.scrollY || document.body.scrollTop || document.documentElement.scrollTop,
            delay = statusTiming[++statusStep] || 0;
        send('status',{pv:cx.pv, scroll:scrollTop, ts: Date.now()})
        statusTimer = setTimeout(sendStatus,1000*delay)
      },
	    is_new = (function(){
	      if (w.localStorage.getItem('cx_pv')) return false;
	      return true
	    })(),
	    checkPageview = function checkPageview(cb) {
        var docref = doc.referrer || doc.referer,
            canonical_link = document.querySelector('link[rel="canonical"]'),
            canonical = canonical_link ? (canonical_link.href || canonical_link.src) : false,
            url = is_frame && docref || location.href,
            ref = is_frame ? 'iframe' : docref,
            domain = url.split('/')[2],
            now = new Date(),
            doSend = false,
            old_pv = cx.pv || canStore && localStorage.getItem('cx_pv'),
            old_url = cx.url || canStore && localStorage.getItem('cx_url');
//console.log(is_frame?'frame':'doc',old_pv,old_url,localStorage);
        cx.pv = old_pv || uuid();
        cx.url = url;
        if (canonical) cx.canonical = canonical
        if (old_pv != cx.pv) {
          cx.ref = ref;
          doSend = true;
        } else if (old_url!=url) { // check if different url
          cx.pv = uuid();
          cx.ref = old_url;
          doSend = true;
        }
        if (doSend) {
          cx.user_id = '5f8818cceac12074a718d00d';
          cx.tag = '5ef090d760a8ef46cb40bfd5';
          cx.new = is_new;
          cx.tz = now.getTimezoneOffset();
          cx.cs = doc.characterSet || doc.charset;
          if (perf) cx.ns = performance.timing.navigationStart; //request start
          cx.ts = now.getTime();
          cx.screen = [ screen.height, screen.width, screen.colorDepth ].join("x");
          //dotmetrics data + ga
          if (w.localStorage.getItem('DotMetricsDeviceId')) cx.ddev = w.localStorage.getItem('DotMetricsDeviceId');
          if (w.localStorage.getItem('DotMetricsUserId')) cx.dusr = w.localStorage.getItem('DotMetricsUserId');
          if (canStore) {
            localStorage.setItem('cx_pv',cx.pv);
            localStorage.setItem('cx_url',cx.url);
          }
          send('pageview',cx,cb);

          
          //TODO check&enable: start sending status events: ts,scrollTop,mouse position
          //statusTimer = setTimeout(sendStatus,statusTiming[++statusStep])
        } else cb()
      },
      send = function send(ev,data,cb) {
        if (0) return
        var url = 'https://collector.contentexchange.me/sl/collect?',
            qs = ['event='+ev],
            img = doc.createElement('img');
        Object.keys(data).forEach( function(k) {qs.push( k+'='+encodeURIComponent(data[k]) );} );
        url += qs.join('&');
        //console.log('sending',qs);
        img.onload = cb;
        img.setAttribute('src',url);
      },
      b64EncodeUnicode = function(str) {
          // first we use encodeURIComponent to get percent-encoded UTF-8,
          // then we convert the percent encodings into raw bytes which
          // can be fed into btoa.
          return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
              function toSolidBytes(match, p1) {
                  return String.fromCharCode('0x' + p1);
          }));
      }

  this.bexEvent = function(ev,data,cb) {
    data.event = ev
    data.pv = cx.pv
    data.ts = Date.now()
    data.customer = '5ef090d760a8ef46cb40bfd5'
    var img = doc.createElement('img'),
        payload = b64EncodeUnicode(JSON.stringify(data)),
        url = 'https://collector.contentexchange.me/sl/collect?_data='+encodeURIComponent(payload);
    img.onload = cb
    img.setAttribute('src',url)
  }

  this.display_bex = function(data) {
//console.log('bex data',data)
    if (data.error) return; // console.log(data.error)
  	var elt = _callback_widgets[data.tid],
  	    now = new Date(),
        html = data.data.replace(/\?cb[0-9]*/gi,'?pv='+cx.pv+'');
  	elt.widget.queued = false;
  	elt.widget.done = true;
  	if (html=='') return;
    switch (data.placement) {
      case 'first': elt.widget.insertAdjacentHTML('afterbegin',html); break;
      case 'last': elt.widget.insertAdjacentHTML('beforeend',html); break;
      case 'before': elt.widget.insertAdjacentHTML('beforebegin',html); break;
      case 'after': elt.widget.insertAdjacentHTML('afterend',html); break;
      case 'replace_all': elt.widget.outerHTML = html; break;
      case 'replace':
      default:
        elt.widget.innerHTML = html;
    }
    if (data.route) {
    	send('route_impression',{pv:cx.pv, customer:data.customer, campaign: data.campaign, route: data.route, segment: data.segment, docs: data.docs.join(','), ts: now.getTime()});
    } else {
    	send('widget_impression',{pv:cx.pv, widget: data.id, posts: data.posts.join(','), ts: now.getTime()});
    }
  	doc.querySelector('body').removeChild(elt.tunnel);
  }

  var show = function(widget,route) {
  //add ref to both requests, TODO - include data-cx-source!
  	tunnel = doc.createElement('script');
  	tunnel.id = guid();
  	tunnel.type = 'text/javascript';
  	var ref = cx.canonical || cx.url;
console.log('cx',cx)
  	if (route=='cx') {
		  var id = widget.getAttribute('data-trafex-widget') || widget.getAttribute('data-contentexchange-widget'),
		      cat = widget.getAttribute('data-trafex-cat') || widget.getAttribute('data-contentexchange-cat') || '',
		      cnt = widget.getAttribute('data-trafex-count') || widget.getAttribute('data-contentexchange-count') || '';
		  if (cat) cat = '/'+cat;
		  if (cnt) cnt = '/'+cnt;
      tunnel.src = cx_base+(id+'-'+tunnel.id)+cat+cnt+'?ref='+encodeURIComponent(ref);
    } else {
      tunnel.src = bex_base+route+'/'+tunnel.id + (location.search ? location.search + '&' : '?') + 'cx_id=5f8818cceac12074a718d00d&ref=' + encodeURIComponent(ref);
    }

    _callback_widgets[tunnel.id] = {
      widget : widget,
      tunnel: tunnel
    };
//console.log('dispatching',tunnel);
  	doc.querySelector('body').appendChild(tunnel);

    var refresh = 0 | ( widget.getAttribute('data-trafex-refresh') || widget.getAttribute('data-contentexchange-refresh') );
    if (refresh) (function(widget,refresh) { setTimeout(function(){show(widget,route)},Math.min(refresh,30)*1000); })(widget,refresh);
  }

  this.bexLoad = function() {
    checkPageview(function(e) {
      //nothing to do ?
    });

//    console.log('bex load') 

  localStorage._bex_data = localStorage._bex_data || '{}'
	var
		store_get = function (key) { return JSON.parse(localStorage._bex_data)[key] },
		store_set = function (key,data) {
		  var bexdata = JSON.parse(localStorage._bex_data)
		  bexdata[key] = data
		  localStorage._bex_data = JSON.stringify(bexdata)
		},
		host = function(domains) { return domains.split(/,/g).indexOf(location.host)>-1 },
		path = function(regexp) {
		  var loc = location.href.replace(location.origin,'')
//					console.log('path',loc,regexp)
			return loc.match(new RegExp(regexp))
		},
		cap = function(route,total,count,interval) {
			var cap = store_get('cap') ||  {}
			cap[route] = cap[route] || {total:0,count:0,reset:Date.now()}
			if (total>0 && cap[route].total>total) return false
			if (cap[route].count > count) return false
			if (Date.now() - cap[route].reset > interval*60000) {
				cap[route].reset = Date.now()
				cap[route].count = 0
			}
			cap[route].total += 1
			cap[route].count += 1
			store_set('cap',cap)
			return true
		},
		wait = function(route,count) {
			var wait = store_get('wait') ||  {}
			wait[route] = wait[route] || 0
			wait[route] += 1
			if (wait[route]>count) {
				wait[route] = 0
				store_set('wait',wait)
				return true
			} else {
				store_set('wait',wait)
			  return false
			}
		},
		timeOfDay = function(intervals,mode) {
        console.log('seg time',intervals)
		    var now = new Date(),
		    			day = now.getDay(),
		    			hrs = now.getHours(),
		    			idx = intervals.indexOf(day+'-'+hrs)>-1
		    return (!mode || mode=='include') ? idx : !idx
		},
		ip = function(ips,mode) {
			if (!mode) return true;
			var idx = ips.split(/,/g).indexOf('123.255.47.60')>-1;
			return mode=='include' ? !!idx : !idx
		},
		render = function(selector,routeId) { // gets things from BEX db
			var elt = document.querySelector(selector)
			if (!elt) return true;
      if (elt.done || elt.queued) return true
      elt.queued = true
			show(elt,routeId)
			return true
    },
    renderAll = function() { // gets things from CX db
  		var widgets = doc.querySelectorAll('[data-trafex-widget],[data-contentexchange-widget]');
      for (var i=0;i< widgets.length;i++) {
	      var widget =  widgets[i];
	      if (widget.queued) continue;
	      widget.queued = true;
	      var delay = 0 | ( widget.getAttribute('data-trafex-delay') || widget.getAttribute('data-contentexchange-delay') );
	      (function(widget,delay) {setTimeout(function() {show(widget,'cx');},delay*1000);})(widget,delay);
      }
			return true
		};

/* triggers -> [ [host,"host_domains,.."], [loc,"regexp for URL"], [ip,'193.2.132.77,234.1.23.45,...' ], [capp,total,count,interval], [render,'selector','route_id'], [renderAll] ]
*/

    //on DomReady run triggers
    function loadWidgets() {
			var routes = []

			for(var i=0;i<routes.length;i++) {
			  var route = routes[i];
			  for(var j=0;j<route.length;j++) {
			    var el = route[j]
			    if (!el[0].apply(this,el.slice(1))) break;
				  //if ( !el[0](...el.slice(1)) ) break;
				}
			}

		}

/*
    //run immediate triggers
		var immediate = [[[path,".*"],[ip,"31.15.169.99",""],[render,"body","5e6112eef2f66476f179b0c7"]]]
		for(var i=0;i<immediate.length;i++) {
		  var route = immediate[i];
		  for(var j=0;j<route.length;j++) {
		    var el = route[j]
		    if (!el[0].apply(this,el.slice(1))) break;
			  //if ( !el[0](...el.slice(1)) ) break;
			}
		}
*/

		// DOMContentLoaded may fire before your script has a chance to run, so check before adding a listener
		// document.addEventListener('readystatechange', function () {console.log(document.readyState)} )
		if (document.readyState === "loading") {
			  document.addEventListener("DOMContentLoaded", loadWidgets);
		} else {  // DOMContentLoaded already fired
			  loadWidgets();
		}
		
	}
	bexLoad();

})(window,document);

        	