#!/usr/bin/env node
'use strict'
const uiPath = __dirname+'/..'
const fs = require('fs');
const { execSync } = require("child_process");

function squeeze(configFile) {
    const appConfig = require(uiPath+'/app/config/'+configFile);
    if(!appConfig.squeeze) return

    let scripts4IndexPage = []
    let styles4IndexPage = []
    for(let packDefinition of appConfig.squeeze.packages) {
        let src='', buf=''; 
        for(let fname of packDefinition.sources){
            try{ src = fs.readFileSync(uiPath+fname,'utf8') }
            catch(err) { 
                console.error(`Could not read file :${uiPath+fname} ... skipped !`) 
                // Uncomment to stop the pipeline on any missed file 
                // or, as sparc will still late-load it anyway if absent, be cool)
                // process.exit(1)
            }
            buf += '\n'+src
            console.log(`Squeezing ${fname} in ${packDefinition.target}`)
        }    
        let ext = packDefinition.target.toLowerCase().substring(packDefinition.target.lastIndexOf('.'))
        if(['.js','.css'].indexOf(ext)<0) {
            console.error(`Unknown file type "${ext}" Skipped !`)
            continue
        }

        try {
            fs.writeFileSync(uiPath+'/squeezed/'+packDefinition.target, buf);

            if(packDefinition.minify) {
                if(ext == '.js') minifyScript(packDefinition.target, packDefinition.mangle) // BEFORE eventual gzipping !!
                else if(ext == '.css') minifyCss(packDefinition.target) // BEFORE eventual gzipping !!
            }
                 
            let endTarget = ''            
            if(packDefinition.compressed) {
                // we gzip in place, no need to cleanup original file
                endTarget = gzip(packDefinition.target)                
            } else { 
                // cleanup eventual gzipped
                delFile(`${uiPath}/squeezed/${packDefinition.target}.gz`)
                endTarget = `/squeezed/${packDefinition.target}`
            }

            if(endTarget && (packDefinition.setIndexPage)) {
                if(ext == '.js') scripts4IndexPage.push(endTarget)
                else if(ext == '.css') styles4IndexPage.push(endTarget)                
            }
            console.log(`Successfully squeezed ${endTarget}\n`)    
        } catch (err) { 
            console.error(`Error while squeezing ${packDefinition.target} : ${err}`)
        }
    }
    buildIndexPage(appConfig.squeeze.indexDefaults, scripts4IndexPage, styles4IndexPage)
}

function minifyScript(file, mangle) {
    console.log(`Minifying ${file} ...`)
    try {
        execSync(`uglifyjs ${uiPath}/squeezed/${file} -c ${mangle ? '-m' : ''} -o ${uiPath}/squeezed/${file}`)
    } catch(err) {
        console.error(`Error while minifying ${file}: ${err}`)
        return('')
    }
    console.log(`${file} minified  ${mangle ? 'and mangled' : ''} OK`)
}

function minifyCss(file) {
    console.log(`Minifying ${file} ...`)
    try {
        execSync(` csso --no-restructure -i ${uiPath}/squeezed/${file} -o ${uiPath}/squeezed/${file}`)
    } catch(err) {
        console.error(`Error while minifying ${file}: ${err}`)
        return('')
    }
    console.log(`${file} minified OK`)
}


function gzip(file) {
    console.log(`Gzipping ${file} ...`)
    try{
        execSync(`gzip -f ${uiPath}/squeezed/${file}`)
    } catch(err) {
        console.error(`Error while gzipping: ${err}`)
        return('')
    }
    console.log(`${file} compressed OK`)
    return(`/squeezed/${file}.gz`)
}

function delFile(file) {
    console.log(`deleting ${file} ...`)    
    fs.stat(file, (err, stats) => {
        fs.unlink(file, err => { });  
     });
}

function buildIndexPage(defaults, scripts, styles) {
    console.log(`editing index.html ...`)  
    let buf
    try{ buf = fs.readFileSync(uiPath+'/index.tpl','utf8') }
    catch {
        console.error('Could not read index.html file...aborting !')
        process.exit(1) // Die in err to stop the pipeline, to preserve a working index !
    }

    const reScripts = /^( *)\{scriptTags\}$/m
    let mtch = buf.match(reScripts)
    let indent = mtch ? mtch[1] : ''
    if(scripts.length<1) scripts = defaults.scripts
    let scriptsBlock = scripts.reduce((acc,x) => acc+`${indent}<script src="${x}"></script>\n`, '')
    scriptsBlock = scriptsBlock.substring(0,scriptsBlock.length-1)

    const reStyles = /^( *)\{cssTags\}$/m
    mtch = buf.match(reStyles)
    indent = mtch ? mtch[1] : ''
    if(styles.length<1) styles = defaults.styles
    let stylesBlock = styles.reduce((acc,x) => acc+`${indent}<link href="${x}" rel="stylesheet" type="text/css">\n`, '')
    stylesBlock = stylesBlock.substring(0,stylesBlock.length-1)

    buf = buf.replace(reScripts, scriptsBlock);
    buf = buf.replace(reStyles, stylesBlock)
    try{ fs.writeFileSync(uiPath+'/index.html', buf) }
    catch(err) {
        console.error(`Could not write index.html file...(${err}) aborting !`)
        process.exit(1) // Die in err to stop the pipeline, to preserve a working index !
    }
    console.log(`Successfully created index.html\n`)
}


if (!fs.existsSync(uiPath+'/squeezed')) fs.mkdirSync(uiPath+'/squeezed')
if(process.argv.length != 3) {
    console.error('Usage : squeeze config file name (no path)')
    process.exit(1);
}
squeeze(process.argv[2])
