(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/common/http'), require('@wm/mobile/components/basic'), require('@wm/mobile/components/basic/search'), require('@wm/mobile/components/containers/segmented-control'), require('@wm/mobile/components/data/media-list'), require('@wm/mobile/components/device/barcode-scanner'), require('@wm/mobile/components/device/camera'), require('@wm/mobile/components/input/file-upload'), require('@wm/mobile/components/page'), require('@wm/mobile/components/page/left-panel'), require('@wm/mobile/components/page/mobile-navbar'), require('@wm/mobile/components/page/tab-bar'), require('@awesome-cordova-plugins/file/ngx'), require('@wm/core'), require('@wm/mobile/core')) :
    typeof define === 'function' && define.amd ? define(['exports', '@angular/core', '@angular/common/http', '@wm/mobile/components/basic', '@wm/mobile/components/basic/search', '@wm/mobile/components/containers/segmented-control', '@wm/mobile/components/data/media-list', '@wm/mobile/components/device/barcode-scanner', '@wm/mobile/components/device/camera', '@wm/mobile/components/input/file-upload', '@wm/mobile/components/page', '@wm/mobile/components/page/left-panel', '@wm/mobile/components/page/mobile-navbar', '@wm/mobile/components/page/tab-bar', '@awesome-cordova-plugins/file/ngx', '@wm/core', '@wm/mobile/core'], factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.wm = global.wm || {}, global.wm.mobile = global.wm.mobile || {}, global.wm.mobile.runtime = global.wm.mobile.runtime || {}, global.wm.mobile.runtime.dynamic = {}), global.ng.core, global.ng.common.http, global.wm.mobile.components.basic, global.wm.mobile.components.basic.search, global.wm.mobile.components.containers.segmentedcontrol, global.wm.mobile.components.data.medialist, global.wm.mobile.components.device.barcodescanner, global.wm.mobile.components.device.camera, global.wm.mobile.components.input.fileupload, global.wm.mobile.components.page, global.wm.mobile.components.page.leftpanel, global.wm.mobile.components.page.mobilenavbar, global.wm.mobile.components.page.tabbar, global.awesomeCordova.plugins, global.wm.core, global.wm.mobile.core));
})(this, (function (exports, i0, http, basic, search, segmentedControl, mediaList, barcodeScanner, camera, fileUpload, page, leftPanel, mobileNavbar, tabBar, i3, i1, i2) { 'use strict';

    function _interopNamespaceDefault(e) {
        var n = Object.create(null);
        if (e) {
            Object.keys(e).forEach(function (k) {
                if (k !== 'default') {
                    var d = Object.getOwnPropertyDescriptor(e, k);
                    Object.defineProperty(n, k, d.get ? d : {
                        enumerable: true,
                        get: function () { return e[k]; }
                    });
                }
            });
        }
        n.default = e;
        return Object.freeze(n);
    }

    var i0__namespace = /*#__PURE__*/_interopNamespaceDefault(i0);
    var i3__namespace = /*#__PURE__*/_interopNamespaceDefault(i3);
    var i1__namespace = /*#__PURE__*/_interopNamespaceDefault(i1);
    var i2__namespace = /*#__PURE__*/_interopNamespaceDefault(i2);

    class LiveSyncInterceptor {
        constructor(app, deviceService, networkService, file) {
            this.app = app;
            this.deviceService = deviceService;
            this.networkService = networkService;
            this.file = file;
            this.urlsToSkip = [];
            this.deployedUrl = '';
            this.localAppUrl = '';
            this.syncAppUrl = '';
            this.urlsToLoadFromLocal = {
                'config.json': 'config.json',
            };
            this.urlsToLoadFromLive = {
                'metadata/app/service-definitions.json': 'services/servicedefs',
                'metadata/app/security-config.json': 'services/security/info'
            };
            this.prefabServicePattern = /^metadata\/prefabs\/.*\/service-definitions.json$/;
            this.isLiveSyncEnabled = false;
            this.settings = {
                enabled: false,
                position: null,
                show: true,
                cordovaPlugins: null
            };
            this.loadSettings();
            this.isLiveSyncEnabled = this.settings.enabled && i1.hasCordova();
            this.deployedUrl = $('meta[name="liveSync.deployedUrl"]').attr('value');
            this.localAppUrl = $('meta[name="liveSync.localAppUrl"]').attr('value');
            this.syncAppUrl = $('meta[name="liveSync.syncAppUrl"]').attr('value');
            this.defineAPI();
            if (!this.isLiveSyncEnabled) {
                this.goToLocalApp();
                if (this.deviceService.isAppConnectedToPreview()) {
                    this.deviceService.whenReady().then(() => {
                        this.deployedUrl = app.deployedUrl;
                        if (!this.networkService.isConnected()) {
                            return;
                        }
                        this.renderUI();
                        if (!this.localAppUrl && !this.settings.cordovaPlugins) {
                            this.getPlugins().then(plugins => {
                                this.settings.cordovaPlugins = plugins;
                                this.saveSettings();
                            });
                        }
                    });
                }
                return;
            }
            if (this.syncAppUrl && this.deployedUrl) {
                this.deviceService.getConfig().baseUrl = this.deployedUrl;
                this.patchSQLite();
                this.patchHistoryApi();
                Object.keys(this.urlsToLoadFromLocal).forEach(k => {
                    this.urlsToLoadFromLocal[k] = this.syncAppUrl + this.urlsToLoadFromLocal[k];
                });
                this.patchApp();
                this.renderUI();
            }
            else {
                window.navigator.splashscreen.hide = () => { };
                this.deployedUrl = app.deployedUrl;
                this.isLiveSyncEnabled = false;
                this.deviceService.whenReady().then(() => {
                    this.networkService.isConnected() && this.launch();
                });
            }
        }
        goToLocalApp() {
            if (this.localAppUrl) {
                location.href = this.localAppUrl;
            }
        }
        defineAPI() {
            window.liveSync = (flag) => {
                if (this.settings.enabled === !!flag
                    || !this.networkService.isConnected()) {
                    return;
                }
                this.settings.enabled = !!flag;
                this.saveSettings();
                setTimeout(() => {
                    window.navigator.splashscreen.show();
                    location.reload();
                }, 100);
            };
        }
        transformPrefabServicedefinitions(url) {
            let isValid = this.prefabServicePattern.test(url), prefabName = '', prefabLoc = 0;
            if (isValid) {
                prefabLoc = 'metadata/prefabs/'.length;
                prefabName = url.substring(prefabLoc, url.indexOf('/', prefabLoc));
                return 'services/prefabs/' + prefabName + '/servicedefs';
            }
            return url;
        }
        intercept(request, next) {
            if (!this.isLiveSyncEnabled) {
                return next.handle(request);
            }
            const deployedUrl = this.app.deployedUrl;
            let url = request.url;
            url = this.urlsToLoadFromLive[url] || this.urlsToLoadFromLocal[url] || url;
            url = this.transformPrefabServicedefinitions(url);
            if (url.startsWith('//')) {
                url = deployedUrl.split('//')[0] + url;
            }
            if (url.indexOf('://') < 0
                || this.urlsToSkip.indexOf(url) >= 0) {
                url = deployedUrl + '/' + url;
            }
            request = request.clone({ url: url });
            return next.handle(request);
        }
        mashUpHtmlFile() {
            const localDir = cordova.file.cacheDirectory;
            return new Promise((resolve, reject) => {
                $.ajax({
                    url: this.deployedUrl + 'index.html',
                    dataType: 'html',
                    success: resolve,
                    error: reject
                });
            }).then((fileContent) => {
                const port = location.port ? ':' + location.port : '';
                let path = this.localAppUrl ||
                    (`${location.protocol}//${location.hostname}${port}${location.pathname}`);
                let cordovaPath = path;
                if (cordovaPath.endsWith('.html')) {
                    const splits = cordovaPath.split('/').slice(0);
                    cordovaPath = splits.slice(0, splits.length - 1).join('/');
                }
                cordovaPath += '/cordova.js';
                const mAppUrl = `${location.protocol}//${location.hostname}${port}${i1.transformFileURI(localDir + 'live-index.html')}`;
                fileContent = fileContent.replace('cordova.js', cordovaPath);
                fileContent = fileContent.replace('<head>', `
            <head>
                <base href="${this.deployedUrl}">
                <meta name="liveSync.deployedUrl" value="${this.deployedUrl}">
                <meta name="liveSync.syncAppUrl" value="${mAppUrl}">
                <meta name="liveSync.localAppUrl" value="${path}">`);
                return this.file.writeFile(localDir, 'live-index.html', fileContent, {
                    replace: true
                }).then(() => mAppUrl);
            });
        }
        getPlugins() {
            return new Promise((resolve, reject) => {
                $.get(this.deployedUrl + 'config.xml').done(function (res) {
                    const plugins = {};
                    $(res).find('plugin').each(function (p) {
                        plugins[$(this).attr('name')] = $(this).attr('spec');
                    });
                    resolve(plugins);
                }).fail(reject);
            });
        }
        hasPluginsChanged() {
            return this.deviceService.whenReady()
                .then(() => this.getPlugins())
                .then(plugins => {
                const pluginsInApk = this.settings.cordovaPlugins || {};
                return !!Object.keys(plugins)
                    .find(k => !pluginsInApk[k] || pluginsInApk[k] !== plugins[k]);
            });
        }
        launch() {
            return this.mashUpHtmlFile()
                .then((filePath) => {
                localStorage.setItem('WM.NetworkService.isConnected', 'true');
                localStorage.setItem('WM.NetworkService._autoConnect', 'true');
                sessionStorage.setItem('debugMode', 'true');
                setTimeout(() => {
                    window.navigator.splashscreen.show();
                    window.location.href = filePath;
                }, 2000);
            });
        }
        patchSQLite() {
            // Offline sql is not supported.
            delete window['SQLitePlugin'];
        }
        patchApp() {
            this.app.reload = () => {
                if (this.networkService.isConnected()) {
                    window.navigator.splashscreen.show();
                    this.launch();
                }
            };
            window['reloadApp'] = this.app.reload;
        }
        patchHistoryApi() {
            const location = this.syncAppUrl;
            const origReplace = window.history.replaceState;
            window.history.replaceState = (state, title, url) => {
                if (url.startsWith('#')) {
                    url = location + url;
                }
                origReplace.call(window.history, state, title, url);
            };
            const origPush = window.history.pushState;
            window.history.pushState = (state, title, url) => {
                if (url.startsWith('#')) {
                    url = location + url;
                }
                origPush.call(window.history, state, title, url);
            };
        }
        loadSettings() {
            const value = sessionStorage.getItem('wm.liveSync.settings');
            try {
                this.settings = value ? JSON.parse(value) : this.settings;
            }
            catch (e) {
                this.saveSettings();
            }
        }
        saveSettings() {
            sessionStorage.setItem('wm.liveSync.settings', JSON.stringify(this.settings));
        }
        renderUI() {
            if (this.settings.enabled) {
                this.hasPluginsChanged().then((changed) => {
                    if (changed) {
                        new DialogComponent({
                            title: 'Require new build',
                            info: 'Cordova Plugins in this app do not match with configuration of project in Studio.' +
                                ' So, new Cordova Build is required for Live Sync to work properly.',
                            iconClass: 'fa fa-warning fa-4x live-sync-warning-icon',
                            actions: [{
                                    title: 'Got it',
                                    primary: true
                                }]
                        }).render();
                    }
                });
            }
            new LiveSyncComponent(this.settings, () => {
                this.saveSettings();
            }).render();
        }
        static { this.ɵfac = function LiveSyncInterceptor_Factory(t) { return new (t || LiveSyncInterceptor)(i0__namespace.ɵɵinject(i1__namespace.App), i0__namespace.ɵɵinject(i2__namespace.DeviceService), i0__namespace.ɵɵinject(i2__namespace.NetworkService), i0__namespace.ɵɵinject(i3__namespace.File)); }; }
        static { this.ɵprov = /*@__PURE__*/ i0__namespace.ɵɵdefineInjectable({ token: LiveSyncInterceptor, factory: LiveSyncInterceptor.ɵfac }); }
    }
    (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0__namespace.ɵsetClassMetadata(LiveSyncInterceptor, [{
            type: i0.Injectable
        }], () => [{ type: i1__namespace.App }, { type: i2__namespace.DeviceService }, { type: i2__namespace.NetworkService }, { type: i3__namespace.File }], null); })();
    class DialogComponent {
        constructor(options) {
            this.options = options;
            this.$ele = $('<div><div>');
        }
        dismiss() {
            this.$ele.remove();
        }
        render() {
            this.$ele = $(`<div class="live-sync-modal live-sync-control">
                    <div class="live-sync-info-container">
                        <span class="${this.options.iconClass}">
                        </span>
                        <label class="live-sync-title">
                            ${this.options.title}
                        </label>
                        <label class="live-sync-description">
                            ${this.options.info}
                        </label>
                        <div class="live-sync-action-panel">
                            ${this.options.actions.map((a) => {
            return a ? `
                                <button
                                    type="button"
                                    class="live-sync-action ${a.primary ? ' live-sync-primary-action' : ''}">
                                        ${a.title}
                                </button>` : '';
        }).join('')}
                        </div>
                    </div>
                </div>
            `);
            $('body').append(this.$ele);
            const _this = this;
            this.$ele.find('.live-sync-action').each(function (index) {
                $(this).bind('click', () => {
                    const action = _this.options.actions[index].action;
                    if (action) {
                        action(_this);
                    }
                    _this.dismiss();
                });
            });
        }
    }
    class LiveSyncComponent {
        constructor(settings, onChange) {
            this.settings = settings;
            this.onChange = onChange;
            this.$ele = $(`<div class="live-sync-control">
            <button class="live-sync-control-btn" type="button">
            </button>
        </div>`);
        }
        setPosition() {
            const menuIcon = this.$ele.find('.live-sync-control-btn');
            const position = this.settings.position;
            if (position) {
                menuIcon.css('left', position.left + 'px');
                menuIcon.css('top', position.top + 'px');
            }
        }
        listenForShowEvent() {
            $('body').bind('touchstart', () => {
                const timerId = setTimeout(() => {
                    this.settings.show = true;
                    this.onChange();
                    this.showConfirmation();
                }, 5000);
                $('body').bind('touchend', () => {
                    clearTimeout(timerId);
                });
            });
        }
        showConfirmation() {
            new DialogComponent({
                title: 'Enable Live Sync?',
                info: 'App UI is pulled from studio. But, offline functionality is turned off.',
                iconClass: 'live-sync-control-icon',
                actions: [{
                        title: 'No',
                        action: () => {
                            this.settings.show = false;
                            this.onChange();
                            this.showHelpInfo();
                        }
                    }, {
                        title: 'Yes',
                        action: () => {
                            window.liveSync(true);
                        },
                        primary: true
                    }]
            }).render();
        }
        ;
        showHelpInfo() {
            new DialogComponent({
                title: '',
                info: 'Tap and hold anywhere for 5 seconds to turn on Live Sync.',
                iconClass: 'live-sync-retrieval-info-icon',
                actions: [{
                        title: 'Got it',
                        primary: true
                    }]
            }).render();
        }
        ;
        renderButton() {
            const menuIcon = this.$ele.find('.live-sync-control-btn');
            this.$ele.on('touchstart', (event) => {
                event.stopPropagation();
                let addClass = true;
                $(document).on('touchmove.liveSync', (event) => {
                    var origEvent = event.originalEvent.touches[0];
                    if (origEvent && origEvent.pageX) {
                        this.settings.position = {
                            left: origEvent.pageX,
                            top: origEvent.pageY
                        };
                    }
                    this.setPosition();
                    if (addClass) {
                        menuIcon.addClass('touched');
                        addClass = false;
                    }
                });
                $(document).one('touchend', (event) => {
                    this.onChange();
                    menuIcon.removeClass('touched');
                    $(document).off('touchmove.liveSync');
                });
            });
            menuIcon.click(() => window.reloadApp());
            $('body').append(this.$ele);
        }
        render() {
            this.setPosition();
            if (this.settings.enabled) {
                this.renderButton();
            }
            else if (this.settings.show) {
                this.showConfirmation();
            }
            this.listenForShowEvent();
        }
    }

    const MOBILE_COMPONENT_MODULES_FOR_ROOT = [
        basic.BasicModule,
        search.SearchModule,
        segmentedControl.SegmentedControlModule,
        mediaList.MediaListModule,
        barcodeScanner.BarcodeScannerModule,
        camera.CameraModule,
        fileUpload.FileUploadModule,
        page.PageModule,
        leftPanel.LeftPanelModule,
        mobileNavbar.MobileNavbarModule,
        tabBar.TabBarModule
    ];
    class MobileRuntimeDynamicModule {
        static { this.ɵfac = function MobileRuntimeDynamicModule_Factory(t) { return new (t || MobileRuntimeDynamicModule)(); }; }
        static { this.ɵmod = /*@__PURE__*/ i0__namespace.ɵɵdefineNgModule({ type: MobileRuntimeDynamicModule }); }
        static { this.ɵinj = /*@__PURE__*/ i0__namespace.ɵɵdefineInjector({ providers: [{
                    provide: http.HTTP_INTERCEPTORS,
                    useClass: LiveSyncInterceptor,
                    multi: true
                }] }); }
    }
    (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0__namespace.ɵsetClassMetadata(MobileRuntimeDynamicModule, [{
            type: i0.NgModule,
            args: [{
                    providers: [{
                            provide: http.HTTP_INTERCEPTORS,
                            useClass: LiveSyncInterceptor,
                            multi: true
                        }]
                }]
        }], null, null); })();

    exports.MOBILE_COMPONENT_MODULES_FOR_ROOT = MOBILE_COMPONENT_MODULES_FOR_ROOT;
    exports.MobileRuntimeDynamicModule = MobileRuntimeDynamicModule;

}));
