// utility to merge defaults
function mergeOption(v, defaultValue){
    if (typeof v === 'undefined' || v === null){
        return defaultValue;
    }else{
        return v;
    }
}

module.exports = {
    // set global options
    parse: function parse(rawOptions, preset){

        // options storage
        const options = {};

        // merge preset
        const opt = Object.assign({}, preset, rawOptions);

        // the max update rate in fps (redraw will only triggered on value change)
        options.throttleTime = 1000 / (mergeOption(opt.fps, 10));

        // the output stream to write on
        options.stream = mergeOption(opt.stream, process.stderr);

        // external terminal provided ?
        options.terminal = mergeOption(opt.terminal, null);

        // clear on finish ?
        options.clearOnComplete = mergeOption(opt.clearOnComplete, false);

        // stop on finish ?
        options.stopOnComplete = mergeOption(opt.stopOnComplete, false);

        // size of the progressbar in chars
        options.barsize = mergeOption(opt.barsize, 40);

        // position of the progress bar - 'left' (default), 'right' or 'center'
        options.align = mergeOption(opt.align, 'left');

        // hide the cursor ?
        options.hideCursor = mergeOption(opt.hideCursor, false);

        // disable linewrapping ?
        options.linewrap = mergeOption(opt.linewrap, false);

        // glue sequence (control chars) between bar elements ?
        options.barGlue = mergeOption(opt.barGlue, '');

        // bar chars
        options.barCompleteChar = mergeOption(opt.barCompleteChar, '=');
        options.barIncompleteChar = mergeOption(opt.barIncompleteChar, '-');

        // the bar format
        options.format = mergeOption(opt.format, 'progress [{bar}] {percentage}% | ETA: {eta}s | {value}/{total}');

        // external time-format provided ?
        options.formatTime = mergeOption(opt.formatTime, null);

        // external value-format provided ?
        options.formatValue = mergeOption(opt.formatValue, null);

        // external bar-format provided ?
        options.formatBar = mergeOption(opt.formatBar, null);

        // the number of results to average ETA over
        options.etaBufferLength = mergeOption(opt.etaBuffer, 10);

        // automatic eta updates based on fps
        options.etaAsynchronousUpdate = mergeOption(opt.etaAsynchronousUpdate, false);

        // progress calculation relative to start value ? default start at 0
        options.progressCalculationRelative = mergeOption(opt.progressCalculationRelative, false);

        // allow synchronous updates ?
        options.synchronousUpdate = mergeOption(opt.synchronousUpdate, true);

        // notty mode
        options.noTTYOutput = mergeOption(opt.noTTYOutput, false);

        // schedule - 2s
        options.notTTYSchedule = mergeOption(opt.notTTYSchedule, 2000);
        
        // emptyOnZero - false
        options.emptyOnZero = mergeOption(opt.emptyOnZero, false);

        // force bar redraw even if progress did not change
        options.forceRedraw = mergeOption(opt.forceRedraw, false);

        // automated padding to fixed width ?
        options.autopadding = mergeOption(opt.autopadding, false);

        // stop bar on SIGINT/SIGTERM to restore cursor settings ?
        options.gracefulExit = mergeOption(opt.gracefulExit, false);

        return options;
    },

    // derived options: instance specific, has to be created for every bar element
    assignDerivedOptions: function assignDerivedOptions(options){
        // pre-render bar strings (performance)
        options.barCompleteString = options.barCompleteChar.repeat(options.barsize + 1);
        options.barIncompleteString = options.barIncompleteChar.repeat(options.barsize + 1);

        // autopadding character - empty in case autopadding is disabled
        options.autopaddingChar = options.autopadding ? mergeOption(options.autopaddingChar, '   ') : '';

        return options;
    }
};