const csv = require('fast-csv');

class CSVStreamParser {

    constructor(attrMap) {
        this.attrMap = attrMap;
    }

    parse(input) {
        const records = [];
        return new Promise((resolve, reject) => {
            let headers;
            const parser = csv()
                .on('data', data => {
                    if (!headers) {
                        headers = this.parseHeaders(data);
                    } else {
                        const record = this.parseRecord(data, headers);
                        records.push(record);
                    }
                })
                .on('error', error => reject(error))
                .on('end', () => {
                    resolve(records);
                });

            input.pipe(parser);
        });
    }

    parseHeaders(data) {
        return data.map(name => name.toLowerCase());
    }

    parseRecord(data, headers) {
        const record = {};
        let errors = undefined;

        for (let i = 0; i < headers.length; i++) {
            const idx = headers[i];
            const value = data[i];
            const attr = this.attrMap[idx];
            
            // only map columns that are known
            if (attr) {
                if(typeof attr === 'object'){
                    record[attr.attrName] = value;
                    errors = this.validateAttr(attr, value);
                } else {
                    record[attr] = value;
                }
            }
        }
        return { errors, record };
    }

    validateAttr(attr, value) {
        if(attr.validation){
            const validationResult = attr.validation.validate(value);
            if(validationResult.error) {
                return { attrName: attr.attrName, error: validationResult.error.message }
            }
        }
    }

}

module.exports = CSVStreamParser;