const { spawn } = require('child_process');
const events = require('events');
const emitter = new events.EventEmitter();
const fs = require('fs');
const fse = require('fs-extra');
const path = require('path');
const axios = require('axios');
const envfile = require('envfile');
const AdmZip = require('adm-zip');
const mongoose = require('mongoose');

const posFolder = 'C:/PointOfSales';
const posBackendFolder = 'C:/PointOfSales/POSBackend';
const posFiles = 'C:/PointOfSales/POSFiles';
const posFrontendFolder = 'C:/PointOfSales/POSFrontend';
const configFile = envfile.parse(fs.readFileSync(path.join(posBackendFolder, 'configs', '.env')));

// REMOVE OLD LIT POS SOFTWARE DATA FILES
const dataFolders = [
    { path: path.join(posFiles, 'actionList'), action: 'recursive' },
    { path: path.join(posFiles, 'distribution'), action: 'recursive' },
    { path: path.join(posFiles, 'documents'), action: 'recursive' },
    { path: path.join(posFiles, 'transactions', 'corrupted'), action: 'files' },
    { path: path.join(posFiles, 'transactions', 'sent'), action: 'recursive' },
    { path: path.join(posFiles, 'transactions', 'unknown'), action: 'files' },
    { path: path.join(posFiles, 'transactions', 'unsent'), action: 'files' }
];
const fileTypes = ['OPER', 'SUMM'];
for (let i=0; i<dataFolders.length; i++) {
    switch (dataFolders[i].action) {
        case 'recursive':
            fse.emptyDirSync(dataFolders[i].path);
        break;
        case 'files':
            const files = fs.readdirSync(dataFolders[i].path);
            for (let f=0; f<files.length; f++) {
                if (fileTypes.some((type) => files[f].startsWith(type))) {
                    fs.unlinkSync(path.join(dataFolders[i].path, files[f]));
                } else {
                    fs.renameSync(path.join(dataFolders[i].path, files[f]), path.join(process.cwd(), '../POSFiles', files[f]));
                }
            }
        break;
    }
}

// REMOVE OLD LIT POS SOFTWARE FILES
const posBackendSrcFolder = fs.readdirSync(posBackendFolder);
const dontRemove = ['configs', 'daemon', 'node_modules', 'package-lock.json'];
for (let i=0; i<posBackendSrcFolder.length; i++) {
    if (!dontRemove.includes(posBackendSrcFolder[i])) {
        const stat = fs.statSync(posBackendSrcFolder[i]);
        if (stat && stat.isDirectory()) {
            fs.rmSync(path.join(posBackendFolder, posBackendSrcFolder[i]), { recursive: true });
        } else {
            fs.unlinkSync(path.join(posBackendFolder, posBackendSrcFolder[i]));
        }
    }
}
fse.emptyDirSync(path.join(posFrontendFolder));

// REMOVE OLD LIT POS SOFTWARE LOGS
fs.truncateSync(path.join(posBackendFolder, 'daemon', 'litpossoftware.err.log'));
fs.truncateSync(path.join(posBackendFolder, 'daemon', 'litpossoftware.out.log'));
fs.truncateSync(path.join(posBackendFolder, 'daemon', 'litpossoftware.wrapper.log'));

// UPDATE DATABASE NEW LIT POS SOFTWARE VERSION
(async () => {
    const databaseName = (typeof process.argv[2] != 'undefined') ? process.argv[2] : 'dev';
    const softwareVersion = (typeof process.argv[3] != 'undefined') ? process.argv[3] : '26.04.03';

    if (databaseName && softwareVersion) {
        const connection = await mongoose.connect('mongodb://localhost:27017/litpos' + databaseName, { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true, useFindAndModify: false, serverSelectionTimeoutMS: 60000 });
        const posModel = mongoose.model('Pos', new mongoose.Schema({ deviceId: String, appVersion: String }));
        const pos = await posModel.findOne({});

        console.log('Updated ' + databaseName + ' from ' + pos.appVersion + ' to ' + softwareVersion);

        await posModel.findOneAndUpdate({deviceId: configFile.POS_DEVICE_ID}, { appVersion: softwareVersion });

        connection.disconnect();
    }
})();

// DOWNLOAD LIT POS SOFTWARE
(async () => {
    const litPosSoftwareZipFile = await axios.get('https://pos.klemenb.si/assets/pos/POS_software.zip', {headers: {'Content-Type': 'application/zip'}, responseType: 'arraybuffer'});
    const litPosSoftwareFiles = new AdmZip(litPosSoftwareZipFile.data);
    litPosSoftwareFiles.extractAllTo(path.join(posFolder, 'new'), true);
})();
/*const litPosSoftwareZipFileVersion = axios.get('https://demo.lit-transit.com/POSinstallation/assets/pos').then((res) => {
    const files = res.data.match(/<a\s+(?:[^>]*?\s+)?href="([^"]*)"/g).filter((file) => file.includes('pos_software_pkg_') && file.includes('.zip'));
    process.env.POS_APP_VERSION = files[files.length-1].match(/href="([^"]*)/)[1].split('pos_software_pkg_')[1].split('.zip')[0];
    // download latest version of LIT POS software ( https://demo.lit-transit.com/POSinstallation/assets/pos/pos_software_pkg_26.01.01.zip )
    const litPosSoftwareZipFile = axios.get('https://demo.lit-transit.com/POSinstallation/assets/pos/pos_software_pkg_'+process.env.POS_APP_VERSION+'.zip', {headers: {'Content-Type': 'application/zip'}, responseType: 'arraybuffer'}).then((res) => {
        const litPosSoftwareFiles = new AdmZip(res.data);
        litPosSoftwareFiles.extractAllTo(posFolder, true);
        emitter.emit('downloadLitPosSoftware-done');
    });
});*/

// MOVE LIT POS SOFTWARE FILES
emitter.on('downloadLitPosSoftware-done', () => {
    const litPosSoftwareFilesFolder = 'pos_software_pkg_'+process.env.POS_APP_VERSION;
    // copy and remove files
    fse.copy(path.join(posFolder, litPosSoftwareFilesFolder, 'POSBackend'), posBackendFolder, {filter: (file) => {
            let notCopyFileList = [];

            if (!['kuwait'].includes(configFile.CLIENT_NAME)) {
                notCopyFileList.push(path.join(posFolder, litPosSoftwareFilesFolder, 'assets', 'templates', 'template_kuwait.json'));
            }

            if (configFile.CLIENT_SECURE_ACCESS_MODULE != 'true') {
                notCopyFileList.push(path.join(posFolder, litPosSoftwareFilesFolder, 'libs', 'sam-smart-card'));
            }

            return !notCopyFileList.includes(file) ? true : false;
        }}, (err) => {
    });
    fse.copy(path.join(posFolder, litPosSoftwareFilesFolder, 'POSFrontend', 'POSFrontend'), path.join(posFrontendFolder, 'POSFrontend'), {filter: (file) => {
            let notCopyFileList = [];

            if (file.includes('client\\') && !file.includes(configFile.CLIENT_NAME)) {
                notCopyFileList.push(file);
            }

            return !notCopyFileList.includes(file) ? true : false;
        }}, (err) => {
    });
    fs.rmSync(path.join(posFolder, litPosSoftwareFilesFolder), { recursive: true });
    emitter.emit('moveLitPosSoftware-done');
});

// INSTALL LIT POS SOFTWARE DEPENDENCIES
emitter.on('moveLitPosSoftware-done', () => {
    // install dependencies ( npm install )
    const npmLitPosSoftware = spawn('npm.cmd', ['install'], {cwd: posBackendFolder});
    npmLitPosSoftware.on('close', (code) => {
        if (parseInt(code) !== 0) { console.log(`npmLitPosSoftware exited with code ${code}`); }
        emitter.emit('npmLitPosSoftware-done');
    });
});

// LINK NODE WINDOWS
emitter.on('npmLitPosSoftware-done', () => {
    // link node-windows ( npm link node-windows )
    const linkNodeWindows = spawn('npm.cmd', ['link', 'node-windows'], {cwd: posBackendFolder});
    linkNodeWindows.on('close', (code) => {
        if (parseInt(code) !== 0) { console.log(`linkNodeWindows exited with code ${code}`); }
        emitter.emit('linkNodeWindows-done');
    });
});

// RESTART LIT POS SOFTWARE BACKEND
emitter.on('linkNodeWindows-done', () => {
    // restart application ( npm run service )
    const nwLitPosSoftware = spawn('npm.cmd', ['run', 'service'], {cwd: posBackendFolder});
    nwLitPosSoftware.on('close', (code) => {
        if (parseInt(code) !== 0) { console.log(`nwLitPosSoftware exited with code ${code}`); }
        emitter.emit('nwLitPosSoftware-done');
    });
});

//emitter.on('nwLitPosSoftware-done', () => {
    console.log('\nUpdate is completed.');
//});
