// source --> https://aidatrans.at/modules/monitoringhub/js/event.js?t=1764744448 
(function() {
    class MonitoringHubEventMonitor {
    
        storageKey = "monitoringhub_events";
        
        consentModeInitialized = false;
    
        config = {
            debug: false,
            log_errors: true,
            store_enabled: false,
            set_only_required_consents: false,
            ga: '',
            gtm: '',
            aw: {
                account: '',
                labels: {
                    page_view: '',
                    view_item: '',
                    add_to_cart: '',
                    purchase: '',
                    lead: ''
                }
            },
            meta: '',
            tiktok: '',
            linkedin: {
                account: '',
                labels: {
                    purchase: '',
                    lead: ''
                }
            }
        };
    
        /**
         * @typedef {Object} StorageData
         * @property {MonitoringHub.UTM} utm
         * @property {string} monitor
         * @property {string} latest_referer_url
         * @property {number} latest_referer_time
         * @property {Object<string, any>} cookie_data
         * @property {Object<string, boolean>} enabled
         */
    
        /**
         * @type {StorageData}
         */
        storageData = null;
    
       /**
         * @typedef {Object} ListenerSettings
         * @property {MonitoringHub.Listener}  listener
         * @property {boolean} enabled
         * @property {boolean} loaded
         */
    
        /**
         * @type {Object.<string, ListenerSettings>}
         */
        listeners = {};
    
        /**
         * @typedef {Object} EventData
         * @property {MonitoringHub.Event} event
         * @property {Object.<string, boolean>} fired
         * @property {boolean} logged
         */
    
        /**
         * @type {EventData[]}
         */
        events = [];
        
        constructor() {
            this.config = { ...this.config, ...( window['monitoringhub_event_config'] || {}) };
    
            this.initErrorHandling();
            this.initDataLayer();
            this.initiateStorage();
    
        }
    
        log(...args) {
            if (!this.config.debug) return;
    
            console.info.apply(console, args);
        }
                
    
        initErrorHandling() {
            const log = this.log.bind(this);
            log("🚨 MonitoringHub: Initialisiere Fehler-Handling...");
    
            const logErrors = this.config.log_errors;

            const LOGGING_ENDPOINT = "/wp-json/monitoringhub/v1/log_error";
    
            function sendLog(errorData) {
                if (!logErrors) {
                    log("🚨 MonitoringHub disabled logging errors...", errorData);
                    return;
                }

                log("🚨 MonitoringHub logged error...", errorData);
                navigator.sendBeacon(LOGGING_ENDPOINT, JSON.stringify(errorData));
            }
    
            function formatError(error, source, lineno, colno) {
                return {
                    message: error?.message || error || "Unknown error",
                    stack: error?.stack || null,
                    source: source || null,
                    lineno: lineno || null,
                    colno: colno || null,
                    userAgent: navigator.userAgent,
                    timestamp: new Date().toISOString(),
                    page: window.location.href
                };
            }
    
            window.onerror = function (message, source, lineno, colno, error) {
                const errorData = formatError(error || message, source, lineno, colno);
                sendLog(errorData);
            };
    
            window.onunhandledrejection = function (event) {
                const errorData = formatError(event.reason, null, null, null);
                sendLog(errorData);
            };
    
            (function interceptConsoleErrors() {
                const originalConsoleError = console.error;
                console.error = function (...args) {
                    originalConsoleError.apply(console, args);
                    sendLog(args);
                };
            })();
        }
    
        initDataLayer(variable="dataLayer") {
            window[variable] = window[variable] || [];
            if (!window['gtag']) {
                window['gtag'] = function(){window[variable].push(arguments)};
            }
            this.initConsentMode();
            window['gtag']('js', new Date());
            console.log('🚨 MonitoringHub: gtag initialisiert', window[variable]);
        }
    
        /**
         * 
         * @param {Object|null} defaults 
         * @returns 
         */
        getStorageData(defaults=null) {
            if (!this.storageData) {
                this.storageData = {
                    'utm': {
                        updated: null,
                        source: "(direct)",
                        medium: "(none)",
                        campaign: null,
                        content: null,
                        term: null
                    },
                    'monitor': null,
                    'latest_referer_url': null,
                    'latest_referer_time': null,
                    'cookie_data': null,
                    'enabled': {}
                }
                try {
                    this.storageData = {...this.storageData, ...JSON.parse(localStorage.getItem(this.storageKey) || '{}')};
                    if (!this.config.store_enabled) {
                        this.storageData.enabled = {};
                    }
                    this.log("📦 MonitoringHub: Daten aus dem LocalStorage geladen!", this.storageData);
                } catch (error) {
                    this.log("🚨 MonitoringHub: Fehler beim Laden der Daten aus dem LocalStorage!", error);
                }
            }
            if (defaults) {
                this.storageData = { ...defaults, ...this.storageData };
            }
            return this.storageData;
    
        }
        setStorageData(data=null) {
            let storage = this.getStorageData();
            if (data) {
                this.storageData = { ...storage, ...data };
            }
            localStorage.setItem(this.storageKey, JSON.stringify({...this.storageData, ...(!this.config.store_enabled ? { 'enabled': {} } : {}) }));
        }
    
        initiateStorage() {
            let storage = this.getStorageData();
    
            if (document.referrer && document.referrer.indexOf(window.location.hostname) === -1) {
                this.setStorageData({
                    'latest_referer_url': document.referrer,
                    'latest_referer_time': Date.now()
                });
            }
    
            if (!storage.monitor) {
                this.setStorageData({ 'monitor': this.uuid() });
            }
            
            let utm = storage.utm;
            var updated = utm.updated ? false : true;
            var params = new URLSearchParams(window.location.search);
            ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'].forEach(param => {
                if (params.has(param)) {
                    this.log('update', param, params.get(param));
                    utm[param.replace('utm_', '')] = params.get(param);
                    updated = true;
                }
            });
    
            if (updated) {
                utm.updated = Date.now();
                this.setStorageData({ 'utm': utm });
            }
        }
    
        uuid() {
            return crypto.randomUUID();
        }
    
        /**
         * 
         * @param {MonitoringHub.Event} event 
         * @param {string[]} listeners 
         */
        logEventToServer(event, listeners=[]) {
            const hub = this;

            /**
             * @typedef {Object} Payload 
             * @property {MonitoringHub.Event} event
             * @property {string} monitor
             * @property {Object<string, any>} params
             * @property {string[]} onlyForListeners
             * @property {MonitoringHub.Webdata} webdata
             */

            let storage = hub.getStorageData();
            /**
             * @type {Payload}
             */
            let payload = {
                event: event,
                monitor: storage.monitor,
                params: storage.cookie_data,
                onlyForListeners: listeners,
                webdata: {
                    utm: storage.utm,
                    userAgent: window.navigator.userAgent,
                    referrer: storage.latest_referer_url,
                    url: window.location.href,
                    title: document.title,
                    language: window.navigator.language,
                    timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
                    viewport: {
                        width: window.innerWidth,
                        height: window.innerHeight
                    }
                }
            };

            let jsonData = JSON.stringify(payload);
            let size = (new Blob([jsonData]).size) / 1024;
            if (size > 64) {
                hub.log("📡 Sende post an Server:", { payload, listeners, size });
                fetch('/wp-json/monitoringhub/v1/monitor_event', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: jsonData
                });
            } else {
                hub.log("📡 Send beacon '"+ (event.name) +"' to server:", { payload, listeners, size });
                navigator.sendBeacon('/wp-json/monitoringhub/v1/monitor_event', JSON.stringify(payload));
            }
        }

        /**
         * 
         * @param {MonitoringHub.Event} event 
         */
        logEvent(event) {
            event.id = this.generateEventId();
            event.timestamp = Date.now();
            event.monitor = this.getStorageData().monitor;
            const eventState = {
                event: event,
                fired: {},
                logged: false
            };
            this.events.push( eventState );
            setTimeout(() => {
                this.processEventsForListeners();
            }, 0);
    
            
            const hub = this;

            setTimeout(() => {
                hub.logEventToServer(event);
                eventState.logged = true;
            }, 1);
        }
    
        processEventsForListeners() {
            Object.keys(this.listeners).forEach(listenerId => {
                this.processEventsForListener(listenerId);
            });
        }
    
        /**
         * 
         * @param {string} listenerId 
         */
        processEventsForListener(listenerId) {
            /**
             * @type {ListenerSettings}
             */
            let listenerSetting = this.listeners[listenerId] || null;
    
            if (!listenerSetting) {
                this.log("🔕 MonitoringHub: "+listenerId+" listener does not exist .... maybe no key set in config");
                return;
            }

            if (!listenerSetting.enabled ) {
                this.log("🔕 MonitoringHub: "+listenerId+" listener not enabled! - use monitoringHubEventMonitor.enable('"+listenerId+"'); ");                
                return;
            }
            const listener  = listenerSetting.listener
            
            if (!listenerSetting.loaded) {
                this.initConsentMode();
                this.log("🔔 MonitoringHub: Load "+listenerId+" listener ");
                if (listener['init']) listener.init();
                this.listeners[listenerId].loaded = true;
            }
    
            if (!listener['isAvailable'] || !listener.isAvailable()) {
                this.log("🔕 MonitoringHub: "+listenerId+" loaded but not available yet - setTimeout ");
                setTimeout(() => {
                    this.processEventsForListener(listenerId);
                }, 250);
                return;
            }
    
            this.events.forEach(eventData => {
                if (eventData.fired[listenerId]) {
                    return;
                }
                if (eventData.logged) {
                    this.logEventToServer(eventData.event, [listenerId]);
                }
                /**
                 * @type {MonitoringHub.Event}
                 */
                let event = eventData.event;
                if (event.name && listener[event.name]) {
                    try {
                        this.log("🔔 " + listener.id + ': ' + event.name);
                        listener[event.name](event);
                    } catch(e) {
                        this.log("🚨 ERROR " + listener.id + ': ' + event.name, event, e);
                    }
                } else {
                    this.log("⚠️ " + listener.id + ': ' + event.name + ' not implemented');
                }
                eventData.fired[listenerId] = true;
            });
        }
    
        getCookie(name) {
            let match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
            return match ? match[2] : null;
        }
    
        setCookie(name, value, days = 90) {
            const expires = new Date(Date.now() + days * 864e5).toUTCString();
            const domain = location.hostname.startsWith('www.')
                ? location.hostname.replace('www.', '.')
                : '.' + location.hostname;


            document.cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}; expires=${expires}; path=/;  domain=${domain}; SameSite=Lax`;
        }
        
        generateEventId() {
            return this.uuid();
        }
    
        /**
         * 
         * @param {MonitoringHub.Listener} listener 
         */
        addListener(listener) {
            this.listeners[listener.id] = {
                'listener': listener,
                'loaded': false,
                'enabled': this.getStorageData()?.enabled[listener.id] || false
            };
        }
    
        enable(id) {
            let listener = this.listeners[id];
            if (listener) {
                listener.enabled = true;
            }
            this.getStorageData({ 'enabled': {} });
            this.storageData.enabled[id] = true;
            this.setStorageData();
            this.processEventsForListener(id);
        }
        
        disable(id) {
            let listener = this.listeners[id];
            if (listener) {
                listener.enabled = false;
            }
            this.getStorageData({ 'enabled': {} });
            delete this.storageData.enabled[id];
            this.setStorageData();
        }
       
        init() {
            const params = new URLSearchParams(window.location.search)
            let cookie_data = this.getStorageData().cookie_data || {};
    
            for(let listener of Object.values(this.listeners)) {
                const listener_url_data = {};
                (listener.listener.params || []).forEach(param => {                
                    const value = params.get(param);
                    if (value) {
                        listener_url_data[param] = value;
                    }
                });
                
                const listener_cookie_data = {};
                (listener.listener.cookies || []).forEach(cookie => {
                    const value = this.getCookie(cookie);
                    if (value) {
                        listener_cookie_data[cookie] = value
                    }
                });
    
                const listener_localstorage_data = {};
                (listener.listener.localstorage || []).forEach(item => {
                    const value = localStorage.getItem(item);
                    if (value) {
                        listener_localstorage_data[item] = value
                    }
                });
    
                let listener_processed_data = {};
                if (listener.listener.processParams) {
                    listener_processed_data = listener.listener.processParams(listener_url_data, listener_cookie_data, listener_localstorage_data);
                }
                
                this.log("🔒 MonitoringHub: Params für " + listener.listener.id + " initialisiert", { listener_url_data, listener_cookie_data, listener_localstorage_data, listener_processed_data});
                cookie_data = {...cookie_data, ...listener_url_data, ...listener_cookie_data, ...listener_localstorage_data, ...listener_processed_data};
            }
            
            this.log("🔒 MonitoringHub: Params gesetzt", cookie_data );
            this.setStorageData({ cookie_data });
        }
        
        loadScript(src, callback=null) {
            const s = document.createElement('script');
            s.src = src;
            s.async = true; // lädt parallel, blockiert nichts
            if (callback) {
                s.onload = callback;
            }
            document.head.appendChild(s);
        }
        
    
        initConsentMode() {
            if (!window['gtag']) {
                this.log("🚨 MonitoringHub: gtag nicht gefunden!");
                return;
            }
    
            var enabled = this.getStorageData({ 'enabled': {} }).enabled;        
            var consentmodes = this.config.set_only_required_consents ? {} : {
                'ad_storage': 'denied',
                'ad_user_data': 'denied',
                'ad_personalization': 'denied',
                'analytics_storage': 'denied',
                'personalization_storage': 'denied',
                'functionality_storage': 'granted',
            };
    
            Object.keys(this.listeners).forEach(listenerId => {
                if (!enabled[listenerId]) return;
    
                const listener = this.listeners[listenerId].listener;
                (listener.consentmodes || []).forEach(mode => {
                    consentmodes[mode] = 'granted';
                });
            });
    
            if (Object.keys(consentmodes).length === 0) {
                this.log("🔒 MonitoringHub: Keine Consent-Modi für Listener gefunden!")

            } else if (!this.consentModeInitialized) {
                const initConsent =  { 'wait_for_update': 250, ...consentmodes};
                this.log("🔒 MonitoringHub: Consent-Modus initialisiert", initConsent);
                window['gtag']('consent', 'default', initConsent);
                
                this.consentModeInitialized = true;
            } else {
                this.log("🔒 MonitoringHub: Consent-Modus updated", consentmodes);
                window['gtag']('consent', 'update', consentmodes);
                
            }
        }
    
        pageView() {
            /** @type {MonitoringHub.PageViewEvent} */
            let event = {
                name: "pageView",
                page: window.location.href
            };
            this.logEvent(event);
        }
        
        viewItem({id=null, name=null, value=0, currency="EUR", type="product", category="", gtin= "", mpn="", brand=""} = {}) {
            /** @type {MonitoringHub.ViewItemEvent} */
            let event = {
                name: "viewItem",
                item: {
                    id: id,
                    name: name,
                    value: value,
                    currency: currency,
                    type: type,
                    quantity: 1,
                    category: category,
                    gtin: gtin,
                    mpn: mpn,
                    brand: brand
                }
            };
            this.logEvent(event);
        }
    
        addToCart({id=null, name=null, value=0, quantity=1, currency="EUR", type="product", category="", gtin="", mpn="", brand=""} = {}) {
            /** @type {MonitoringHub.AddToCartEvent} */
            let event = {
                name: "addToCart",
                item: {
                    id: id,
                    name: name,
                    value: value,
                    currency: currency,
                    type: type,
                    quantity: quantity,
                    category: category,
                    gtin: gtin,
                    mpn: mpn,
                    brand: brand
                }
            };
            this.logEvent(event);
        }
    
        initiateCheckout({ items=[{id: null, name: null, value: 0, quantity: 1, currency: "EUR", type: "product", category: "", gtin: "", mpn: "", brand: ""}]} = {}) {
            // Validate items
            if (!Array.isArray(items) || items.length === 0) {
                this.log("🚨 MonitoringHub: Invalid items array for initiateCheckout event.");
                return;
            }
    
            for (let item of items) {
                if (!item.id) item.id = "unknown";
                if (!item.name) item.name = "unknown";
                if (typeof item.value !== 'number') item.value = 0;
                if (typeof item.quantity !== 'number') item.quantity = 1;

                if (!item.gtin) item.gtin = "";
                if (!item.mpn) item.mpn = "";
                if (!item.brand) item.brand = "";
                
            }
    
            /** @type {MonitoringHub.InitiateCheckoutEvent} */
            let event = {
                name: "initiateCheckout",
                items: items
            };
            this.logEvent(event);
        }
        

        addPaymentInfo({ items=[{id: null, name: null, value: 0, quantity: 1, currency: "EUR", type: "product", category: "", gtin: "", mpn: "", brand: ""}]} = {}) {
            // Validate items
            if (!Array.isArray(items) || items.length === 0) {
                this.log("🚨 MonitoringHub: Invalid items array for addPaymentInfo event.");
                return;
            }
    
            for (let item of items) {
                if (!item.id) item.id = "unknown";
                if (!item.name) item.name = "unknown";
                if (typeof item.value !== 'number') item.value = 0;
                if (typeof item.quantity !== 'number') item.quantity = 1;

                if (!item.gtin) item.gtin = "";
                if (!item.mpn) item.mpn = "";
                if (!item.brand) item.brand = "";
                
            }
    
            /** @type {MonitoringHub.InitiateCheckoutEvent} */
            let event = {
                name: "initiateCheckout",
                items: items
            };
            this.logEvent(event);
        }

        purchase({ 
            transaction=null, 
            items=[{id: null, name: null, value: 0, quantity: 1, currency: "EUR", type: "product", category: "", gtin: "", mpn: "", brand: ""}], 
            delivery_country=null,
            customer_email=null,
            estimated_delivery_date=null,
        } = {}) {
            // Validate items
            if (!Array.isArray(items) || items.length === 0) {
                this.log("🚨 MonitoringHub: Invalid items array for purchase event.");
                return;
            }
    
            for (let item of items) {
                if (!item.id) item.id = "unknown";
                if (!item.name) item.name = "unknown";
                if (typeof item.value !== 'number') item.value = 0;
                if (typeof item.quantity !== 'number') item.quantity = 1;

                if (!item.gtin) item.gtin = "";
                if (!item.mpn) item.mpn = "";
                if (!item.brand) item.brand = "";
                
            }
    
            /** @type {MonitoringHub.PurchaseEvent} */
            let event = {
                name: "purchase",
                transaction_id: transaction,
                delivery_country: delivery_country,
                customer_email: customer_email,
                estimated_delivery_date: estimated_delivery_date,
                items: items
            };
            this.logEvent(event);
        }

        lead({subject="", value=0, currency="EUR"}={}) {
             /** @type {MonitoringHub.LeadEvent} */
             let event = {
                name: "lead",
                subject: subject,
                value: value,
                currency: currency
            };
            this.logEvent(event);
        }

        search(event={}) {
            this.log("🚨 MonitoringHub: not implemented ", event.name);
        }

        schedule(event={}) {
            this.log("🚨 MonitoringHub: not implemented ", event.name);
        }

        startTrial(event={}) {
            this.log("🚨 MonitoringHub: not implemented ", event.name);
        }

        submitApplication(event={}) {
            this.log("🚨 MonitoringHub: not implemented ", event.name);
        }

        subscribe(event={}) {
            this.log("🚨 MonitoringHub: not implemented ", event.name);
        }

        customizeProduct(event={}) {
            this.log("🚨 MonitoringHub: not implemented ", event.name);
        }

        viewItemList(event={}) {
            this.log("🚨 MonitoringHub: not implemented ", event.name);
        }
    }
    
    let monitoringHubEventMonitor = new MonitoringHubEventMonitor();
    // **Globale Instanz bereitstellen**
    window['monitoringHubEventMonitor'] = monitoringHubEventMonitor;
    
    if (!window['monitoringhub_event_config']) {
        monitoringHubEventMonitor.log("🚨 MonitoringHub: Event-Codes nicht gefunden!");
    } else {
        monitoringHubEventMonitor.log("✅ MonitoringHub: Event Codes geladen!", monitoringHubEventMonitor.config);
        
        if (monitoringHubEventMonitor.config.ga) {    
            monitoringHubEventMonitor.addListener({
                id: 'ga',
                name: 'Google Analytics',
                cookies: ['_ga'],
                localstorage: [],
                consentmodes: ['analytics_storage'],
                isAvailable: function () {
                    return window['gtag'] && window['gtag'] instanceof Function;
                },
                baseEventProperty: function(event) {
                    const ret = { 
                        'send_to': monitoringHubEventMonitor.config.ga,
                        'anonymize_ip': true,
                        'event_id': event.id,
                        'user_id': event.monitor
                    };
                    if (event.item) {
                        ret['value'] = event.item?.value * event.item?.quantity;
                        ret['currency'] = event.item?.currency;
                        ret['items'] = [{
                            'item_id': event.item?.id,
                            'item_name': event.item?.name,
                            'item_category': event.item?.category,
                            'quantity': event.item?.quantity,
                            'price': event.item?.value
                        }];
                    };
                    if (event.items) {
                        ret['value'] = event.items?.reduce((acc, item) => (acc + item.value * item.quantity), 0);
                        ret['currency'] = event.items ? event.items[0].currency : 'EUR';
                        ret['items'] = event.items.map((item, index) => ({
                            'item_id': item.id,
                            'item_name': item.name,
                            'item_category': item.category,
                            'quantity': item.quantity,
                            'price': item.value
                        }));
                    };
                    return ret;
                },
                init: function () {
                    monitoringHubEventMonitor.log("🔔 GA init " + monitoringHubEventMonitor.config.ga);
                    monitoringHubEventMonitor.loadScript("https://www.googletagmanager.com/gtag/js?id=" + monitoringHubEventMonitor.config.ga);
                    monitoringHubEventMonitor.log("🔔 GA config");
                    gtag('config', monitoringHubEventMonitor.config.ga, { 
                        'send_page_view': false, 
                        'anonymize_ip': true,
                    });
                },
                pageView: function (event) {
                    gtag('event', 'page_view', { 
                        ...this.baseEventProperty(event)
                    });
                },
                viewItem: function (event) {
                    gtag('event', 'view_item', {
                        ...this.baseEventProperty(event)
                    });
                },
                addToCart: function (event) {
                    gtag('event', 'add_to_cart', { 
                        ...this.baseEventProperty(event)
                    });
                },
                initiateCheckout: function (event) {
                    gtag('event', 'begin_checkout', { 
                        ...this.baseEventProperty(event)
                    });
                },
                addPaymentInfo: function (event) {
                    gtag('event', 'add_payment_info', { 
                        ...this.baseEventProperty(event)
                    });
                },
                purchase: function (event) {
                    gtag('event', 'purchase', {
                        ...this.baseEventProperty(event),
                        'transaction_id': event.transaction_id,
                    });
                },
                lead: function (event) {
                    gtag('event', 'generate_lead', {
                        ...this.baseEventProperty(event)
                    });
                },
                search: function (event) {
                    gtag('event', 'search', {
                        ...this.baseEventProperty(event)
                    });
                },
                schedule: function (event) {
                    gtag('event', 'schedule', {
                        ...this.baseEventProperty(event)
                    });
                },
                startTrial: function (event) {
                    gtag('event', 'start_trial', {
                        ...this.baseEventProperty(event)
                    });
                },
                submitApplication: function (event) {
                    gtag('event', 'submit_application', {
                        ...this.baseEventProperty(event)
                    });
                },
                subscribe: function (event) {
                    gtag('event', 'subscribe', {
                        ...this.baseEventProperty(event)
                    });
                },
                customizeProduct: function (event) {
                    gtag('event', 'customize_product', {
                        ...this.baseEventProperty(event)
                    });
                },
                viewItemList: function (event) {
                    gtag('event', 'view_item_list', {
                        ...this.baseEventProperty(event)
                    });
                }
            });   
        }


        if (monitoringHubEventMonitor.config.meta) {    
            monitoringHubEventMonitor.addListener({
                id: 'meta',
                name: 'Facebook / Meta',
                params: ['fbclid'],
                cookies: ['_fbp', '_fbc', 'fr', 'datr', 'xs', 'c_user', 'sb', 'wd', 'usida'],
                localstorage: [],
                consentmodes: [],
                processParams: function (url_data, cookie_data, localstorage_data) {
                    const ret = {};
                    if (url_data['fbclid']) {
                        const timestamp = Math.floor(Date.now()); 
                        ret['_fbc'] = `fb.1.${timestamp}.${url_data['fbclid']}`;
                        /* das find ich eher blöd hier, aber egal momentan */
                        monitoringHubEventMonitor.setCookie('_fbc', ret['_fbc'], 90);
                    } else {
                        const fbcCleanup = monitoringHubEventMonitor.getCookie('_fbc');
                        if(fbcCleanup){
                            const match = fbcCleanup.match(/fb\.[0-9]\.(\d+)\.(.*)/);
                            let ts = parseInt(match[1]);
                            if(ts < 9999999999){ // nur 10 Stellen = Sekunden
                                ret['_fbc'] = fbcCleanup.replace('.' + match[1] + '.', "." + Date.now() + ".");
                                monitoringHubEventMonitor.log("🔔 META Cookie _fbc gefunden, aber nicht mehr gültig - " + fbcCleanup + ' - ' + ret['_fbc']);
                                monitoringHubEventMonitor.setCookie('_fbc', ret['_fbc'], 90);
                            }
                        }
                    }
                    return ret;
                },
                isAvailable: function () {
                    return window['fbq'] && window['fbq'] instanceof Function;
                },
                _sha256: async function(str) {
                    const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(str));
                    return Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, '0')).join('');
                },
                _track: async function(eventname, event, params) {
                    const external_id = await this._sha256(event.monitor)
                    const ret = {
                        external_id
                    };
                    if (event.item) {
                        ret['content_ids'] = [ event.item.id ];
                        ret['content_name'] = [ event.item.name ];
                        ret['content_type'] = event.item.type;
                        ret['num_items'] = 1;
                        ret['value'] = event.item.value * event.item.quantity;
                        ret['currency'] = event.item.currency;
                    };
                    if (event.items) {
                        ret['content_ids'] = event.items.map((item, index) => item.id);
                        ret['content_name'] = event.items.map((item, index) => item.id).join(', ');
                        ret['num_items'] = event.items?.length || 0,
                        ret['value'] = event.items?.reduce((acc, item) => (acc + item.value * item.quantity), 0);
                        ret['currency'] = event.items ? event.items[0].currency : 'EUR';
                        ret['items'] = event.items.map((item, index) => ({
                            'id': item.id,
                            'name': item.name,
                            'category': item.category,
                            'quantity': item.quantity,
                            'price': item.value,
                            'value': item.value * item.quantity
                        }));
                    };
                    const eventId = event.transaction_id || event.id;
                    fbq('trackSingle', monitoringHubEventMonitor.config.meta, eventname, {
                        ...ret,
                        ...params
                    }, { eventID: eventId });

                    monitoringHubEventMonitor.log("🔔  META data", ['trackSingle', monitoringHubEventMonitor.config.meta, eventname, {
                        ...ret,
                        ...params
                    }, { eventID: eventId }]);
                },
                init: function () {
                    monitoringHubEventMonitor.log("🔔 init META script " + monitoringHubEventMonitor.config.meta);
    
                    // @ts-ignore
                    !function(f,b,e,v,n,t,s)
                    {if(f.fbq)return;n=f.fbq=function(){n.callMethod?
                    n.callMethod.apply(n,arguments):n.queue.push(arguments)};
                    if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
                    n.queue=[];t=b.createElement(e);t.async=!0;
                    t.src=v;s=b.getElementsByTagName(e)[0];
                    s.parentNode.insertBefore(t,s)}(window, document,'script',
                    'https://connect.facebook.net/en_US/fbevents.js');
                    fbq('init', monitoringHubEventMonitor.config.meta);

                    
                },
                pageView: function (event) {
                    this._track('PageView', event, {
                    });
                },
                viewItem: function (event) {
                    this._track('ViewContent', event, {
                    });
                },
                addToCart: function (event) {
                    this._track('AddToCart', event, {
                    });
                },
                initiateCheckout: function (event) {
                    this._track('InitiateCheckout', event, {
                    });
                },
                addPaymentInfo: function (event) {
                    this._track('AddPaymentInfo', event, {
                    });
                },
                purchase: function (event) {                
                    this._track('Purchase', event, {
                    });
                },
                lead: function (event) {
                    this._track('Lead', event, {
                    });
                },
                search: function (event) {
                    this._track('Search', event, {
                    });
                },
                schedule: function (event) {
                    this._track('Schedule', event, {
                    });
                },
                startTrial: function (event) {
                    this._track('StartTrial', event, {
                    });
                },
                submitApplication: function (event) {
                    this._track('SubmitApplication', event, {
                    });
                },
                subscribe: function (event) {
                    this._track('Subscribe', event, {
                    });
                },
                customizeProduct: function (event) {
                    this._track('CustomizeProduct', event, {
                    });
                },
                viewItemList: function (event) {
                    this._track('ViewItemList', event, {
                    });
                }            
            });
        }

        if (monitoringHubEventMonitor.config.aw && monitoringHubEventMonitor.config.aw.account) {    
            monitoringHubEventMonitor.addListener({
                id: 'aw',
                name: 'Google Ads',
                params: ['srsltid', 'gclid', 'gbraid', 'wbraid' ],
                cookies: ['_gcl_au', '_gcl_aw', '_gcl_dc', 'gclid' ],
                localstorage: [],
                consentmodes: [ 'analytics_storage', 'ad_storage', 'ad_user_data', 'ad_personalization' ],
                baseEventProperty: function(event) {
                    const ret = { 
                        'send_to': monitoringHubEventMonitor.config.aw.account,
                        'anonymize_ip': true,
                        'event_id': event.id,
                        'user_id': event.monitor
                    };
                    if (event.item) {
                        ret['value'] = event.item?.value * event.item?.quantity;
                        ret['currency'] = event.item?.currency;
                        ret['items'] = [{
                            'item_id': event.item?.id,
                            'item_name': event.item?.name,
                            'item_category': event.item?.category,
                            'quantity': event.item?.quantity,
                            'price': event.item?.value
                        }];
                    };
                    if (event.items) {
                        ret['value'] = event.items?.reduce((acc, item) => (acc + (item.value * item.quantity)), 0);
                        ret['currency'] = event.items ? event.items[0].currency : 'EUR';
                        ret['items'] = event.items.map((item, index) => ({
                            'item_id': item.id,
                            'item_name': item.name,
                            'item_category': item.category,
                            'quantity': item.quantity,
                            'price': item.value
                        }))
                    };
                    return ret;
                },
                _conversion(label, event) {
                    if (!monitoringHubEventMonitor.config.aw.labels[label]) return;
                    const send_to = monitoringHubEventMonitor.config.aw.labels[label].replace(/AW-\w+\//, '');

                    const conversion = { 
                        'send_to': monitoringHubEventMonitor.config.aw.account + '/' + send_to,
                        'anonymize_ip': true,
                        'event_id': event.id,
                        'user_id': event.monitor,
                        'transaction_id': event.transaction_id || event.monitor + '_' + event.name + '_' + (new Date()).toDateString(),
                    };
                    if (event.item) {
                        conversion['value'] = event.item?.value * event.item?.quantity;
                        conversion['currency'] = event.item?.currency;
                    };
                    if (event.items) {
                        conversion['value'] = event.items?.reduce((acc, item) => (acc + item.value * item.quantity), 0);
                        conversion['currency'] = event.items ? event.items[0].currency : 'EUR';
                    }
                    gtag('event', 'conversion', conversion);

                },
                isAvailable: function () {
                    return window['gtag'] && window['gtag'] instanceof Function;
                },
                init: function () {
                    monitoringHubEventMonitor.log("🔔 AW init " + monitoringHubEventMonitor.config.aw.account);
                    monitoringHubEventMonitor.loadScript("https://www.googletagmanager.com/gtag/js?id=" + monitoringHubEventMonitor.config.aw.account);
                    monitoringHubEventMonitor.log("🔔 AW config");
                    gtag('config', monitoringHubEventMonitor.config.aw.account, { 
                        'send_page_view': false, 
                        'anonymize_ip': true,
                    });
                },
                pageView: function (event) {
                    this._conversion('page_view', event);
                    gtag('event', 'page_view', {
                        ...this.baseEventProperty(event) 
                    });
                },
                viewItem: function (event) {
                    this._conversion('view_item', event);
                    gtag('event', 'view_item', {
                        ...this.baseEventProperty(event)
                    });
                },
                addToCart: function (event) {
                    this._conversion('add_to_cart', event);
                    gtag('event', 'add_to_cart', {
                        ...this.baseEventProperty(event)
                    });
                },
                initiateCheckout: function (event) {
                    this._conversion('initiate_checkout', event);
                    gtag('event', 'begin_checkout', {
                        ...this.baseEventProperty(event)
                    });
                },
                addPaymentInfo: function (event) {
                    gtag('event', 'add_payment_info', {
                        ...this.baseEventProperty(event)
                    });
                },
                purchase: function (event) {
                    this._conversion('purchase', event);
                    gtag('event', 'purchase', {
                        ...this.baseEventProperty(event),
                        'transaction_id': event.transaction_id,
                    });

                },
                lead: function (event) {
                    this._conversion('lead', event);
                    gtag('event', 'generate_lead', {
                        ...this.baseEventProperty(event)
                    });
                },
                search: function (event) {
                    gtag('event', 'search', {
                        ...this.baseEventProperty(event)
                    });
                },
                schedule: function (event) {
                    gtag('event', 'schedule', {
                        ...this.baseEventProperty(event)
                    });
                },
                startTrial: function (event) {
                    gtag('event', 'start_trial', {
                        ...this.baseEventProperty(event)
                    });
                },
                submitApplication: function (event) {
                    gtag('event', 'submit_application', {
                        ...this.baseEventProperty(event)
                    });
                },
                subscribe: function (event) {
                    gtag('event', 'subscribe', {
                        ...this.baseEventProperty(event)
                    });
                },
                customizeProduct: function (event) {
                    gtag('event', 'customize_product', {
                        ...this.baseEventProperty(event)
                    });
                },
                viewItemList: function (event) {
                    gtag('event', 'view_item_list', {
                        ...this.baseEventProperty(event)
                    });
                }
            });   
        }
    
        if (monitoringHubEventMonitor.config.linkedin && monitoringHubEventMonitor.config.linkedin.account) {    
            monitoringHubEventMonitor.addListener({
                id: 'li',
                name: 'LinkedIn',
                params: [],
                cookies: ['li_fat_id', 'li_sugr', 'UserMatchHistory', 'bcookie', 'lidc'],
                localstorage: [],
                consentmodes: [],
                isAvailable: function () {
                    return typeof window['lintrk'] === 'function';
                },
                init: function () {
                    monitoringHubEventMonitor.log("🔔 init LinkedIn Insight Tag");

                    // Insight Tag (Standard Snippet)
                    const partnerId = monitoringHubEventMonitor.config.linkedin.account;
                    window._linkedin_partner_id = partnerId;
                    window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];
                    window._linkedin_data_partner_ids.push(partnerId);

                    const script = document.createElement("script");
                    script.type = "text/javascript";
                    script.async = true;
                    script.src = "https://snap.licdn.com/li.lms-analytics/insight.min.js";
                    document.head.appendChild(script);
                },
                
                _track(label, event) {
                    if (!monitoringHubEventMonitor.config.linkedin.labels[label]) return;
                    lintrk('track', {
                        conversion_id: monitoringHubEventMonitor.config.linkedin.labels[label],
                        event_id: event.id // optional
                    });
                },
                pageView: function (event) {
                    this._track('pageView', event);
                },
                purchase: function (event) {                
                    this._track('purchase', event);
                },
                lead: function (event) {
                    this._track('lead', event);
                }
            });
        }

        if (monitoringHubEventMonitor.config.tiktok) {
            monitoringHubEventMonitor.addListener({
                id: 'tt',
                name: 'TikTok',
                params: ['ttclid'],
                cookies: ['_ttp'],
                localstorage: [],
                consentmodes: [],
                isAvailable() {
                    return typeof window['ttq'] === 'object';
                },
                init() {
                    monitoringHubEventMonitor.log("🔔 init TikTok Pixel");
        
                    const tagId = monitoringHubEventMonitor.config.tiktok;
                    
                    // @ts-ignore
                    !function (w, d, t) {
                    w.TiktokAnalyticsObject=t;var ttq=w[t]=w[t]||[];ttq.methods=["page","track","identify","instances","debug","on","off","once","ready","alias","group","enableCookie","disableCookie","holdConsent","revokeConsent","grantConsent"],ttq.setAndDefer=function(t,e){t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}};for(var i=0;i<ttq.methods.length;i++)ttq.setAndDefer(ttq,ttq.methods[i]);ttq.instance=function(t){for(
                    var e=ttq._i[t]||[],n=0;n<ttq.methods.length;n++)ttq.setAndDefer(e,ttq.methods[n]);return e},ttq.load=function(e,n){var r="https://analytics.tiktok.com/i18n/pixel/events.js",o=n&&n.partner;ttq._i=ttq._i||{},ttq._i[e]=[],ttq._i[e]._u=r,ttq._t=ttq._t||{},ttq._t[e]=+new Date,ttq._o=ttq._o||{},ttq._o[e]=n||{};n=document.createElement("script")
                    ;n.type="text/javascript",n.async=!0,n.src=r+"?sdkid="+e+"&lib="+t;e=document.getElementsByTagName("script")[0];e.parentNode.insertBefore(n,e)};
                    ttq.load(tagId);
                    }(window, document, 'ttq');

                },
                _track(eventname, event, params = {}) {
                    const data = {
                        external_id: event.monitor,
                    };

                    if (event.items) {
                        data['content_id'] = event.items.map(i => i.id).join(',');
                        data['quantity'] = event.items.length;
                        data['value'] = event.items.reduce((acc, i) => (acc + i.value * i.quantity), 0);
                        data['currency'] = event.items[0]?.currency || 'EUR';
                        data['contents'] = event.items.map(i => ({
                            content_id: i.id,
                            content_type: i.type || 'product',
                            content_category: i.category || 'Unknown',
                            quantity: i.quantity,
                            price: i.value,
                            value: i.value * i.quantity
                        }));
                    }
        
                    if (event.item) {
                        data['content_id'] = event.item.id;
                        data['value'] = event.item.value * event.item.quantity;
                        data['currency'] = event.item.currency;
                        data['quantity'] = 1;
                        data['contents'] = [{
                            content_id: event.item.id,
                            content_type: event.item.type || 'product',
                            content_category: event.item.category || 'Unknown',
                            quantity: event.item.quantity,
                            price: event.item.value,
                            value: event.item.value * event.item.quantity
                        }];
                    }
        
                    const eventId = event.transaction_id || event.id;
        
                    ttq.track(eventname, {
                        ...data,
                        ...params,
                    }, { event_id: eventId });
                    
                },
                pageView(event) {
                    this._track('PageView', event);
                },
                viewItem(event) {
                    this._track('ViewContent', event);
                },
                addToCart(event) {
                    this._track('AddToCart', event);
                },
                initiateCheckout(event) {
                    this._track('InitiateCheckout', event);
                },
                purchase(event) {
                    this._track('Purchase', event);
                },
                lead(event) {
                    this._track('Lead', event);
                }
            });
        }


        if (monitoringHubEventMonitor.config.mc) {    
            monitoringHubEventMonitor.addListener({
                id: 'mc',
                name: 'MerchantCenter',
                params: [],
                cookies: [],
                localstorage: [],
                consentmodes: [],
                isAvailable: function () {
                    return true;
                },
                pageView:  function (event) {},
                viewItem:  function (event) {},
                addToCart:  function (event) {},
                initiateCheckout:  function (event) {},
                addPaymentInfo:  function (event) {},
                lead:  function (event) {},
                search:  function (event) {},
                schedule:  function (event) {},
                startTrial:  function (event) {},
                submitApplication:  function (event) {},
                subscribe:  function (event) {},
                customizeProduct:  function (event) {},
                viewItemList: function (event) {},
                purchase: function (event) {

                    const products = event.items.map((item) => {
                        return {
                            gtin: item.gtin,
                            id: item.id,
                        };
                    }).filter((item) => {
                        if (item.gtin) return true;
                        return false;
                    });

                    window.merchantCenterRenderOptIn = function() {
                        window.gapi.load('surveyoptin', function() {
                            window.gapi.surveyoptin.render({
                                // REQUIRED FIELDS
                                "merchant_id": monitoringHubEventMonitor.config.mc,
                                "order_id": event.transaction_id,
                                "email": event.customer_email,
                                "delivery_country": event.delivery_country,
                                "estimated_delivery_date": event.estimated_delivery_date,
                                // OPTIONAL FIELDS
                                "products": products
                            });
                        });
                      
                    }

                    const script = document.createElement("script");
                    script.type = "text/javascript";
                    script.async = true;
                    script.defer = true;
                    script.src = "https://apis.google.com/js/platform.js?onload=merchantCenterRenderOptIn";
                    document.head.appendChild(script);
                }
            });
        }
    }
    monitoringHubEventMonitor.init();

    document.addEventListener('DOMContentLoaded', function() {
        monitoringHubEventMonitor.pageView();
    });
    
})();