(function(ns, fetch){
  const shopifyScopeUpdatedPlaceholder = false;
  const cartTokenName = 'sibPreviousCartEventToken';
  const cartStateName = 'sibCartState';
  const { ShopifyAnalytics }  = window;
  const { meta: { page: { customerId } = {} } = {} } = ShopifyAnalytics || {};
  const { page: { customerId: metaCustomerId } = {} } = meta || {};
  const isShopifyScopeUpdated = shopifyScopeUpdatedPlaceholder === true;
  const enableCartTracking = Boolean(metaCustomerId);
  // const enableCartTracking = Boolean(isShopifyScopeUpdated ? ShopifyAnalytics : metaCustomerId);
  // const vistiorIdCookieName = 'sib_cuid';

  const setCookie = (name, value, days = '6.25') => {
		let expires = '';
		if (days) {
			const date = new Date();
			date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
			expires = `; expires=${date.toUTCString()}`;
		}
		document.cookie = `${name}=${value || ''}${expires}; path=/`;
	};

	const getCookie = (cookieName) => {
		const name = `${cookieName}=`;
		const cookieArray = document.cookie.split(';');
		for (let i = 0; i < cookieArray.length; i++) {
			let cookie = cookieArray[i];
			while (cookie.charAt(0) === ' ') cookie = cookie.substring(1, cookie.length);
			if (cookie.indexOf(name) === 0) return cookie.substring(name.length, cookie.length);
		}
		return null;
	};


  addListenerOnAjaxComplete();
  addWrapperForFetch(ns, fetch);

  async function sha1Encoding(message) {
		const msgUint8 = new TextEncoder().encode(message);                           // encode as (utf-8) Uint8Array
		const hashBuffer = await crypto.subtle.digest('SHA-1', msgUint8);           // hash the message
		const hashArray = Array.from(new Uint8Array(hashBuffer));                     // convert buffer to byte array
		const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); // convert bytes to hex string
		return hashHex;
	};

  const adds = (newItems, oldItems, action = 'addToCart') => {
      return Object.keys(newItems).reduce((result, productId) => {
        const newItemData = newItems[productId]||{};
        const oldItemData = oldItems[productId]||{};
        const quantity = newItemData.quantity || 0;
        const previousQuantity = oldItemData.quantity || 0;
        if( previousQuantity < quantity) {
          const data = { ...newItemData };
          data.quantity = quantity-previousQuantity;
          result.push({
            action,
            data
          });
        }
        return result
      }, [])
  }

  const removes = (newItems, oldItems) => {
      return adds(oldItems, newItems, 'removeFromCart')
  };

  const checkForCartStateChanges = (cart) => {
    const {items, token} = cart;
    if (!items)  return { data: cart, newCartState: {}, oldCartState: {} };
    if (getCookie(cartTokenName) !== token) {
        if (items.length > 0) setCookie(cartTokenName, token); 
        setCookie(cartStateName);//remove cart state
      }
      const {actiondata, newCartState, oldCartState} = resolveCartEvents(items);
      data = {...cart, actiondata};
      return { data, newCartState, oldCartState };
  }   

  const resolveCartEvents = (items) => {
    const cartStateCookie = getCookie(cartStateName);
    const oldCartState = cartStateCookie ? JSON.parse(cartStateCookie) : {}
    const newCartState = items.reduce((result, item) => { 
      const {  variant_title, 
              quantity, product_id, 
              product_title, 
              variant_id, 
              featured_image:{url:imageURL} = { url: ''}, 
              price, url, options_with_values = []} = item;
      const productId = variant_title ? variant_id : product_id;
      const sizeObj = (options_with_values && options_with_values.filter( option => option.name === 'Size'))[0] || {};
      const data = {
        variant_name: variant_title || '',
        quantity: quantity || '',
        product_id: product_id || '', 
        variant_id: variant_id || '', 
        name: product_title || '', 
        image: imageURL || '',
        price: price || '', 
        url: url ? window.location.origin + url : '', 
        size: sizeObj.value || ''
      }
      result[productId] = data;
      return result
    }, {})
    const actiondata = adds(newCartState, oldCartState).concat(removes(newCartState, oldCartState))[0];
    setCookie(cartStateName,JSON.stringify(newCartState));
    return {actiondata, newCartState, oldCartState};
    }

  function addWrapperForFetch(ns, fetch) {
    if(typeof fetch !== 'function') return;

    ns.fetch = function() {
      var out = fetch.apply(this, arguments);
      out.then(
        function(responseJson) {
          if (responseJson.status && responseJson.status == 200) {
            if ( enableCartTracking && (responseJson.url.match('/cart/add') || responseJson.url.match('/cart/change') || (isShopifyScopeUpdated && responseJson.url.match('/cart/update')))) {      
              fetch('/cart.js', {
                method: 'GET',
                credentials: 'same-origin',
                headers: {
                  'Content-Type': 'application/x-www-form-urlencoded',
                  'X-Requested-With': 'XMLHttpRequest'
                }            
              }).then(function(response) {
                  return response.json();
              }).then (function (cart) {
                callCartTrackingByFetch(cart)
              })
            } 
          }
        }
      )
  
      return out;
    }

    function callCartTrackingByFetch(response) {
      if(isShopifyScopeUpdated){
          const { data, newCartState, oldCartState } = checkForCartStateChanges(response);
          data.customerId = customerId || '';
          // data.visitor_uid = getCookie(vistiorIdCookieName);
          data.isFromShopFrontend = true;
          if(typeof theme !== 'undefined' && typeof theme.moneyFormat !== 'undefined') {
            data.moneyFormat = theme.moneyFormat;
          }
          try {
            sha1Encoding(JSON.stringify(oldCartState) + JSON.stringify(newCartState)).then(
              fingerPrint => {
                fetch('https://plugin.brevo.com/integrations/api/events/609e4f1bc44c2e45d9041d72/cart_tracking?ma-key=yno5j3cr6udvcewja27kb2c3', {
                  method: 'POST',
                  headers: {
                    'Content-Type': 'application/json'
                  },
                  body: JSON.stringify({fingerPrint,...data})        
                })  
              });  
          } catch (error) {
          }
      }
      else{
        let data = response;
        data.customerId = metaCustomerId;
        data.isFromShopFrontend = true;
        if(typeof theme !== 'undefined' && typeof theme.moneyFormat !== 'undefined') {
          data.moneyFormat = theme.moneyFormat;
        }
        fetch('https://plugin.brevo.com/integrations/api/events/609e4f1bc44c2e45d9041d72/cart_tracking?ma-key=yno5j3cr6udvcewja27kb2c3', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify(data)        
        });
      }  
    }
  }

  function addListenerOnAjaxComplete() {
    if (typeof jQuery === 'undefined') return;

    $(document).ajaxComplete(function (event, xhr, settings) {

      function callCartTrackingByJquery() {
        if(isShopifyScopeUpdated){
          const { data, newCartState, oldCartState } = checkForCartStateChanges(JSON.parse(this.responseText));
          data.isFromShopFrontend = true;
          if(typeof theme !== 'undefined' && typeof theme.moneyFormat !== 'undefined') {
            data.moneyFormat = theme.moneyFormat;
          }
          data.customerId = customerId || '';
          // data.visitor_uid = getCookie(vistiorIdCookieName);
          data.isFromShopFrontend = true;
          if(typeof theme !== 'undefined' && typeof theme.moneyFormat !== 'undefined') {
            data.moneyFormat = theme.moneyFormat;
          }
          try {
            sha1Encoding(JSON.stringify(oldCartState) + JSON.stringify(newCartState)).then(
              fingerPrint => {
                let request = new XMLHttpRequest();
                request.open('POST', 'https://plugin.brevo.com/integrations/api/events/609e4f1bc44c2e45d9041d72/cart_tracking?ma-key=yno5j3cr6udvcewja27kb2c3', true);
                request.setRequestHeader('Content-Type', 'application/json');
                request.send(JSON.stringify({fingerPrint,...data}));
              });   
          } catch (error) {
          }
        }
        else{
          let data = JSON.parse(this.responseText);
          data.customerId = metaCustomerId;
          data.isFromShopFrontend = true;
          if(typeof theme !== 'undefined' && typeof theme.moneyFormat !== 'undefined') {
            data.moneyFormat = theme.moneyFormat;
          }
          let request = new XMLHttpRequest();
          request.open('POST', 'https://plugin.brevo.com/integrations/api/events/609e4f1bc44c2e45d9041d72/cart_tracking?ma-key=yno5j3cr6udvcewja27kb2c3', true);
          request.setRequestHeader('Content-Type', 'application/json');
          request.send(JSON.stringify(data));
        }

      }
    
      if (enableCartTracking && (settings.url === '/cart/add.js' || settings.url === '/cart/change.js' || (isShopifyScopeUpdated && settings.url === '/cart/update.js'))) {
        let request = new XMLHttpRequest();
        request.addEventListener('load', callCartTrackingByJquery);
        request.open('GET', '/cart.js', true);
        request.send();
      } 
    });
  }
  
}(window, window.fetch))