let pgsql = require('./pgsql.utils'),
logger = require('../../logger'),
eventstringCommon = require('./eventstringcommon');
let common = require('./common.js');
let moment = common.moment;
//this function is to make regex for date ranges
//it takes start date and end date as input
//the regex is paritioned into 5 parts 
//part 2 and part 4 will not exit if year of both dates are same
//order of coding is part1, part5, part3, part2 and part4
function getRegex(startDate, endDate){
	if(startDate>endDate){
  	return "Incorrect Date Format";
  }
	let year = startDate.getFullYear();
  let year2 = endDate.getFullYear();
  let month1 = startDate.getMonth()+1;
  let month2 = endDate.getMonth()+1;
  let day1 = startDate.getDate();
  let day2 = endDate.getDate();
  let monthstring1 = month1;
  let monthstring2 = month2;
  let daystring1 = day1;
  let daystring2 = day2;
  //Values less than 10 come in single digit
  //so we add an extra 0 to match required pattern
  if(day1<10){
  	daystring1 = '0' + daystring1;
  }
  if(day2<10){
  	daystring2 = '0' + daystring2;
  }
  if(month1<10){
  	monthstring1 = '0' + monthstring1;
  }
  if(month2<10){
  	monthstring2 = '0' + monthstring2;
  }
  let mod1 = year%100
  let mod2 = year2%100
  
  let part1 = '';
  let part2 = '';
  let part3 = '';
  let part4 = '';
  let part5 = '';
  //generic string for days and months of a year
  let generic = '(0[1-9]|1[0-9]|2[0-9]|3[01])((0[1-9]|1[0-2]))'
  //generic string for days of a month
  let generic2 = '(0[1-9]|1[0-9]|2[0-9]|3[01])'
  let final = '';
  
  if(month1==month2&&year==year2){
    //part1 updated

    if(day1<10){
      if(day2<10){
        part1 = part1 + '0[' + day1 + '-' + day2+ ']';
      }
      else if(day2==10){
        part1 = part1 + '0['+ day1  +'-9]|1[0]';
      }
      else if(day2<20){
        day2 = day2%10
        part1 = part1 + '0['+ day1 + '-9]|1[0-' + day2 + ']';
      }
      else if(day2==20){
        part1 = part1 + '0['+ day1 +'-9]|1[0-9]|2[0]';
      }
      else if(day2<30){
        day2 = day2%10
        part1 = part1 + '0['+ day1 +'-9]|1[0-9]|2[0-' + day2 + ']';
      }
      else if(day2==30){
        part1 = part1 + '0['+ day1 +'-9]|1[0-9]|2[0-9]|3[0]';
      }
      else if(day2==31){
        part1 = part1 + '0['+ day1 +'-9]|1[0-9]|2[0-9]|3[0-1]';
      }
    }
    else if(day1<20){
      day1 = day1%10
      if(day2==10){
        part1 = part1 + '1[0]'
      }
      else if(day2<20){
        day2 = day2%10
        part1 = part1 + '1[' + day1 + '-' + day2+ ']';
      }
      else if(day2==20){
        part1 = part1 + '1['+ day1  +'-9]|2[0]';
      }
      else if(day2<30){
        day2 = day2%10
        part1 = part1 + '1['+ day1 +'-9]|2[0-' + day2 + ']';
      }
      else if(day2==30){
        part1 = part1 + '1['+ day1 +'-9]|2[0-9]|3[0]';
      }
      else if(day2==31){
        part1 = part1 + '1['+ day1 +'-9]|2[0-9]|3[0-1]';
      }
    } 
    else if(day1<30){
      day1 = day1%10
      if(day2==20){
        part1 = part1 + '2[0]'
      }
      else if(day2<30){
        day2 = day2%10
        part1 = part1 + '2[' + day1 + '-' + day2+ ']';
      }
      else if(day2==30){
        part1 = part1 + '2['+ day1  +'-9]|3[0]';
      }
      else if(day2==31){
        part1 = part1 + '2['+ day1  +'-9]|3[0-1]';
      }
    } 
    else if(day1==30){
      day1 = day1%10
      if(day2==30){
        part1 = part1 + '3[0]';
      }
      else if(day2==31){
        part1 = part1 + '3[0-1]';
      }
    }
    else if(day==31){
      part1 = part1 + '3[1]';
    }

    part1 = '(' + part1 + ')'
    part1 = '(D' + part1 +  monthstring1 +  mod1 + ')';
    return part1;
  }



//part1 updated 

if(day1<10){
  part1 = part1 + '0[' + day1 + '-9]|1[0-9]|2[0-9]|3[0-1]';
}
else if(day1<20){
  day1 = day1%10
  part1 = part1 + '1[' + day1 + '-9]|2[0-9]|3[0-1]';
}
else if(day1<30){
  day1 = day1%10
  part1 = part1 + '2[' + day1 + '-9]|3[0-1]';
}
else if(day1==30){
  part1 = part1 + '3[0-1]';
}
else if(day1==31){
  part1 = part1 + '3[1]';
}


  part1 = '(' + part1 + ')'
  part1 = '(' + part1 +  monthstring1 +  mod1 + ')';
  /* alert(part1); */	


  //part5 updated

if(day2<10){
  part5 = part5 + '0[1-' + day2 + ']';
}
else if(day2==10){
  part5 = part5 + '0[0-9]|1[0]';
}
else if(day2<20){
  day2 = day2%10
  part5 = part5 + '0[1-9]|1[0-' + day2 + ']';
}
else if(day2==20){
  part5 = part5 + '0[1-9]|1[0-9]|2[0]';
}
else if(day2<30){
  day2 = day2%10
  part5 = part5 + '0[1-9]|1[0-9]|2[0-' + day2 + ']';
}
else if(day2==30){
  part5 = part5 + '0[1-9]|1[0-9]|2[0-9]|3[0]';
}
else if(day2==31){
  part5 = part5 + '0[1-9]|1[0-9]|2[0-9]|3[0-1]';
}

  part5 = '(' + part5 + ')'
  part5 = '(' + part5 + monthstring2 + mod2 + ')';
  /* alert(part5) ;*/
    
  //if both years will be same then part 2 and part 4 will not exist 
  //and part3 will be different
  if(year!=year2){
  	//implementing part 3 
    //adding all the years in between start and end year
    for(let k = year + 1; k< year2; k++){
    	let temp = k%100;
      part3 = part3 + '(' + generic + temp + ')';
      if(k!=year2-1){
        part3 = part3 + '|';
      }
    }
    /* alert(part3) ;*/
    
    //implementing part 2
    //adding all the months after start month of start year
    let part2check = false
  	for(let l = month1 + 1; l<13; l++){
      part2check = true
    	if(l<10){
      	part2 = part2 + '0' + l;
      }
      else{
      	part2 = part2 + l;
      }
      if(l!=12){
        part2 = part2 + '|';
      }	
    }
    
    if(part2check == true ){
      part2 = '(' + generic2 + '(' + part2 + ')' + mod1 + ')'  
    }
    
    /* alert(part2) ;*/
    
    //implementing part 4
    //adding all the months before end month of end year
    let part4check = false
    for(let m = 1; m<month2; m++){
      part4check = true
    	if(m<10){
      	part4 = part4 + '0' + m;
      }
      else{
      	part4 = part4 + m;
      }
      if(m!=month2-1){
        part4 = part4 + '|';
      }	
    }
    if(part4check == true ){
      part4 = '(' + generic2 + '(' + part4 + ')' + mod2 + ')' 
    }
    
    /* alert(part4) ;*/
    
    //final string including all 5 parts
    final = '(' + part1 + '|' ;
    if(part2!=''){
    	final = final + part2 + '|';
    }
    if(part3!=''){
    	final = final + part3 + '|';
    }
    if(part4!=''){
    	final = final + part4 + '|';
    }
    
    final = final + part5 + ')';
    
		
  /* alert(final) ;*/ 
    
  }
  else{
  	//implementing part 3
    //adding all the months of same year
		for(let a = month1 +1 ; a<month2; a++){
    	if(a<10){
      	part3 = part3 + '0' + a;
      }
      else{
      	part3 = part3 + a;
      }
      if(a!=month2-1){
        part3 = part3 + '|';
      }	
    }
    
    part3 = '(' + generic2 + '(' + part3 + ')' + mod1 + ')';
    /* alert(part3) ;*/
    
    
    //final string including all parts
    final = '(' + part1 + '|' ;
    if(part3!='' && month2-month1!=1){
    	final = final + part3 + '|';
    }
    final = final + part5+ ')';
    /* alert(final) ;*/
  
  }
  
  final = "(D" + final + ")";
  return final;
  
}

//this version is for int and float comparison
function getRegexV2(startDate, endDate){
	if(startDate>endDate){
  	return "Incorrect Date Format";
  }
	let year = startDate.getFullYear();
  let year2 = endDate.getFullYear();
  let month1 = startDate.getMonth()+1;
  let month2 = endDate.getMonth()+1;
  let day1 = startDate.getDate();
  let day2 = endDate.getDate();
  let monthstring1 = month1;
  let monthstring2 = month2;
  let daystring1 = day1;
  let daystring2 = day2;
  //Values less than 10 come in single digit
  //so we add an extra 0 to match required pattern
  if(day1<10){
  	daystring1 = '0' + daystring1;
  }
  if(day2<10){
  	daystring2 = '0' + daystring2;
  }
  if(month1<10){
  	monthstring1 = '0' + monthstring1;
  }
  if(month2<10){
  	monthstring2 = '0' + monthstring2;
  }
  let mod1 = year%100
  let mod2 = year2%100

  let my1 = monthstring1 +''+ mod1;
  let my2 = monthstring2 +''+ mod2;
  
  let part1 = '';
  let part2 = '';
  let part3 = '';
  let part4 = '';
  let part5 = '';
  let final = '';
  
  if(month1==month2&&year==year2){
    //part1 updated

    if(day1<10){
      if(day2<10){
        part1 = part1 + '0[' + day1 + '-' + day2+ ']' + my1;
      }
      else if(day2==10){
        part1 = part1 + '0['+ day1  +'-9]' + my1 + '|1[0]' + my1;
      }
      else if(day2<20){
        day2 = day2%10
        part1 = part1 + '0['+ day1 + '-9]' + my1 + '|1[0-' + day2 + ']' + my1;
      }
      else if(day2==20){
        part1 = part1 + '0['+ day1 +'-9]' + my1 + '|1[0-9]'  + my1 + '|2[0]' + my1;
      }
      else if(day2<30){
        day2 = day2%10
        part1 = part1 + '0['+ day1 +'-9]' + my1 + '|1[0-9]' + my1 + '|2[0-' + day2 + ']' + my1;
      }
      else if(day2==30){
        part1 = part1 + '0['+ day1 +'-9]' + my1 + '|1[0-9]' + my1 + '|2[0-9]' + my1 + '|3[0]' + my1;
      }
      else if(day2==31){
        part1 = part1 + '0['+ day1 +'-9]' + my1 + '|1[0-9]' + my1 + '|2[0-9]' + my1 + '|3[0-1]' + my1;
      }
    }
    else if(day1<20){
      day1 = day1%10
      if(day2==10){
        part1 = part1 + '1[0]' + my1
      }
      else if(day2<20){
        day2 = day2%10
        part1 = part1 + '1[' + day1 + '-' + day2+ ']' + my1;
      }
      else if(day2==20){
        part1 = part1 + '1['+ day1  +'-9]|2[0]' + my1;
      }
      else if(day2<30){
        day2 = day2%10
        part1 = part1 + '1['+ day1 +'-9]' + my1 + '|2[0-' + day2 + ']' + my1;
      }
      else if(day2==30){
        part1 = part1 + '1['+ day1 +'-9]' + my1 + '|2[0-9]' + my1 + '|3[0]' + my1;
      }
      else if(day2==31){
        part1 = part1 + '1['+ day1 +'-9]' + my1 + '|2[0-9]' + my1 + '|3[0-1]' + my1;
      }
    } 
    else if(day1<30){
      day1 = day1%10
      if(day2==20){
        part1 = part1 + '2[0]' + my1
      }
      else if(day2<30){
        day2 = day2%10
        part1 = part1 + '2[' + day1 + '-' + day2+ ']' + my1;
      }
      else if(day2==30){
        part1 = part1 + '2['+ day1  +'-9]' + my1 + '|3[0]' + my1;
      }
      else if(day2==31){
        part1 = part1 + '2['+ day1  +'-9]' + my1 + '|3[0-1]' + my1;
      }
    } 
    else if(day1==30){
      day1 = day1%10
      if(day2==30){
        part1 = part1 + '3[0]' + my1;
      }
      else if(day2==31){
        part1 = part1 + '3[0-1]' + my1;
      }
    }
    else if(day==31){
      part1 = part1 + '3[1]' + my1;
    }

    part1 = '(D(' + part1 +'))';
    return part1;
  }



//part1 updated 

if(day1<10){
  part1 = part1 + '0[' + day1 + '-9]' + my1 + '|1[0-9]' + my1 +'|2[0-9]' + my1 + '|3[0-1]' + my1;
}
else if(day1<20){
  day1 = day1%10
  part1 = part1 + '1[' + day1 + '-9]' + my1 + '|2[0-9]' + my1 + '|3[0-1]' + my1;
}
else if(day1<30){
  day1 = day1%10
  part1 = part1 + '2[' + day1 + '-9]' + my1 + '|3[0-1]' + my1;
}
else if(day1==30){
  part1 = part1 + '3[0-1]' + my1;
}
else if(day1==31){
  part1 = part1 + '3[1]' + my1;
}


  part1 = '(' + part1 + ')'
  /* alert(part1); */	


  //part5 updated

if(day2<10){
  part5 = part5 + '0[1-' + day2 + ']' + my2;
}
else if(day2==10){
  part5 = part5 + '0[0-9]' + my2 + '|1[0]' + my2;
}
else if(day2<20){
  day2 = day2%10
  part5 = part5 + '0[1-9]' + my2 + '|1[0-' + day2 + ']' + my2;
}
else if(day2==20){
  part5 = part5 + '0[1-9]' + my2 + '|1[0-9]' + my2 + '|2[0]' + my2;
}
else if(day2<30){
  day2 = day2%10
  part5 = part5 + '0[1-9]' + my2 + '|1[0-9]' + my2 + '|2[0-' + day2 + ']' + my2;
}
else if(day2==30){
  part5 = part5 + '0[1-9]' + my2 + '|1[0-9]' + my2 + '|2[0-9]' + my2 +'|3[0]' + my2;
}
else if(day2==31){
  part5 = part5 + '0[1-9]' + my2 + '|1[0-9]' + my2 + '|2[0-9]' + my2 + '|3[0-1]' + my2;
}

  part5 = '(' + part5 + ')'
  /* alert(part5) ;*/
    
  //if both years will be same then part 2 and part 4 will not exist 
  //and part3 will be different
  if(year!=year2){
  	//implementing part 3 
    //adding all the years in between start and end year
    for(let k = year + 1; k< year2; k++){
    	let y = k%100;
      let my5
      for(let i=1; i<13; i++){
        my5 = i<10 ? ('0' +i+''+ y) : (i+''+ y)
        part3 = part3 + '(0[1-9]'+my5+'|1[0-9]'+my5+'|2[0-9]'+my5+'|3[0-1]'+my5+')';
      }
      if(k!=year2-1){
        part3 = part3 + '|';
      }
    }
    
    //implementing part 2
    //adding all the months after start month of start year
  	for(let l = month1 + 1; l<13; l++){
      let my4 = l +''+ mod1
    	if(l<10){
      	my4 = '0' + my4;
        part2 = part2 + '(0[1-9]'+ my4 +'|1[0-9]'+ my4 +'|2[0-9]'+ my4 +'|3[0-1]'+ my4+')'
      }
      else{
      	part2 = part2 + '(0[1-9]'+ my4 +'|1[0-9]'+ my4 +'|2[0-9]'+ my4 +'|3[0-1]'+ my4+')'
      }
      if(l!=12){
        part2 = part2 + '|';
      }	
    }
    
    /* alert(part2) ;*/
    
    //implementing part 4
    //adding all the months before end month of end year
    for(let m = 1; m<month2; m++){
      let my5 = m+''+mod2;
    	if(m<10){
      	my5 = '0' + my5;
        part4 = part4 + '(0[1-9]'+ my5 +'|1[0-9]'+ my5 +'|2[0-9]'+ my5 +'|3[0-1]'+ my5+')'
      }
      else{
      	part4 = part4 + '(0[1-9]'+ my5 +'|1[0-9]'+ my5 +'|2[0-9]'+ my5 +'|3[0-1]'+ my5+')'
      }
      if(m!=month2-1){
        part4 = part4 + '|';
      }	
    }
    
    /* alert(part4) ;*/
    
    //final string including all 5 parts
    final = part1 + '|' ;
    if(part2!=''){
    	final = final + part2 + '|';
    }
    if(part3!=''){
    	final = final + part3 + '|';
    }
    if(part4!=''){
    	final = final + part4 + '|';
    }
    
    final = final + part5;
    
  }
  else{
  	//implementing part 3
    //adding all the months of same year
		for(let a = month1 +1 ; a<month2; a++){
      let my3 = a+''+mod1
    	if(a<10){
      	my3 = '0' + my3;
        part3 = part3 + '(0[1-9]'+ my3 +'|1[0-9]'+ my3 +'|2[0-9]'+ my3 +'|3[0-1]'+ my3+')'
      }
      else{
      	part3 = part3 + '(0[1-9]'+ my3 +'|1[0-9]'+ my3 +'|2[0-9]'+ my3 +'|3[0-1]'+ my3+')'
      }
      if(a!=month2-1){
        part3 = part3 + '|';
      }	
    }
    
    //final string including all parts
    final = part1 + '|' ;
    if(part3!='' && month2-month1!=1){
    	final = final + part3 + '|';
    }
    final = final + part5;
    /* alert(final) ;*/
  
  }
  
  final = "(D" + final + ")";
  return final;
  
}


/***
* Regex Numeric Range Generator
*/
this.RegNumericRange = function() {
    function t(r, e, n, s) {
        return null === n && (n = {}), this instanceof t ? (this.minValue = r, this.maxValue = e, this.options = this.extend({}, this.defaults, n), void(this.data = {})) : new t(r, e, n, s)
    }
    return t.prototype.defaults = {
        MatchWholeWord: !1,
        MatchWholeLine: !1,
        MatchLeadingZero: !1,
        showProcess: !1
    }, t.prototype.generate = function(t) {
        let r = this.minValue.toString(),
            e = this.maxValue.toString(),
            n = [],
            s = [],
            i = [];
        if (!this.minValue || !this.maxValue) {
            let a = "Minimum & Maximum value is required!";
            if ("function" == typeof t) return t({
                success: !1,
                message: a
            });
            throw new Error(a)
        }
        if (!this.isNumeric(this.minValue) || !this.isNumeric(this.maxValue)) {
            let a = "Minimum & Maximum value must numbers only!";
            if ("function" == typeof t) return t({
                success: !1,
                message: a
            });
            throw new Error(a)
        }
        if (parseInt(this.minValue) === parseInt(this.maxValue) || parseInt(this.minValue) > parseInt(this.maxValue)) {
            let a = "Max. value must greater than Min. value!";
            if ("function" == typeof t) return t({
                success: !1,
                message: a
            });
            throw new Error(a)
        }
        n = this.parseStartRange(r, e);
        for (let o in n) s.push(this.parseEndRange(n[o][0], n[o][1]));
        if (n = this.reformatArray(s), this.options.showProcess)
            for (i[i.length] = {
                    title: "Parse Into Range:",
                    steps: []
                }, o = 0; o < n.length; o++) i[i.length - 1].steps.push(n[o].join(" - "));
        let h = this.parseIntoRegex(n);
        if (this.options.showProcess)
            for (i[i.length] = {
                    title: "Parse Into Block Regex:",
                    steps: []
                }, o = 0; o < h.length; o++) i[i.length - 1].steps.push(h[o]);
        let u = this.parseIntoPattern(h);
        return this.options.showProcess && (i[i.length] = {
            title: "Combining Into Regex Pattern:",
            steps: [u]
        }), this.setProcess({
            pattern: u,
            process: i
        }), "function" == typeof t ? t({
            success: !0,
            data: this.data
        }) : this.data
    }, t.prototype.setProcess = function(t) {
        this.data = this.extend({}, this.data, t)
    }, t.prototype.parseStartRange = function(t, r) {
        return t = parseInt(t), r = parseInt(r), t.toString().length === r.toString().length ? [
            [t.toString(), r.toString()]
        ] : (breakPoint = Math.pow(10, t.toString().length) - 1, [
            [t.toString(), breakPoint.toString()]
        ].concat(this.parseStartRange(breakPoint + 1, r.toString())))
    }, t.prototype.parseEndRange = function(t, r) {
        if (1 === t.length) return [t, r];
        if (Array(t.length + 1).join("0") === "0" + t.substr(1)) {
            if (Array(r.length + 1).join("0") === "9" + r.substr(1)) return [t, r];
            if (t.substr(0, 1) < r.substr(0, 1)) {
                let e = parseInt(r.substr(0, 1) + Array(r.substr(1).length + 1).join("0")) - 1,
                    n = this.strBreakPoint(e),
                    s = this.strBreakPoint(e + 1);
                return [t, n].concat(this.parseEndRange(s, r))
            }
        }
        if (Array(r.length + 1).join("9") === "9" + r.substr(1) && t.substr(0, 1) < r.substr(0, 1)) {
            let i = (parseInt(t.substr(0, 1)) + 1).toString(),
                e = parseInt(i + Array(r.substr(1).length + 1).join("0")) - 1,
                n = this.strBreakPoint(e),
                s = this.strBreakPoint(e + 1);
            return this.parseEndRange(t, n).concat([s, r])
        }
        if (t.substr(0, 1) < r.substr(0, 1)) {
            let i = (parseInt(t.substr(0, 1)) + 1).toString(),
                e = parseInt(i + Array(r.substr(1).length + 1).join("0")) - 1,
                n = this.strBreakPoint(e),
                s = this.strBreakPoint(e + 1);
            return this.parseEndRange(t, n).concat(this.parseEndRange(s, r))
        }
        for (let a = t.substr(0, 1), o = this.parseEndRange(t.substr(1), r.substr(1)), h = [], u = 0; u < o.length; u++) h.push(a + o[u]);
        return h
    }, t.prototype.parseIntoRegex = function(t) {
        if (!this.isArray(t)) throw new Error("Argument needs to be an array!");
        let r = [];
        for (i = 0; i < t.length; i++) {
            let e = t[i][0].split(""),
                n = t[i][1].split(""),
                s = "",
                o = 0,
                h = "";
            for (a = 0; a < e.length; a++) e[a] === n[a] ? h += e[a] : parseInt(e[a]) + 1 === parseInt(n[a]) ? h += "[" + e[a] + n[a] + "]" : (s === e[a] + n[a] ? o++ : s = e[a] + n[a], a === e.length - 1 ? h += o > 0 ? "{" + (o + 1) + "}" : "[" + e[a] + "-" + n[a] + "]" : 0 === o && (h += "[" + e[a] + "-" + n[a] + "]"));
            r.push(h)
        }
        return r
    }, t.prototype.parseIntoPattern = function(t) {
        if (this.isArray(t)) {
            let r = t.join("|");
            return this.options.MatchWholeLine && this.options.MatchLeadingZero ? "^0*(" + r + ")$" : this.options.MatchLeadingZero ? "0*(" + r + ")" : this.options.MatchWholeLine ? "^(" + r + ")$" : this.options.MatchWholeWord ? "\\b(" + r + ")\\b" : "(" + r + ")"
        }
        let r = "[" + t + "]";
        return this.options.MatchWholeLine && this.options.MatchLeadingZero ? "^0*(" + r + ")$" : this.options.MatchLeadingZero ? "0*(" + r + ")" : this.options.MatchWholeLine ? "^(" + r + ")$" : this.options.MatchWholeWord ? "\\b(" + r + ")\\b" : "(" + r + ")"
    }, t.prototype.reformatArray = function(t) {
        for (arrReturn = [], i = 0; i < t.length; i++)
            for (page = t[i].length / 2, a = 0; a < page; a++) left = 2 * a, right = 2 * a + 2, arrReturn.push(t[i].slice(left, right));
        return arrReturn
    }, t.prototype.fixPair = function(t) {
        let r = t[0],
            e = t[1];
        return this.rjust(r, e.length, "0")
    }, t.prototype.strBreakPoint = function(t) {
        return this.fixPair([t.toString(), (t + 1).toString()])
    }, t.prototype.rjust = function(t, r, e) {
        return e = e || " ", e = e.substr(0, 1), t.length < r ? e.repeat(r - t.length) + t : t
    }, t.prototype.extend = function() {
        let t, r, e, n, s, i, a;
        for (i = arguments[0], t = 2 <= arguments.length ? [].slice.call(arguments, 1) : [], r = 0, n = t.length; n > r; r++) {
            s = t[r];
            for (e in s) a = s[e], null != a && (i[e] = a)
        }
        return i
    }, t.prototype.append = function(t, r) {
        return document.querySelector(t) && document.querySelector(t).insertAdjacentHTML("beforeend", r), this
    }, t.prototype.isArray = Array.isArray || function(t) {
        return "[object Array]" === Object.prototype.toString.call(t)
    }, t.prototype.isNumeric = function(t) {
        return !isNaN(parseFloat(t)) && isFinite(t)
    }, t
}();



let a = 5;
let b = 200;


function generateRegexForIntegerRange(a,b){
	let str =''
  if(a>b){
  	return "Format Incorrect";
  }
  if(a>0&&b>0){
		str = RegNumericRange(a, b).generate(function(result){
                return JSON.stringify(result.data.pattern);
              });
    str = str.replace(/['"]+/g, '');          
    /* alert(str); */
  }
  else if(a<0&&b>0){
  	let temp = a*(-1)
    str = RegNumericRange(1, temp).generate(function(result){
    						/* alert(JSON.stringify(result)); */
                return JSON.stringify(result.data.pattern);
              });
    /* alert(str); */
    let str2 = RegNumericRange(1, b).generate(function(result){
                return JSON.stringify(result.data.pattern);
              });
    /* alert(str2); */
    let str3 = str.replace(/['"]+/g, '');
    let str4  = str2.replace(/['"]+/g, '');
    /* alert(str3) */
    str = "((-" + str3 + ")|(" + str4 + "))";
   /*  alert(str); */
  }
  else if(a<0&&b<0){
  	a = a*(-1)
    b = b*(-1)
  	let str = RegNumericRange(b, a).generate(function(result){
                return JSON.stringify(result.data.pattern);
              });
    let str3 = str.replace(/['"]+/g, '');          
    str = "(-" + str3 + ")";    
    /* alert(str); */
  }
  return str;
}


//this function is to make regex for event key
//this version is for int and float comparison
function generateRegexForEventKeyV2(id,havenot){
	if(id>=1){
    return "(B" + id + "T.*?";
  }
  else{
  	return "Id cannot be less than 1"
  }
}

function generateRegexForEventKey(id,havenot){
	if(id>=1){
    return "[^D]*?B" + id + "T.*?";
  }
  else{
  	return "Id cannot be less than 1"
  }
}

function generateRegexForBoolean(value, flag, condition){
	let str= '';
  if(flag==0){
  	if(condition == 'eq'){
    	str = "V" + value;
    }
    else{
    	str = "V(?!" + value + ")";
    }
  	
  }
  else{
  	
  }
  return str;
}

const sessionStartRegex = 'S\\d+T\\d+';
const eventRegex = 'B\\d+T\\d+';
const attrRegex = 'A\\d+';
const valueRegex = 'V([+|-]?\\d+[\\.]?\\d*)';
const sessionEndRegex = 'E\\d+T\\d+';


//this method is attribute regex
function generateRegexForAttributeRegex(){
    return attrRegex;
}

//this method is for session end
function generateRegexForValueRegex(){
    return valueRegex;
}

//this method is for session start
function generateRegexForSessionStart(){
    return sessionStartRegex;
}

//this method is for session end
function generateRegexForSessionEnd(){
    return sessionEndRegex;
}


//this method is for event Regex
function generateRegexForEventRegex(){
    return eventRegex;
}






//this method is for skipping events
function generateRegexForSkippingEvents(){
		let str1 = generateRegexForEventRegex();
    let str2 = generateRegexForAttributeRegex();
    let str3 = generateRegexForValueRegex();
    return '(('+ str1 +')('+ str2 + '('+str3 +')+)*)*?';
}


//this function is for skipping till session end
function generateRegexForSkippingTillSessionEnd(){
		let str = generateRegexForSkippingEvents();
    let str2 = generateRegexForSessionEnd();
    return '(('+ str +')('+ str2 +'))*?';
}

//this function is for skipping sessions
function generateRegexForSkippingSessions(){
		let str = generateRegexForSkippingEvents();
    let str2 = generateRegexForSessionEnd();
    let str1 = generateRegexForSessionStart();
    return '(('+ str1 +')('+ str +')('+ str2 +'))*?';
}

//this function is for skipping daily data
function generateRegexForSkippingDailyData(dateRegex){
		let str = generateRegexForSkippingSessions();
    return '('+ dateRegex + str +')';
}

//this function is for skipping data
function generateRegexForSkippingData(sameSession, dateRegex, complex){
    if(complex==false){
      return ;
    }
    if(sameSession){
    		let str = generateRegexForSkippingEvents();
        str = '(' + str + ')';
        return str;
    }
    else{
    		let str = generateRegexForSkippingEvents();
        let str2 = generateRegexForSkippingSessions();
       	let str3 = generateRegexForSkippingDailyData(dateRegex);
        str = '(' + str + ')|(' + str2 + ')|(' + str3 + ')';
        return str;
    }
}

//this function is to make regex for attribute array 
function generateRegexForAttribute(attribute){
	// let genericAttribute = '(' + attrRegex  + valueRegex +')*';
  let str = ''
  for(let i=0;i<attribute.length;i++){
    // str = str + '.*?'
  	
    str = str + "A" + attribute[i].attribute;
    if(attribute[i].condition=='eq'){
    	str = str + "V" + attribute[i].value;
    }
    else if(attribute[i].condition=='neq'){
    	str = str + "V(?!" + attribute[i].value + ")";
    }
		else if(attribute[i].condition=='in'||attribute[i].condition=='contains'||attribute[i].condition=='startsWith'||attribute[i].condition=='endsWith'){
    	let str2 = 'V('
      for(let j=0;j<attribute[i].value.length;j++){
      	str2 = str2 + attribute[i].value[j] ;
        if(j!=attribute[i].value.length-1){
        	str2 = str2+ '|';
        }
      }
      str2 = str2 + ")"
      str = str + str2;
    }
    else if(attribute[i].condition=='nin'||attribute[i].condition=='doesntstartsWith'||attribute[i].condition=='doesntendsWith'){
    	let str2 = 'V'
      for(let j=0;j<attribute[i].value.length;j++){
      	str2 = str2 + "(?!"+ attribute[i].value[j] + ")";
      }
      str = str + str2;
    }
    else if(attribute[i].condition=='isb'){
    	let str2 = generateRegexForIntegerRange(attribute[i].value[0],attribute[i].value[1]);      
      str = str + str2;
    }
    else if(attribute[i].condition=='isnb'){
    	let str2 = generateRegexForIntegerRange(attribute[i].value[0],attribute[i].value[1]);      
      str2 = "(!" + str2 + ")";
      str = str + str2;
    }
    else if(attribute[i].condition=='lt'){
    	let str2 = generateRegexForIntegerRange(attribute[i].value[0],attribute[i].value[1]-1);      
      str = str + str2;
    }
    else if(attribute[i].condition=='gt'){
    	let str2 = generateRegexForIntegerRange(attribute[i].value[0]+1,attribute[i].value[1]);      
      str = str + str2;
    }
    else if(attribute[i].condition=='lte'){
    	let str2 = generateRegexForIntegerRange(attribute[i].value[0],attribute[i].value[1]);      
      str = str + str2;
    }
    else if(attribute[i].condition=='gte'){
    	let str2 = generateRegexForIntegerRange(attribute[i].value[0],attribute[i].value[1]);      
      str = str + str2;
    }
    
    
    if(i==attribute.length-1){
    	// str = str + genericAttribute;
      str= str + '.*?'
    }
  }
  return str;
}

//this function is to make regex for attribute array 
//this version is for int and float comparison
function generateRegexForAttributeV2(attribute){
	// let genericAttribute = '(' + attrRegex  + valueRegex +')*';
  let str = ''
  for(let i=0;i<attribute.length;i++){
    if(attribute[i].type == 'float')
    str = str + "A" + attribute[i].attribute + "V([+-]?[0-9]+[.]{1}[0-9]+))"; //matches float
    else
    str = str + "A" + attribute[i].attribute + "V([+-]?[0-9]+.?[0-9]+))"; //matches int
  }
  return str;
}

//this function is to make regex for each step
//it will have an event key and attribute array as arguments
function generateRegexForStep(key, attribute, attrList){
  if(key<1){
    return "Id cannot be less than 1";
  }
  
  let str
  if(attrList > 0){
    let str = generateRegexForEventKeyV2(key);

    if(attribute.length>=0){
      let str3 = generateRegexForAttributeV2(attribute);     
      str = str + str3;
    }
  }else{
    let str = generateRegexForEventKey(key);

    if(attribute.length>=0){
      let str3 = generateRegexForAttribute(attribute);      
      str = str + str3;
    }
  }
  
  // if(complex==true){
  //  str = str + ')'; 
  // }
  return str;
  
}

let attribute = [
{"attribute":'12',
 "value":'223',
 "condition": 'neq'
},
{"attribute":'11',
 "value":['2553','121'],
 "condition": 'doesntstartsWith'
},
{"attribute":'2',
 "value":['23333','233','33'],
 "condition": 'doesntendsWith'
}]

attribute.sort(function(a, b) {
    return parseInt(a.attribute) - parseInt(b.attribute);
});


//compute time difference for have not scenarios
function computeTimeForHaveNot(step){
   //===========================================//
    //Have not scenario handled here
    //if condition is of have not
    if(step.since.have=='hn'){
      let dateDifference = 0  //get date difference to compute date regex
      let epochDifference = 0 //epoch time difference to compute for hours, mminutes, seconds
      //if condition is days, compute only date difference
      if(what[i].since.type=='d'){
        dateDifference = step.since.time        
      }
      //if condition is hours, compute both
      else if(step.since.type=='h'){
        //temp is used to convert hours into days
        let temp = step.since.time / 24;
        //get the ceiling value
        temp = Math.ceil(temp);
        if(temp>0){
          dateDifference = temp;
        }
        //compute time in seconds to get difference from current time
        epochDifference = step.since.time * 60 * 60;
      }
      //if condition is minutes, compute both date differnce and epoch time
      else if(step.since.type=='m'){
        //converting it to hours
        let temp = step.since.time / 60;
        //take the ceiling value
        temp = Math.ceil(temp);
        if(temp>0){
          //converting it to days
          let temp2 = temp/24;
          temp2 = Math.ceil(temp2);
          if(temp2>0){
          dateDifference = temp2;
          }
        }
        //converting it to seconds
        epochDifference = step.since.time * 60 ;
      }
      //if condition is seconds, compute both date difference and epoch time
      else if(step.since.type=='s'){
        //converting it to minutes
        let temp = step.since.time / 60;
        //take the ceiling value
        temp = Math.ceil(temp);
        if(temp>0){
          //converting it to hours
          let temp2 = temp/60;
          temp2 = Math.ceil(temp2);
          if(temp2>0){
            //converting it to days
            let temp3 = temp2/24;
            temp3 = Math.ceil(temp3);
            if(temp3>0){
            dateDifference = temp3;
            }
          }
        }
        //compute it to seconds
        epochDifference = step.since.time;
      }
    }
    return epochDifference;
}

function epochToJsDate(timestamp){
    // ts = epoch timestamp
    // returns date obj
    let d =  new Date(timestamp*1000);
    return (d.getFullYear() + '-' + ("0" + (d.getMonth() + 1)).slice(-2) + '-' + ("0" + d.getDate()).slice(-2));
}

async function generateRegexForSteps( app_id, what , startDate , endDate, platform, countOrData, column){
  logger.info(`startdate:>> ${startDate} && enddate ${endDate}`);
  let attrList = [];
  let attributeList = async (value,operator,type,index) =>{
    attrList.push({
      'value': value,
      'condition': operator,
      'type': type,
      'eventIndex': index
    })
  }
  let startdate = epochToJsDate(startDate)
  let enddate = epochToJsDate(endDate)
  startdate = new Date(startdate)
  enddate = new Date(enddate)

	let appEventTable = 'app_events_' + app_id;
  let attributeTable = "attributes_" + app_id //attribute name table
  let attributeValueTable = "attribute_value_" + app_id //attribute value table
  //get date regex for default/provided dates
  let dateRegex = getRegex(startdate, enddate);

  let inputEndDate = new Date(endDate);
  let todaysDate = new Date();

  // let complex = false
  inputEndDate = inputEndDate.getTime();
  todaysDate = todaysDate.getTime();
  logger.info(`time:::: ${inputEndDate} && ${todaysDate}`);

  /* let who = steps.who */
  /* let when = steps.when */
  /* let where = steps.where */
  //final regex will first have regex for skipping data to get to first step, then add all the regex for each step
  let finalRegex = ''
  //regex for all the steps
  let regexSteps = ''
  //initialise epoch time difference for have not conditon
  let epochDifference = 0;
  //loop around all the events coming in what condition
  for(let i = 0; i< what.length; i++){
    //get the operand which the key 
  	let temp = what[i].operand;	
    //fetch event id from the app events table
    let appEventData = await eventstringCommon.fetchAppEventsDataWithKey(appEventTable, temp);
    //fetch attribute details from attribute table
    let attribute = []
    if(what[i].attr!='' && what[i].attr!='undefined' && what[i].attr!=undefined){
      let getAttributeData = await eventstringCommon.fetchAttributeDetailsWithKey(attributeTable, temp, what[i].attr)
      
      // check if value is in array or single object
      if(Array.isArray(what[i].value)){
      	let getAttributeValue = []
        //loop over all the values of value attribute
        for(let j=0;j<what[i].value.length;j++){
          //checking for int
          if(getAttributeData[0][0].datatype == 'int'){
              getAttributeValue.push(what[i].value[j]);
              await attributeList(what[i].value[j],what[i].operator,'int',i+1);
          }
          //checking for float
          else if(getAttributeData[0][0].datatype == 'float'){
              getAttributeValue.push(what[i].value[j]);
              await attributeList(what[i].value[j],what[i].operator,'float',i+1);
          }
          //checking for string
          else if(getAttributeData[0][0].datatype == 'string'){
            let attributeValueId = await eventstringCommon.fetchAttributeValueDetailsWithValue(attributeValueTable, what[i].value[j])
            getAttributeValue.push(attributeValueId[0].id);
          }
        	
        }

        //making attribute object for generate regex for step and attribute
        attribute = [{
        'attribute': getAttributeData[0][0].id,
        'value': getAttributeValue,
        'condition': what[i].operator,
        'type': getAttributeData[0][0].datatype
        }]
      }
      else{    	
        let getAttributeValue = []
        logger.info(`value ::: ${typeof (what[i].value), what[i].value}`);
        //checking for int
        if(getAttributeData[0][0].datatype == 'int'){
            getAttributeValue.push(what[i].value);
            await attributeList(what[i].value,what[i].operator,'int',i+1);
        }
        //checking for float
        else if(getAttributeData[0][0].datatype == 'float'){
            getAttributeValue.push(what[i].value);
            await attributeList(what[i].value,what[i].operator,'float',i+1);
        }
        //checking for string
        else if(getAttributeData[0][0].datatype == 'string'){
          logger.info("THis is a string value");
          let attributeValueId = await eventstringCommon.fetchAttributeValueDetailsWithValue(attributeValueTable, getAttributeData[0][0].id, what[i].value)
          getAttributeValue.push(attributeValueId[0][0].id);
        }
        logger.info(`getAttributeValue=> ${getAttributeValue}`);
        //making attribute object for generate regex for step and attribute
        attribute = [{
        'attribute': getAttributeData[0][0].id,
        'value': getAttributeValue,
        'condition': what[i].operator,
        'type': getAttributeData[0][0].datatype
        }]
      }
    }

    let havenot = false;
    if(what[i].since.have=='hn'){
      havenot = true;
    }
    let regexStep = generateRegexForStep(appEventData[0][0].id, attribute, attrList.length);

    regexSteps = regexSteps  + regexStep;
    if(i < what.length-1){
      regexSteps = regexSteps  +'[^D]*';
    }
    if(i==0){
      regexStep1 = regexSteps
    }
    if(i==1){
      regexStep2 = regexSteps
    }
  }
  //dynamically add platform to query if sent
  let p = (platform.length==3) ? "" : " and p in ('"+platform.join("','")+"')";
  if(attrList.length>0){     //this will run if the events have int/float values
    let dateRegexX = getRegexV2(startdate, enddate);
    let offset = 2;  //offset is set as 2 because we get the value in 2nd position and position for consecutive values is multiple of 2
    let attrCompare = "";
    //making the attribute value comparison with the result returned from regexp_matches
    for(let i=0; i< attrList.length;i++){
      let operator = (attrList[i].condition=='eq') ? '=' : ((attrList[i].condition=='neq') ? '!=' : ((attrList[i].condition=='gt') ? '>' : ((attrList[i].condition=='lt') ? '<' : ((attrList[i].condition=='gte') ? '>=' : '<='))))
      attrCompare += "(s2.match["+((attrList[i].eventIndex)*offset)+"])::"+attrList[i].type+" "+operator+" "+attrList[i].value;
      attrCompare += i!=attrList.length-1 ? " and " : ""
    }
    finalRegex = "select (case when sum(case when "+attrCompare+" then (case when (select substring(s2.eventstring,1,regexp_instr(s2.eventstring,'"+ regexSteps +"', 1,s2.row_number::int)) ~ '" +  dateRegexX + "')=true then 1 else 0 end) else 0 end)::int>0 then 1 else 0 end) from (select row_number() over(),* from (SELECT eventstring, regexp_matches( eventstring,'"+ regexSteps +"','g') as match from app_users_"+ app_id +" where eventstring <> ''"+p+") as s1) as s2;";
  }
  else{   //this will run if the events doesnot have int/float values
    if(what.length==2){
      if(havenot==false){
        finalRegex = "select count( did) from app_users_"+ app_id +" where eventstring ~ '" +  dateRegex + regexSteps+"'"+p+";";
      }
      else{
        finalRegex = "select count( did) from app_users_"+ app_id +" where eventstring ~ '" +  dateRegex + regexStep1+"' and eventstring !~ '"+ dateRegex + regexStep2 +"'"+p+";";
      }
    }
    else {
      if(havenot==false){
        finalRegex = "select count( did) from app_users_"+ app_id +" where eventstring ~ '" +  dateRegex + regexSteps+"'"+p+";";
      }
      else{
        finalRegex = "select count( did) from app_users_"+ app_id +" where eventstring !~ '" +  dateRegex + regexSteps+"'"+p+";";
      }  
    }
    if(typeof column != 'undefined'){
      finalRegex = common.generateQuery(finalRegex, countOrData, column);
    }  
  }
  
  logger.info(`final regexxxxx::: ${finalRegex}`)
  return finalRegex;
}

function generateSqlQuery(steps, startdate, enddate){
  // let eventstring = generateRegexForSteps(steps, startdate, enddate, sameSession)
  // let dateRegex = getRegex(startDate, enddate);
  // let query = "select did from " + tablename + " where active = true AND ls > Now() - "+ range +" AND substring(eventstring, getOffset(day_map, '"+ dateRegex +"'))  ~ '" + eventstring + "'";
  return "success";
}

function sayHello(){
   return "hello there jest"
}

module.exports = {sayHello, getRegex, generateRegexForIntegerRange,generateRegexForEventKey, generateRegexForSessionStart, generateRegexForSessionEnd, generateRegexForEventRegex, generateRegexForAttributeRegex, generateRegexForValueRegex, generateRegexForSkippingEvents, generateRegexForSkippingTillSessionEnd, generateRegexForSkippingSessions, generateRegexForSkippingDailyData, generateRegexForSkippingData, generateRegexForStep, generateRegexForAttribute, generateRegexForSteps, generateSqlQuery};
