import childProcess from 'child_process';
import log from 'fancy-log';
import { argv as values } from 'yargs';

export module Utilities {

    function toBoolean(value: any, defaultValue: boolean = false) {
        return defaultValue ? value !== false : !!value;
    }

    export function gulpArgv(): { [index: string]: boolean | string } {
        return {
            prod: toBoolean(values['prod']),
            verbose: toBoolean(values['verbose']),
            junit: toBoolean(values['junit']),
            expandCss: toBoolean(values['expandcss']),
            target: values['target'] as string,
            debug: toBoolean(values['debug']),
            styles: toBoolean(values['styles']),
            resources: toBoolean(values['resources']),
            core: toBoolean(values['core']),
            angular: toBoolean(values['angular']),
            app: toBoolean(values['app']),
            devGuide: toBoolean(values['devguide']),
            fix: toBoolean(values['fix']),
            version: values['V'] as string,
            icon: values['icon'] as string,
            license: values['license'] as string,
            company: values['company'] as string,
            copyright: values['copyright'] as string,
            iconUrl: values['iconUrl'] as string,
            targetPath: values['targetPath'] as string
        };
    }

    export function exportFunctions(context: any, gulpModule: any): void {
        for (const func in gulpModule) {
            if (gulpModule.hasOwnProperty(func)) {
                context[func] = gulpModule[func];
            }
        }
    }

    export function ng(cb, args, options = {}, codeHandler = null, logIdentifier = '') {
        log(`${logIdentifier} - ng`, args.join(' '));
        const errors = [];
        const cmd = childProcess.spawn('ng.cmd', args, { ...options, shell: true });

        cmd.stdout.on('data', function (data) { log(`${logIdentifier} - ${data.toString().trim()}`); });

        cmd.stderr.on('data', function (data) {
            const message = data.toString().trim();
            if (message.toUpperCase().startsWith('ERROR')) {
                log.error(`${logIdentifier} - ${message}`);
                errors.push(`${logIdentifier} - ${message}`);
            } else {
                log(`${logIdentifier} - ${message}`);
            }
        });
    
        cmd.on('exit', function (code) {
            if (codeHandler) {
                const codeError = codeHandler(code);
                if (codeError) {
                    errors.push(codeError);
                }
            }
    
            log(`${logIdentifier} - Process exited with code ${code}`);
            finalize();
        });

        cmd.on('error', function (err) {
            log.error(`${logIdentifier} - ${err.message}`);
            errors.push(`${logIdentifier} - ${err.message}`);
            finalize();
        });
    
        cmd.on('close', function (code) {
            log(`${logIdentifier} - Process closed with code ${code}`);
            finalize();
        });

        const timeout = setTimeout(() => {
            cmd.kill('SIGKILL');
            log(`${logIdentifier} - Timeout on the process.`);
            finalize();
        }, options['timeout'] || 300000);

        function finalize() {
            clearTimeout(timeout);
            if (errors.length > 0) {
                cb(errors.join('\n'));
            } else {
                cb();
            }
        }
    }
}
