/**
 * exPostAd tracking lib IIFE
 *
 * @param {object} document - document dom object
 * @param {object} window - window dom object
 * @returns {void}
 */
'use strict';
(function exPostAd(document, window) {
  var
      // host to send the requests to
      TRACKING_URL = 'https://adsat.iocnt.net/tx.io',
      // multiplicand constant for math random
      RANDOM_MULTIPLICAND_01 = 100000,
      // multiplicand constant for math random
      RANDOM_MULTIPLICAND_02 = 1000,
      // timeout setting
      WAITING_TIMEOUT = 10000,
      // define zero value
      // slice length
      SLICE_LEN = 2048,
      ZERO = 0,
      // determine if native json support is given
      jsonSupported = (function jsSup() {
        try{
            return ({}).toString.call(JSON.parse(JSON.stringify({}))) === '[object Object]';
          } catch (e) {
            return false;
          }
      })(),
      // determine if postMessage support is given
      postMessageSupported = (function pmSup() {
        return typeof window.postMessage !== 'undefined';
      })(),
      // determine if the scripts is evaluated in top window
      isTopWindow = (window === top),
      // determine framedepth
      frameDepth = (function getDepth() {
        var fd = 0,
        frame = window;

        while (frame !== top) {
          frame = frame.parent;
          fd += 1; // eslint-disable-line no-magic-numbers
        }
        return fd;
      })(),
      referrer = (function getRf() {
        var a = document.createElement('a');

        a.href = document.referrer;
        return a.protocol + '//' + a.host;
      })(),
      iamData = (function getIamData() {
	     return (isTopWindow) ? window.iam_data : null;
      })(),
      fingerprint = (function calcFingerprint() {
        var nav = window.navigator,
        t = nav.userAgent + screen.width + 'x' + screen.height + 'x' + screen.colorDepth,
        i;

        /* eslint-disable no-magic-numbers */
        function hash(key) {
          var hash = 0,
          i;

          for (i = ZERO; i < key.length; i += 1) {
            hash += key.charCodeAt(i);
            hash += (hash << 10);
            hash ^= (hash >> 6);
          }
          hash += (hash << 3);
          hash ^= (hash >> 11);
          hash += (hash << 15);
          hash = Math.abs(hash & hash);
          return hash.toString(36);
        }

        function activeXDetect() {
          var result = '',
          componentVersion,
          components = [
                       '7790769C-0471-11D2-AF11-00C04FA35D02', '89820200-ECBD-11CF-8B85-00AA005B4340',
                       '283807B5-2C60-11D0-A31D-00AA00B92C03', '4F216970-C90C-11D1-B5C7-0000F8051515',
                       '44BBA848-CC51-11CF-AAFA-00AA00B6015C', '9381D8F2-0288-11D0-9501-00AA00B911A5',
                       '4F216970-C90C-11D1-B5C7-0000F8051515', '5A8D6EE0-3E18-11D0-821E-444553540000',
                       '89820200-ECBD-11CF-8B85-00AA005B4383', '08B0E5C0-4FCB-11CF-AAA5-00401C608555',
                       '45EA75A0-A269-11D1-B5BF-0000F8051515', 'DE5AED00-A4BF-11D1-9948-00C04F98BBC9',
                       '22D6F312-B0F6-11D0-94AB-0080C74C7E95', '44BBA842-CC51-11CF-AAFA-00AA00B6015B',
                       '3AF36230-A269-11D1-B5BF-0000F8051515', '44BBA840-CC51-11CF-AAFA-00AA00B6015C',
                       'CC2A9BA0-3BDD-11D0-821E-444553540000', '08B0E5C0-4FCB-11CF-AAA5-00401C608500',
                       'D27CDB6E-AE6D-11CF-96B8-444553540000', '2A202491-F00D-11CF-87CC-0020AFEECF20'
          ],
          i = 0;

          document.body.addBehavior( '#default#clientCaps' );
          for (i = ZERO; i < components.length; i += 1) {
            componentVersion = document.body.getComponentVersion('{' + components[i] + '}', 'ComponentID');
            if ( componentVersion === null ) {
              result += 'null';
            } else {
              result += componentVersion;
            }
          }
          return result;
        }

        if (nav.plugins.length > ZERO ) {
          for (i = ZERO; i < nav.plugins.length; i += 1 ) {
            t += nav.plugins[i].filename + nav.plugins[i].version + nav.plugins[i].description;
          }
        }

        if (nav.mimeTypes.length > ZERO ) {
          for (i = ZERO; i < nav.mimeTypes.length; i += 1 ) {
            t += nav.mimeTypes[i].type;
          }
        }

        if ( /MSIE (\d+\.\d+);/.test(nav.userAgent) ) {
          try {
            t += activeXDetect();
          } catch (e) {
            // ignore
          }
        }

        return hash(t);
      })();
  /* eslint-enable no-magic-numbers */

  /**
   * attaches eventlistener to current window
   * @param {string} eventName - event to listen
   * @param {function} callBack - function to call after event was triggered
   * @returns {void}
   */
  function addEventListener(eventName, callBack) {
    if (window.addEventListener) {
      window.addEventListener(eventName, callBack);
    } else {
      window.attachEvent('on' + eventName, callBack);
    }
  }

  /**
   * performs once campaign tracking
   * @param {object} iamTrackData - the Data
   * @param {string} supplier - the supplier's id
   * @param {string} campaign - the campaign's id
   * @param {object} data - additional data to append to the tracking url
   * @param {boolean} useHistory - identifier if the call history is used
   * @returns {void}
   */
  function track(iamTrackData, supplier, campaign, data) {
    var KEY_LEN = 8,
    dataAppendix = '',
    sin = 'noiam',
    sco = 'noiam',
    key,
    url;

    /* eslint-disable no-magic-numbers */
    for (key in data) {
      if (data.hasOwnProperty(key)) {
        dataAppendix = dataAppendix + '&' + encodeURIComponent(key).slice(0, KEY_LEN) + '=' + encodeURIComponent(data[key]).slice(0, SLICE_LEN);
      }
    }

    if (iamTrackData && iamTrackData.st && iamTrackData.cp) {
      sin = iamTrackData.st;
      sco = iamTrackData.cp;
    }

    url = TRACKING_URL
    + '?st=' + encodeURIComponent(supplier).slice(0, SLICE_LEN)
    + '&cp=' + encodeURIComponent(campaign).slice(0, SLICE_LEN)
    + '&sin=' + encodeURIComponent(sin).slice(0, SLICE_LEN)
    + '&sco=' + encodeURIComponent(sco).slice(0, SLICE_LEN)
    + '&ur=' + encodeURIComponent(document.location.host).slice(0, SLICE_LEN)
    + '&rf=' + encodeURIComponent(referrer).slice(0, SLICE_LEN)
    + '&dp=' + encodeURIComponent(frameDepth).slice(0, SLICE_LEN)
    + dataAppendix
    + '&id=' + encodeURIComponent(fingerprint).slice(0, SLICE_LEN)
    + '&mo=1'
    + '&rd=' + encodeURIComponent(Math.random() * RANDOM_MULTIPLICAND_01).slice(0, SLICE_LEN);
    /* eslint-enable no-magic-numbers */
    writeImage(url);
  }

  /**
   * requests an url via image object
   * @param {string} url - the url to request
   * @returns {void}
   */
  function writeImage(url) {
    (new Image()).src = url;
  }

  /**
   * searches array for a given object
   * @param {mixed} needle - the object to search for
   * @param {array} haystack - the list to search in
   * @returns {boolean} - result of the array search
   */
  /* eslint-disable no-magic-numbers */
  function inArray(needle, haystack) {
    var i;

    for (i = 0; i < haystack.length; i += 1) {
      if (haystack[i] === needle) {
        return true;
      }
    }
    return false;
  }
  /* eslint-enable no-magic-numbers */
  /**
   * initializes the call, handles the delegation to track function
   * @param {string} supplier - the supplier's id
   * @param {string} campaign - the campaign's id
   * @param {object} data - additional data to append to the tracking url
   * @returns {void}
   */
  function init(supplier, campaign, data) {
    var windows = {},
    wnd = window,
    MIN_CAMPDATA = 1,
    MAX_CAMPDATA = 9,
    seqNr = 1,
    seqPrefix = parseInt(Math.random() * RANDOM_MULTIPLICAND_02, 10),
    reqObj = {
      type : 'iam_data',
      seq : seqPrefix + '_' + seqNr,
      supplier : supplier,
      campaign : campaign
    },
    msgdata,
    ready = false,
    measureHit = false,
    instanceIamData = null,
    eventList = [],
    extraVars = {
      avi: 'avi',
      bri: 'bri',
      pui: 'pui',
      sti: 'sti',
      nei: 'nei',
      pli: 'pli',
      cri: 'cri',
      adm: 'adm',
      adf: 'adf',
      exi: 'exi',
      ex2: 'ex2',
      rdi: 'rdi',
      roi: 'roi',
      rii: 'rii',
      uni: 'uni',
      aev: 'aev'
    },
    dataBase = (function campaignData() {
      var dataObject = {}, k;

      for (k in data) {
        if ({}.hasOwnProperty.call(data, k)) {
          if (k.indexOf('campdata') !== -1 && k.replace('campdata', '') >= MIN_CAMPDATA && k.replace('campdata', '') <= MAX_CAMPDATA) { //eslint-disable-line no-magic-numbers
            dataObject[k.replace('campdata', 'cd')] = data[k];
          }
          if (inArray(k, Object.keys(extraVars))) {
            dataObject[extraVars[k]] = data[k];
          }
        }
      }
      return dataObject;
    })();

    function flushEventList() {
      var evList = [],
      item;

      while (eventList.length) {
        item = eventList.pop();
        evList.push(item);
      }

      while (evList.length) {
        item = evList.pop();
        track(instanceIamData, item.supplier, item.campaign, item.data);
      }
    };

    if (isTopWindow || !jsonSupported || !postMessageSupported || iamData) {
        instanceIamData = iamData;
        ready = true;
    } else {
        addEventListener('beforeunload', function unloadListener(e) {
            if (!ready) {
              ready = true;
              flushEventList();
            }
        });

        addEventListener('message', function eventListener(msg) {
            try {
              msgdata = JSON.parse(msg.data);
            } catch (e) {
              msgdata = {seq: 'a'};
            }

            if (typeof msgdata === 'object'
            && typeof msgdata.seq !== 'undefined'
            && msg.source === windows[msgdata.seq]) {
              iamData = msgdata.iam_data;
              if (!ready) {
                ready = true;
                instanceIamData = iamData;
                flushEventList();
              }
            }
          });

        do {
            wnd = wnd.parent;
            reqObj.seq = seqPrefix + '_' + seqNr;
            wnd.postMessage(JSON.stringify(reqObj), '*');
            windows[reqObj.seq] = wnd;
            seqNr += 1; // eslint-disable-line no-magic-numbers
        } while (wnd !== top);

        window.setTimeout(function responseTimeout() {
            if (!ready) {
              ready = true;
              flushEventList();
            }
          }, WAITING_TIMEOUT);
    }

    // return event api
    return {
      trackEvent: function trackEvent(name, eventData) {
        var events = ['createview', 'start', 'firstquartile', 'midpoint', 'complete', 'thirdquartile',
          'mute', 'unmute', 'pause', 'rewind', 'resume', 'fullscreen', 'expand',
          'collapse', 'acceptinvitation', 'close', 'impression', 'clicktracking',
          'clickthrough'],
        minIndex = 0,
        data = {},
        dataObject = {},
        dataObjects = [],
        trackable = false;

        if (events.indexOf(name.toLowerCase()) >= minIndex) {
          trackable = true;
          dataObject = {ev:name};
        } else if (name === 'measure' && measureHit === false) {
          measureHit = true;
          trackable = true;
        }

        if (trackable) {
          eventData = eventData || {};
          dataObjects = [eventData, dataObject, dataBase];
          data = dataObjects.reduce(function red(r, o) {
            Object.keys(o).forEach(function ass(k) {
              r[k] = o[k];
            });
            return r;
          }, {});

          if (ready === false) {
            eventList.push({
              supplier: supplier,
              campaign: campaign,
              data: data
            });
          } else {
            track(instanceIamData, supplier, campaign, data);
          }
        }
      }
    };
  }


  window.iamAdtClient = window.iamAdtClient || {
	  init: function apiInit(vars) {
		  if (vars && ({}).toString.call(vars) === '[object Object]') {

		    if (vars.cp) {
		      vars.campaign = vars.cp;
		      delete vars.cp;
        }

		    if (vars.st) {
		      vars.supplier = vars.st;
		      delete vars.st;
        }

			  if (vars.campaign && vars.supplier) {
				  return init(vars.supplier, vars.campaign, (function callDelegate() {
		              delete vars.campaign;
		              delete vars.supplier;
		              return vars;
		            })());
			  }
		  }
		  return {
			  trackEvent: function empty() {}
		  };
	  },
      call: function apiCall(vars) {
        this.init(vars).trackEvent('measure');
      }
  };
})(document || {}, window || {});
