var TWFR = window.twfr = window.TWFR = new function() {
    var targets = [];

    function findFrame(target) {
        var data = {};
        if (target instanceof HTMLIFrameElement) {
            data.iframe = target;
            data.window = target.contentWindow;
        } else {
            data.window = target.window || target;
        }
        if (data.window === self) { return {}; }
        for (var i=0, l=targets.length; i<l; i++) {
            if (targets[i].iframe && targets[i].iframe.contentWindow === data.window) {
                // sometimes not set initially
                targets[i].window = targets[i].iframe.contentWindow;
            }
            if (targets[i].window === data.window) {
                if (!targets[i].iframe) {
                    var iframes = document.querySelectorAll('iframe');
                    for (var j=0, k=iframes.length; j<k; j++) {
                        if (iframes[j].contentWindow === data.window) {
                            targets[i].iframe = iframes[j];
                            break;
                        }
                    }
                }
                return targets[i];
            }
        }
        if (data.window === window) { return {}; }
        data.notYetRegistered = true;
        return data;
    }
    this.findFrame = findFrame;

    this.listFrames = function() { return targets; }

    this.regSender = function(target) {
        var data = findFrame(target);
        if (!data.iframe && (!data.window || !data.window.self)) { return {}; }
        if (data.notYetRegistered) {
            delete data.notYetRegistered;
            //data.opener = data.window.opener;
            data.history = [];
            data.index = targets.length;
            targets.push(data);
        }
        if (data.iframe && !data.window) {
            data.window = data.iframe.contentWindow;
            targets[data.index] = data;
        }
        return data;
    };

    /* Creating Frames */
    this.domFrame = function(url, attributes, style) {
        var iframe = document.createElement('iframe')
        iframe.src = url;
        if (!style && (attributes || {}).style) {
            style = attributes.style;
            attributes.style = null;
        }
        for (var item in (attributes || {})) {
            if (!attributes.hasOwnProperty(item)) continue;
            iframe.setAttribute(item, attributes[item]);
            iframe[item] = attributes[item];
        }
        for (var item in (style || {})) {
            if (!attributes.hasOwnProperty(item)) continue;
            iframe.style[item] = attributes[item];
        }
        this.regSender(iframe);
        return iframe;
    };

    this.writeFrame = function(url, attributes, style) {
        var iframe = this.domFrame(url, attributes, style);
        var scriptTag = null !== document.getElementById('twl-mobile-560') ? document.getElementById('twl-mobile-560') : document.getElementById('twl-wp-560');

        if (scriptTag) {
            scriptTag.parentNode.appendChild(iframe);
        }

        return iframe;
    };

    this.getIframUrlParams = function(urlQuery) {
        var parentUrlParams = new URLSearchParams(urlQuery);
        var iFrameUrlParam = new URLSearchParams();

        for (let p of parentUrlParams) {
            if (p[0].match(/(mtm_campaign|mtm_cid|mtm_source|mtm_medium|mtm_content|mtm_kwd|utm_source|utm_medium|utm_campaign|utm_content|utm_term|fbclid|gclid|msclkid)/)) {
                iFrameUrlParam.set(p[0],p[1]);
            }

            if (p[0].match(/(tx_networks|tx_data_units|tx_phone_units|tx_contract_period|tx_payment|tx_download|tx_technologies|tx_mnp_req|tx_data_auto_incl|tx_esim_req|tx_sms_flat_req|tx_special_offers_req|tx_is_checkout_req|tx_is_price_stable_req|tx_incl_young|tx_phone)/)) {
                iFrameUrlParam.set(p[0].replace('tx_', ''),p[1]);
            }
        }

        var iFrameUrlParamString =  iFrameUrlParam.toString();

        return (0 < iFrameUrlParamString.length ? '&' : '') + iFrameUrlParamString;
    }

    /* History */
    this.addHistory = function(target, direction, command, params) {
        var data = {
            target: target,
            direction: direction,
            command: command,
            params: params,
            time: new Date(),
        };
        targets[target.index].history.push(data);
        if (this.onHistoryEntry) {
            try {
                this.onHistoryEntry(data);
            } catch (e) {
            }
        }
    };

    /* Command Management */
    this.commands = {}; // global commands, allowed from all senders
    this.commands.scroll = function (target, position) {
        var element = document.getElementById("twl-mobile-iframe-560");
        var top = element.getBoundingClientRect().top - document.documentElement.getBoundingClientRect().top;

        window.scrollTo({
            top: top + parseInt(position) - 10,
            behavior: 'smooth'
        });
    };
    this.commands.resize = function(target, size) {
        size = size.split('x');
        for (var i=0, l=size.length; i<l; i++) {
            if (size[i].indexOf('%') < 0) {
                size[i] += 'px';
            }
        }
        if (size.length === 1) {
            target.iframe.style.height = size[0];
        } else {
            target.iframe.style.width  = size[0];
            target.iframe.style.height = size[1];
        }
    };
    var targetCommands = {}; // target-individual commands
    this.regCmd = function(target, command, callback) {
        var commandList;
        if (typeof target === 'string' && typeof command === 'function') {
            // no target specified, so it's a global command
            callback = command;
            command = target;
            commandList = this.commands;
        } else {
            // target specified, so it's an individual command
            var data = findFrame(target);
            commandList = targetCommands[data.index] = targetCommands[data.index] || {};
        }
        commandList[command] = callback;
    };

    /* Communication */
    this.sendMsg = function(command, params, target) {
        if (typeof target === 'undefined') {
            target = params;
            params = undefined;
        }

        target = this.regSender(target);
        if (target.notYetRegistered) {
            return;
        }
        if (!target.window || !target.window.postMessage) {
            return;
        }
        if (command.indexOf('=') >= 0) {
            params = command.substring(command.indexOf('=')+1);
            command = command.substring(0, command.indexOf('='));
        }
        var data = {
            originator: 'twfr',
            command: command,
            params: params
        };
        target.window.postMessage(JSON.stringify(data), '*');
        this.addHistory(target, 1, command, params);
    };

    /* Initialization */
    this.listen = function() {
        if (this.initialized) { return; }
        window.addEventListener('message', (function(event) {
            try {
                var data = JSON.parse(event.data);
                if (data.originator !== 'twfr') { throw new Error('JSON msg not from TWFR'); }
                if (!data.command) { throw new Error('TWFR msg has no cmd'); }
            } catch (e) {
                // message not valid / no message from TWFR
                return;
            }
            var sender = findFrame(event.source);
            if (sender.notYetRegistered) {
                return;
            }
            var command = (targetCommands[sender.index] && targetCommands[sender.index].hasOwnProperty(data.command)) ? targetCommands[sender.index][data.command] : this.commands[data.command];
            if (typeof command === 'function') {
                try {
                    command.bind({data:data, sender:sender, event:event})(sender, data.params);
                } catch (e) {
                    console.log('cmd not executable', command, data, event, e);
                }
                this.addHistory(sender, -1, data.command, data.params);
            } else {
                console.log('cmd not allowed', command, sender, data, event);
            }
        }).bind(this), false);
        this.initialized = true;
    };

    this.init = function() {
        var iframes = document.querySelectorAll('[data-twfr-register="true"]');

        for (var i=0, l=iframes.length; i<l; i++) {
            TWFR.regSender(iframes[i]);
        }

        this.listen();
    }

    if (document.readyState !== 'loading') {
        this.init();
    } else {
        document.addEventListener('DOMContentLoaded', (function() {
            this.init();
        }).bind(this), false);
    }
};

(function (twfr) {
    if (twfr = (twfr || TWFR)) {
        var url = 'https://www.tariffuxx.de/tools/twl-mobile-frame?tool_id=560' + twfr.getIframUrlParams(window.location.search);
        var attr = {
            scrolling: 'no',
            height: '1024',
            width: '100%',
            id: 'twl-mobile-iframe-560',
            frameborder: '0',
            border: '0',
            marginwidth: '0',
            marginheight: '0',
            background: 'transparent',
            allowtransparency: 'true',
            title: 'Tarifvergleich'
        };
        twfr.writeFrame(url, attr);
    }
}());