(function(window) {
  'use strict';

  var close = false;
  var europe = ["AX","DK","EE","FO","FI","GG","IS","IE","JE","IM","LV","LT","NO","SJ","SE","GB","AL","AD","BA","HR","CY","GI","GR","IT","MK","VA","MT","ME","PT","SM","RS","SI","ES","BY","BG","CZ","GE","HU","MD","PL","RO","RU","SK","UA","AT","BE","FR","DE","LI","LU","MC","NL","CH"];
  var cookieDesc = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie') ||
    Object.getOwnPropertyDescriptor(HTMLDocument.prototype, 'cookie');
  var setter = cookieDesc.set;
  var getter = cookieDesc.get;
  var cookiesSet = [];
  var cookiesBlocked = false;

  function recordCookieSet(str) {
    cookiesSet.push(str);
    return true;
  }

  function deleteAllCookies() {
    var cookies = document.cookie.split(/;\s?/);

    for (var i = 0; i < cookies.length; i++) {
        var cookie = cookies[i];
        var eqPos = cookie.indexOf("=");
        var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
        document.cookie = name + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
    }
  }

  function blockCookies() {
    Object.defineProperty(document, 'cookie', {
      get: function () { return getter.call(document) },
      set: recordCookieSet,
      configurable: true
    });

    cookiesBlocked = true;
  }

  function restoreCookies() {
    Object.defineProperty(document, 'cookie', {
      get: function () { return getter.call(document) },
      set: function (val) { setter.call(document, val) },
    });

    // Set any cookie set during the enblockening
    cookiesSet.forEach(c => document.cookie = c);
  }

  /**
   * Retrieves the current users IP Address
   * @returns {Promise} resolves with the IP and other intel
   */
  function getIntel() {
    return fetch('https://geoip.internal.commerce.campaignmonitor.com/json/', {
      method: 'GET'
    })
      .then(function(res) {
        return res.json();
      })
      .then(function(data) {
        return data;
      });
  }

  /**
   * Gets the data with the passed name from localStorage
   * @param {String} name - the name of the property
   * @returns {String/Boolean/Number} the contents of the storage
   */
  function getData(name) {
    return localStorage.getItem(name);
  }

  /**
   * Checks if there is relevant data and what it's content are
   * then checks whether the user has accepted or declined
   * and returns the result
   * @param {String} ip - the users current IP
   * @returns {Object} the has accepted result and ip
   */
  function checkData(ip) {
    var url = window.location.href;

    // First check if there is any data stored
    var acceptCookie = getData('_accept_banner');
    var ipCookie = getData('_accept_banner_ip');

    // They accepted the banner previously
    if (acceptCookie) {
      if (acceptCookie === 'accept') {
        Cooki.setAccepted();
        if (cookiesBlocked) restoreCookies();
      }
      else if (acceptCookie === 'decline') Cooki.setDeclined();
      return { showBanner: false, ip: ip };
    }

    // No accept in storage, continue
    return { showBanner: true, ip: ip };
  }

  /**
   * Logs the decision and IP to the server
   * @param {String} choice - 'accept' or 'decline'
   * @param {String} ip - the users current IP
   * @returns {Promise} resolves on successfully sent log
   */
  function addLog(choice, ip) {
    var meta = {
      choice,
      notification: '5b08d9c8828c890014c6ed50',
      ip: ip,
      userAgent: navigator.userAgent,
      url: window.location.href
    };

    return fetch('https://cookihq.com/log', {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(meta)
    })
    .catch(function(e) {
      console.error('An error occurred while trying to ' +
        'record the acceptance of cookies', e);
    });
  }

  /**
   * Adds the HTML elements with styles and event listeners
   * @param {String} ip - the users current IP
   */
  function addNotification(ip, showBanner) {
    var height = 150;

    // Add style tag for additional compatibility
    var styles = document.createElement('style');
    styles.type = 'text/css';
    var css = '.cooki-description p { color: inherit; }';
    if (styles.styleSheet) styles.styleSheet.cssText = css;
    else styles.appendChild(document.createTextNode(css));
    document.body.appendChild(styles);

    // Create the container of the notification
    var container = document.createElement('div');
    container.style.cssText = 'background:#5c6ac4;position:fixed;' +
      'left:0px;right:0px;padding:0.5em 1em 1em;font-family:;' +
      'z-index: 999;transition: all 0.3s ease-in;';
    container.className= 'cooki-container';

    var description = document.createElement('div');
    description.style.cssText = 'color:#FFFFFF';
    description.innerHTML = '<p><strong>Why we use cookies:</strong> This website uses cookies to deliver the best possible user experience.</p>';
    description.className = 'cooki-description';
    container.appendChild(description);

    var accept = document.createElement('a');
    accept.style.cssText = 'border:0px;display:inline-block;padding:8px 20px;' +
      'background:#83be32;border-radius:0.3em;' +
      'color:#FFFFFF;cursor:pointer;font-size:1em;' +
      'text-decoration:none;';
    accept.innerHTML = 'Accept';
    accept.className = 'cooki-accept';
    accept.addEventListener('click', function() {
      // Update Height, the screen size could have altered it
      height = container.clientHeight;
      Cooki.callAccepted();
      if (cookiesBlocked) restoreCookies();
      if ('bottom' === 'top') container.style.top = '-' + height + 'px';
      else container.style.bottom = '-' + height + 'px';

      // Set the data for the accept
      localStorage.setItem('_accept_banner', 'accept');
      localStorage.setItem('_accept_banner_ip', ip);

      addLog('accept', ip);
    });
    container.appendChild(accept);

    var decline = document.createElement('a');
    decline.style.cssText = 'border:0px;display:inline-block;padding:8px 20px;' +
      'background:#bf0711;border-radius:0.3em;' +
      'color:#FFFFFF;cursor:pointer;margin-left:10px;' +
      'font-size:1em;text-decoration:none';
    decline.innerHTML = 'Decline';
    decline.className = 'cooki-decline';
    decline.addEventListener('click', function() {
      // Update Height, the screen size could have altered it
      height = container.clientHeight;
      Cooki.callDeclined();
      if ('bottom' === 'top') container.style.top = '-' + height + 'px';
      else container.style.bottom = '-' + height + 'px';

      // Set the data for the accepts
      localStorage.setItem('_accept_banner', 'decline');
      localStorage.setItem('_accept_banner_ip', ip);

      addLog('decline', ip);
    });
    container.appendChild(decline);

    if (true) {
      var info = document.createElement('a');
      info.style.cssText = 'border:0px;display:inline-block;padding:8px 20px;' +
        'background:#413fb5;border-radius:0.3em;' +
        'color:#FFFFFF;cursor:pointer;margin-left:10px;font-size:1em;' +
        'text-decoration:none;';
      info.innerHTML = 'More Info';
      info.setAttribute('href', '');
      info.setAttribute('target', '_blank');
      info.className = 'cooki-info';
      container.appendChild(info);
    }

    // Append the notification to the body
    document.body.appendChild(container);
    height = container.clientHeight;

    if ('' === 'true') {
      var tab = document.createElement('a');
      tab.style.cssText = 'position:absolute;background:#5c6ac4;' +
        'display:block;right:30px;padding:5px 10px;color:#FFFFFF;' +
        'cursor:pointer;';
      tab.innerText = '' || 'Cookies';
      tab.addEventListener('click', function() {
        if ('bottom' === 'top') container.style.top = '0px';
        else container.style.bottom = '0px';
      });
      container.appendChild(tab);
      var tabHeight = tab.clientHeight;
      if ('bottom' === 'top') {
        tab.style.bottom = '-' + tabHeight + 'px';
        tab.style.borderBottomRightRadius = '5px';
        tab.style.borderBottomLeftRadius = '5px';
      } else  {
        tab.style.top = '-' + tabHeight + 'px';
        tab.style.borderTopRightRadius = '5px';
        tab.style.borderTopLeftRadius = '5px';
      }
    }

    if ('bottom' === 'top') {
      container.style.top = '-' + height + 'px';
      if (showBanner) setTimeout(function() { container.style.top = '0px'; }, 10);
    } else {
      container.style.bottom = '-' + height + 'px';
      if (showBanner) setTimeout(function() { container.style.bottom = '0px'; }, 10);
    }
  }

  function isInEurope(intel) {
    return europe.indexOf(intel.country_code) > -1;
  }

  function CookiAPI() {
    this.acceptListeners = [];
    this.declineListeners = [];
    this.readyListeners = [];
    this.declined = false;
    this.accepted = false;
    this.isInEurope = false;
  }

  CookiAPI.prototype.addAcceptListener = function(listener) {
    this.acceptListeners.push(listener);
  }

  CookiAPI.prototype.removeAcceptListener = function(listener) {
    this.acceptListeners = this.acceptListeners.filter(function(l) {
      return l !== listener;
    });
  }

  CookiAPI.prototype.addDeclineListener = function(listener) {
    this.declineListeners.push(listener);
  }

  CookiAPI.prototype.removeDeclineListener = function(listener) {
    this.declineListeners = this.declineListeners.filter(function(l) {
      return l !== listener;
    });
  }

  CookiAPI.prototype.addReadyListener = function(listener) {
    this.readyListeners.push(listener);
  }

  CookiAPI.prototype.removeReadyListener = function(listener) {
    this.readyListeners = this.readyListeners.filter(function(l) {
      return l !== listener;
    });
  }

  CookiAPI.prototype.setAccepted = function() {
    this.accepted = true;
    this.declined = false;
  }

  CookiAPI.prototype.setDeclined = function() {
    this.accepted = false;
    this.declined = true;

    // Remove all cookies that are currently accessible
    if (
      '' === 'true' ||
      ('' === '' && 'false' === 'true')
    ) deleteAllCookies();
  }

  CookiAPI.prototype.callAccepted = function() {
    this.setAccepted();
    this.acceptListeners.forEach(function(listener) {
      if (listener) listener();
    });
  }

  CookiAPI.prototype.callDeclined = function() {
    this.setDeclined();
    this.declineListeners.forEach(function(listener) {
      if (listener) listener();
    });
  }

  CookiAPI.prototype.ready = function() {
    this.readyListeners.forEach(function(listener) {
      if (listener) listener();
    });
  }

  window.Cooki = new CookiAPI();

  if ('false' === 'true')  blockCookies();

  getIntel()
    .then(function(intel) {
      var result = isInEurope(intel)
      Cooki.isInEurope = result;

      // Check if the notification should be shown (europe)
      if (true) {
        // Check whether the country is in europe
        if (!result) {
          restoreCookies();
          return { showBanner: false, ip: intel.ip, isEurope: result };
        }
        return checkData(intel.ip);
      }

      // Check whether the ip has already been registered
      return checkData(intel.ip);
    })
    .then(function(data) {
      Cooki.ready();
      if (data.isEurope) return;

      // Add the notification
      addNotification(data.ip, data.showBanner);
    })
    .catch(function(e) {
      console.log(e);
      console.error('An error has occurred when adding the cookie notification', e);
    });
})(window);