const { app, screen, ipcMain, powerSaveBlocker } = require('electron');
const isDev = require('electron-is-dev');
const log = require('electron-log');
const path = require("path");
const fs = require("fs");
const url = require("url");
const moment = require('moment');
const getIp = require('ip');
const os = require('os');

const baseAppName = require('../package.json').name;

const isSubmodule = app.name !== baseAppName;

if (!isSubmodule) {
    require('./modules/logger').init();
    require('./modules/unhandled-errors')();
}

const appIndependent = require('./core/appIndependent.js');
const appSubmodule = require('./core/appSubmodule.js');
const getAppWindow = require('./modules/getAppWindow.js');
const eventNames = require('./configs-constants/eventNames.js');

const { forMain } = eventNames;
const serverPort = 3000;
let win = null;
let interval = 300000;
let pathToDefaultVideo = ''

const initialize = (params = {}) => {
    let configMachine = params?.configMachine || null;
    let configMachinePath = params?.configMachinePath || '';
    win = params?.window || null;
    const htmlFile = params?.htmlFile || 'content.html';
    const appendTo = params?.appendTo || '#module_neuroad';
    const checkEnabling = params?.checkEnabling || function () { return true; };
    interval = params?.interval ? params.interval : interval
    pathToDefaultVideo = params.pathToDefaultVideo || '';
    if (!isSubmodule && !app.requestSingleInstanceLock()) {
        app.quit();
    }

    const emptyFn = () => {};
    const isLowCpu = (os.cpus().length < 4);

    const getMachineConfig = require('./modules/configMachine/getMachineConfig.js');
    const getMacAddress = require('./modules/getMacAddress');
    const checkUpdateDataInfoAndBroadcasts = require('./helpers/check-update-info-data-and-broadcasts');
    const serverWorker = (isLowCpu ? emptyFn : require('./helpers/server-worker'));
    const scheduler = (isSubmodule ? emptyFn : require('./modules/scheduler'));
    const createWindow = (isSubmodule ? emptyFn : require('./core/createWindow.js'));
    const checkTimeIsOffset = (isSubmodule ? emptyFn : require('./core/checkTimeIsOffset.js'));

    const appParams = new Map();
    let isOnline = false;
    let isFirstSwitchToOnline = true;

    moment.locale('en');

    if (!isSubmodule) {
        app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required');
        app.commandLine.appendSwitch('force-color-profile', 'srgb');
        app.commandLine.appendSwitch('ignore-gpu-blacklist', 'true');

        app.allowRendererProcessReuse = false;
    }

    const secondLoop = () => {
        const intervalTime = 1000;
        const counterMax = (isLowCpu ? 1800 : 60);
        let counter = 0;

        let intervalId = setInterval(() => {
            try {
                if ( !win || !configMachine || !configMachine.remote_href ) {// app not init
                    return;
                }

                if (!isSubmodule) {
                    checkTimeIsOffset(intervalTime, (isLowCpu ? 10000 : 1000));
                }

                if (isFirstSwitchToOnline) {
                    return;
                }

                if (counter === counterMax) {
                    counter = 0;

                    checkUpdateDataInfoAndBroadcasts();
                    setTimeout(scheduler, 1000);
                } else {
                    counter += 1;
                }
            } catch (err) {
                clearInterval(intervalId);

                log.error('index:setInterval()', err);
            }
        }, interval);
    };

    const afterPageReady = () => {
        let getMyIpIntervalId = null;

        log.info('dom-ready. app version: '+ app.getVersion());

        powerSaveBlocker.start('prevent-display-sleep');

        if (!configMachine) {
            if (configMachinePath && configMachinePath.endsWith('.json')) {
                configMachine = JSON.parse(fs.readFileSync(configMachinePath, 'utf8'));
            } else {
                configMachine = getMachineConfig(configMachinePath);
            }
        }

        if (configMachine?.remote_href && configMachine.remote_href.indexOf('http') !== 0) {
            configMachine.remote_href = 'http://'+ configMachine.remote_href;
        }

        win.webContents.send('msg',{ type: 'device_orientation', msg: configMachine.device.device_orientation , pathToDefaultVideo: pathToDefaultVideo });
        win.webContents.send('msg',{ type: 'appUserDataPath', msg: app.getPath('userData') });
        win.webContents.send('msg',{ type: 'savedJsonDir', msg: appParams.get('savedData') });
        win.webContents.send('msg',{ type: 'createWebSocket', msg: {href: configMachine.remote_href, conf: configMachine} });
        win.webContents.send('msg',{ type: 'init', msg: true });

        getMyIpIntervalId = setInterval(() => {
            const myIp = getIp.address('public', 'ipv4');

            if (myIp !== '127.0.0.1' && myIp !== '0.0.0.0') {
                clearInterval(getMyIpIntervalId);

                log.info('my ip: '+ myIp);

                appParams.set('ipAddress', myIp);
                appParams.set('macAddress', getMacAddress());

                serverWorker(serverPort);

                if (!isFirstSwitchToOnline) {
                    checkUpdateDataInfoAndBroadcasts();
                }
            }
        }, 333);
    };

    const setIpcMainListeners = function () {
        try {
            ipcMain.on(forMain.pageReady, afterPageReady);
            ipcMain.once(forMain.pageReadyForPlay, secondLoop);

            ipcMain.on('msg', (event, arg) => log.info(arg));

            ipcMain.on('get-param', (paramName) => {
                switch ( paramName ) {
                    case('appConfig'):
                        ipcMain.emit('send-param', configMachine);
                        break;
                    case('appUserData'):
                        ipcMain.emit('send-param', app.getPath('userData'));
                        break;
                    case('savedDataPath'):
                        ipcMain.emit('send-param', appParams.get('savedData'));
                        break;
                    case('uploadsPath'):
                        ipcMain.emit('send-param', path.join(app.getPath('userData'), 'uploads'));
                        break;
                    case('ipAddress'):
                        ipcMain.emit('send-param', appParams.get('ipAddress'));
                        break;
                    case('macAddress'):
                        ipcMain.emit('send-param', appParams.get('macAddress'));
                        break;
                    case('serverPort'):
                        ipcMain.emit('send-param', appParams.get('serverPort'));
                        break;
                    case('appParams'):
                        ipcMain.emit('send-param', appParams);
                        break;
                }
            });

            ipcMain.on(forMain.onlineStatus, (event, arg) => {
                isOnline = arg;

                if ( isOnline ) {
                    appParams.set('ipAddress', getIp.address('public', 'ipv4'));

                    if (isFirstSwitchToOnline) {
                        isFirstSwitchToOnline = false;

                        checkUpdateDataInfoAndBroadcasts();

                        setTimeout(scheduler, 1000);
                    }
                }
            });
        } catch (err) {
            log.error('index:setIpcMainListeners()', err);
        }
    };

    const init = () => {
        try {
            setIpcMainListeners();

            appParams.set('savedData', path.join(app.getPath('userData'), 'data'));
            appParams.set('serverPort', serverPort);
            appParams.set('ipAddress', '');
            appParams.set('macAddress', '');
        } catch (e) {
            log.error('init neuroAd\n', e);
        }
    };

    if (isSubmodule) {
        appSubmodule.setAppListeners();

        if (app.isReady()) {
            init();
            win = win || getAppWindow();
        } else {
            app.once('ready', () => {
                win = win || getAppWindow();
            });
        }
    } else {
        appIndependent.setAppListeners();
        app.once('ready', () => {
            init();
            win = appIndependent.createWin();
        });
    }
};

console.log('=====================', getIp.address('public', 'IPv4'))

module.exports = {
    nadInitMain: initialize,
    nadEventNames: eventNames
};
