const {app} = require('electron');
const log = require('electron-log');
const path = require('path');
const fs = require('fs');
const moment = require('moment');

const getParams = require('../get-params');

const getInfoDataFilePath = async () => {
    try {
        const {savedDataPath} = await getParams('savedDataPath');
        const filename = 'info-data.json';
        const filePath = path.join(savedDataPath, filename);

        if ( !fs.existsSync(savedDataPath) ) {
            fs.mkdirSync(savedDataPath);
        }

        if ( !fs.existsSync(filePath) ) {
            const basicData = {
                last_update: {
                    _ads: '',
                    _info: '',
                    _button: ''
                },
                ip: '',
                main_ip: '',
                g_volume: 0,
                filenames: {
                    _ads: '',
                    _info: '',
                    _button: ''
                }
            };

            fs.writeFileSync(filePath, JSON.stringify(basicData));
        }

        return filePath;
    } catch (e) {
        log.error('mod:data-controller/getInfoDataFilePath broken', e);

        return '';
    }
};

const updateInfoAndGetWithBroadcasts = async (data) => {
    try {
        if ( !data || typeof data !== 'object' ) {
            log.error('mod:data-controller/updateInfoAndGetWithBroadcasts', 'no data or data not object');
            return false;
        } else if ( !data['last_update'] || typeof data['last_update'] !== 'object' ) {
            log.error('mod:data-controller/updateFilenames', 'data not have last_update or last_update not object');
            return false;
        }

        const infoData = await getInfoData();
        const newInfoData = JSON.parse(JSON.stringify(infoData));
        let broadcasts = {
            _ads: false,
            _info: false,
            _button: false
        };
        const promises = [];

        data['last_update'].forEach((updDate, updDateIndex) => promises.push(new Promise(async (resolve) => {
            let fileEnd = null;

            switch ( updDateIndex ) {
                case(0): fileEnd = '_ads'; break;
                case(1): fileEnd = '_info'; break;
                case(2): fileEnd = '_button'; break;
            }

            if ( !fileEnd ) {
                return resolve();
            }

            const clear = () => {
                broadcasts[fileEnd] = false;
                newInfoData.last_update[fileEnd] = '';
                newInfoData.filenames[fileEnd] = '';
            };

            if ( !moment(updDate).isValid() ) {
                clear();

                return resolve();
            }

            const lastUpdate = parseInt(moment(updDate).format('YYYYMMDDHHmmss'), 10);

            if ( !lastUpdate ) {
                clear();

                return resolve();
            }

            const broadcastFilename = lastUpdate + fileEnd + '.json';

            broadcasts[fileEnd] = await checkAndSaveBroadcast(data, fileEnd, broadcastFilename);

            if ( broadcasts[fileEnd] ) {
                newInfoData.last_update[fileEnd] = updDate;
                newInfoData.filenames[fileEnd] = broadcastFilename;
            }

            resolve();
        })));

        await Promise.all(promises);

        if ( data['g_volume'] || data['g_volume'] === 0 ) {
            newInfoData.g_volume = data['g_volume'];
        }

        if ( data['ip'] ) {
            newInfoData.ip = data['ip'];
        }

        if ( data['main_ip'] ) {
            newInfoData.main_ip = data['main_ip'];
        }

        return {
            broadcasts: broadcasts,
            infoData: newInfoData
        };
    } catch (e) {
        log.error('mod:data-controller/updateInfoAndGetWithBroadcasts broken', e);

        return {
            broadcasts: {},
            infoData: {}
        };
    }
};

const getInfoData = async () => {
    try {
        const filePath = await getInfoDataFilePath();
        const data = (filePath ? fs.readFileSync(filePath) : null);

        return (data ? JSON.parse(data) : {});
    } catch (e) {
        log.error('mod:data-controller/getInfoData broken', e);

        return {};
    }
};

const getInfoDataWithBroadcasts = async () => {
    try {
        const {savedDataPath} = await getParams('savedDataPath');
        const infoData = await getInfoData();
        const broadcasts = {};

        for ( let key in infoData.filenames ) {
            const filePath = (infoData.filenames[key] ? path.join(savedDataPath, infoData.filenames[key]) : false);
            const exists = (filePath ? fs.existsSync(filePath) : false);

            broadcasts[key] = false;

            if ( filePath && exists ) {
                broadcasts[key] = JSON.parse(fs.readFileSync(filePath));
            } else if ( filePath && !exists ) {
                log.error('mod:data-controller/getInfoDataWithBroadcasts', 'file not found: '+ filePath);
            }
        }

        return {
            broadcasts: broadcasts,
            infoData: infoData
        };
    } catch (e) {
        log.error('mod:data-controller/getInfoDataWithBroadcasts broken', e);

        return {
            broadcasts: {},
            infoData: {}
        };
    }
};

const checkAndSaveBroadcast = async (data, ending, filename) => {
    try {
        if ( !data || !ending || !filename ) {
            log.error('mod:data-controller/checkAndSaveBroadcast', 'not send data, ending or filename');
            return false;
        }

        const bcEnd = (ending === '_ads' ? '' : ending);

        if ( !data || !data.device || !data.device.ingroup || !data.device.ingroup['group_broadcasts'+ bcEnd] ) {
            log.error('mod:data-controller/checkAndSaveBroadcast', 'bad data');
            return false;
        } else if ( !data.device.ingroup['group_broadcasts'+ bcEnd][0] ) {
            log.error('mod:data-controller/checkAndSaveBroadcast', 'no data...group_broadcasts.[]');
            return false;
        } else if ( !data.device.ingroup['group_broadcasts'+ bcEnd][0].clear_broadcast ) {
            log.error('mod:data-controller/checkAndSaveBroadcast', 'no data....clear_broadcast');
            return false;
        }

        const {savedDataPath} = await getParams('savedDataPath');
        const filePath = path.join(savedDataPath, filename);
        const broadcast = data.device.ingroup['group_broadcasts'+ bcEnd][0].clear_broadcast;

        if ( !fs.existsSync(filePath) ) {
            fs.writeFileSync(filePath, JSON.stringify(broadcast));
        }

        return broadcast;
    } catch (e) {
        log.error('mod:data-controller/checkAndSaveBroadcast broken', e);

        return null;
    }
};

const clearLastUpdateFromInfoDataFile = async () => {
    try {
        const filePath = await getInfoDataFilePath();
        const infoData = await getInfoData();

        infoData.last_update = {
            _ads: '',
            _info: '',
            _button: ''
        };

        fs.writeFileSync(filePath, JSON.stringify(infoData));
    } catch (e) {
        log.error('mod:data-controller/clearLastUpdateFromInfoDataFile broken', e);
    }
};

const updateInfoData = async (data) => {
    try {
        const filePath = await getInfoDataFilePath();
        const infoData = await getInfoData();

        infoData.last_update = data['last_update'];
        infoData.ip = data['ip'];
        infoData.main_ip = data['main_ip'];
        infoData.g_volume = data['g_volume'];
        infoData.filenames = data['filenames'];

        fs.writeFileSync(filePath, JSON.stringify(infoData));
    } catch (e) {
        log.error('mod:data-controller/updateInfoData broken', e);
    }
};

module.exports = {
    getInfoDataFilePath: getInfoDataFilePath,
    updateInfoAndGetWithBroadcasts: updateInfoAndGetWithBroadcasts,
    getInfoData: getInfoData,
    getInfoDataWithBroadcasts: getInfoDataWithBroadcasts,
    clearLastUpdateFromInfoDataFile: clearLastUpdateFromInfoDataFile,
    updateInfoData: updateInfoData
};
