/*
 * Nested JSON to CSV parser
 * @Author Manish Yadav
 * @copyright Semusi Technologies Pvt Ltd @2017
 */
var common = require('./../utils/common.js');

let json2csv = {};
(function(json2csv,common){
    json2csv.convert2csv = function(data, isSeparate){
        json2csv.keysData = {HKEYS:[]};
        // validate data param
        if(data){
            // validate data it should be with object or object
            if( (Array.isArray(data) && data.length > 0 )
                    || (Object.keys(data).length > 0 && data.constructor === Object) 
                ){
            
                // check type cast 
                if(Array.isArray(data)){
                    // init csvHeaderKeys variable
                    let csvHeaderKeys = [];
                    let csvDataStr = '';
                    let rows = []
                    // iterate data array
                    data.forEach(function(element){
                        let tmpData = [];
                        let data = "";
                        json2csv.parseJSONObj(element);
                        // get different keys into csv header
                        json2csv.keysData.HKEYS.filter(function(obj) {  if(csvHeaderKeys.indexOf(obj) == -1){ csvHeaderKeys.push(obj);} });
                        csvHeaderKeys.forEach(function(key, index){
                            if(json2csv.keysData[key]){
                                data = json2csv.keysData[key];
                                if (typeof data === "string")
	                                tmpData.push(common.sanitizeString(data));
                                else
                                	tmpData.push(data);
                            }
                            else{
                                tmpData.push("");
                            }
                            // remove special character from csv columns
                            csvHeaderKeys[index] = key.replace(/[`~%!@#$%^&*()|+\-=?;'",<>\{\}\[\]\\\/\s]/gi, '_');
                        }); 
                        rows.push(tmpData);
                        //csvDataStr += tmpData.join(",")+"\n";
                        json2csv.keysData = {HKEYS:[]};
                        
                    });

                    // check all rows columns valude that should be equal
                    rows.forEach(function(tmpData, rowIndex){
                        if(csvHeaderKeys.length > tmpData.length){
                            for(i = tmpData.length; i < csvHeaderKeys.length; i++ ){
                                tmpData.push("");
                            }
                            rows[rowIndex] = tmpData;
                        }
                        csvDataStr += tmpData.join(",")+"\n";
                    })

                    // clear keysData variable space from memory
                    json2csv.keysData = {};
                    // check send data separately or combine
                    if(isSeparate){ // return csv header separately
                        return {err:null, csv:csvDataStr, header:csvHeaderKeys.join(",")};
                    }
                    else{ // return csv header combine
                        let csv = csvHeaderKeys.join(",")+"\n"+csvDataStr;
                        csvHeaderKeys = [];
                        return {err:null, csv:csv};
                    }
                }
                else{
                    let tmpData = [];
                    let csvHeaderKeys = [];
                    // get single object keys
                    json2csv.parseJSONObj(data);
                    // get different keys into csv header
                    json2csv.keysData.HKEYS.filter(function(obj) {  if(csvHeaderKeys.indexOf(obj) == -1){ csvHeaderKeys.push(obj);} });
                    csvHeaderKeys.forEach(function(key, index){
                        if(json2csv.keysData[key]){
                            tmpData.push(json2csv.keysData[key]);
                        }
                        else{
                            tmpData.push("");
                        }
                        // remove special character from csv columns
                        csvHeaderKeys[index] = key.replace(/[`~%!@#$%^&*()|+\-=?;'",<>\{\}\[\]\\\/\s]/gi, '_');
                    }); 
                    // clear keysData variable space from memory
                    json2csv.keysData = {};
                    // check send data separately or combine
                    if(isSeparate){ // return csv header separately
                        return {err:null, csv:tmpData.join(","), header:csvHeaderKeys.join(",")};
                    }
                    else{ // return csv header combine
                        let csv = csvHeaderKeys.join(",")+"\n"+tmpData.join(",")+"\n";
                        csvHeaderKeys = [];
                        return {err:null, csv:csv};
                    }
                }
            }
            else{
                // return message as error
                return {err:"Data should be array with object or object format!", csv:""};
            }
        }
        else{
            // return message as error
             
            return {err:"Data not found!", csv:""};
        }
    }
    
    // get json keys list
    json2csv.parseJSONObj = function(data){
        // get json object keys
        let parentKeys = json2csv.getKeys(data);
        parentKeys.forEach(function(key){
            if(data[key]){
                if(data[key].constructor === Object){
                    // call nested json keys function
                    json2csv.getNestedJSONKeysValues(data[key], key);
                }
                else {
                    json2csv.keysData.HKEYS.push(key);
                    data[key] = (data[key] != '' && typeof data[key] == 'string' )? data[key].replace(new RegExp('\r?\n','g'), "") : data[key];
                    //data[key] = (data[key] != '' && typeof data[key] == 'string' )? data[key].replace(/\s*,\s*|\s+,/g, "") : data[key];
                    //data[key] = (data[key] != '' && typeof data[key] == 'string' )? data[key].replace(/[`~%!@#$%^&*()|+\-=?;'",<>\{\}\[\]\\\/]/gi, '_') : data[key];
                    json2csv.keysData[key] = data[key];//(data[key] != '')? data[key].replace(/\t?\n/g, "") : data[key];
                }
            }
        });
        return;
    }
    
    // get nested json keys
    json2csv.getNestedJSONKeysValues = function(obj, pKey){
        let objectKeys = [];
        let childKeys = json2csv.getKeys(obj);
        childKeys.forEach(function(key){
            // check object key property
            if(obj[key] && obj[key].constructor === Object){
                objectKeys.push(key);
            }
            else {
                json2csv.keysData.HKEYS.push(pKey+"_"+key);
                obj[key] = (obj[key] != '' && typeof obj[key] == 'string' )? obj[key].replace(new RegExp('\r?\n','g'), "") : obj[key];
                //obj[key] = (obj[key] != '' && typeof obj[key] == 'string' )? obj[key].replace(/\s*,\s*|\s+,/g, "") : obj[key];
                //obj[key] = (obj[key] != '' && typeof obj[key] == 'string' )? obj[key].replace(/[`~%!@#$%^&*()|+\-=?;'",<>\{\}\[\]\\\/]/gi, '_') : obj[key];
                json2csv.keysData[pKey+"_"+key] = obj[key];//(obj[key] != '')? obj[key].replace(/\t?\n/g, "") : obj[key];
            }
        });
        // check nested object keys
        if(objectKeys.length > 0){
            objectKeys.forEach(function(objKey){
                // push json key as column
                json2csv.keysData.HKEYS.push(pKey+'_'+objKey);
                json2csv.keysData[pKey+'_'+objKey] = '';
                // make flattern json nested keys
                json2csv.getNestedJSONKeysValues(obj[objKey], pKey+'_'+objKey);
            });
        }
        else{
            return false;
        }
    }
    
    // get parent keys of json
    json2csv.getKeys = function(obj){
        return Object.keys(obj);
    }
    
}(json2csv,common));
module.exports = json2csv;

