pgsql = require('./../../utils/pgsql.utils.js');
logger = require('../../../logger');
//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";
  }
	var year = startDate.getFullYear();
  var year2 = endDate.getFullYear();
  var month1 = startDate.getMonth()+1;
  var month2 = endDate.getMonth()+1;
  var day1 = startDate.getDate();
  var day2 = endDate.getDate();
  var monthstring1 = month1;
  var monthstring2 = month2;
  var daystring1 = day1;
  var 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;
  }
  var mod1 = year%100
  var mod2 = year2%100
  
  var part1 = '';
  var part2 = '';
  var part3 = '';
  var part4 = '';
  var part5 = '';
  //generic string for days and months of a year
  var 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
  var generic2 = '(0[1-9]|1[0-9]|2[0-9]|3[01])'
  var final = '';
  
  if(month1==month2&&year==year2){
  	//regex for all the days of start month 
    for(var j = day1; j<=day2; j++){
      if(j<10){
        part1 = part1 + '0' + j;
      }
      else{
        part1 = part1 + j;
      }
      if(j!=day2){
        part1 = part1 + '|';
      }
    }

    part1 = '(' + part1 + ')'
    part1 = '(D' + part1 +  monthstring1 +  mod1 + ')';
    return part1;
  }
  
  
  //implementing part 1
  //regex for all the days of start month 
	for(var j = day1; j<=31; j++){
    if(j<10){
      part1 = part1 + '0' + j;
    }
    else{
      part1 = part1 + j;
    }
    if(j!=31){
      part1 = part1 + '|';
    }
  }

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

	//implemting part 5
  //all the days of last month
  for(var j = 1; j<=day2; j++){
    if(j<10){
      part5 = part5 + '0' + j;
    }
    else{
      part5 = part5 + j;
    }
    if(j!=day2){
      part5 = part5 + '|';
    }
  }

  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(var k = year + 1; k< year2; k++){
    	var 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
  	for(var l = month1 + 1; l<13; l++){
    	if(l<10){
      	part2 = part2 + '0' + l;
      }
      else{
      	part2 = part2 + l;
      }
      if(l!=12){
        part2 = part2 + '|';
      }	
    }
    
    part2 = '(' + generic2 + '(' + part2 + ')' + mod1 + ')'
    /* alert(part2) ;*/
    
    //implementing part 4
    //adding all the months before end month of end year
    for(var m = 1; m<month2; m++){
    	if(m<10){
      	part4 = part4 + '0' + m;
      }
      else{
      	part4 = part4 + m;
      }
      if(m!=month2-1){
        part4 = part4 + '|';
      }	
    }
    
    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(var 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!=''){
    	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) {
        var r = this.minValue.toString(),
            e = this.maxValue.toString(),
            n = [],
            s = [],
            i = [];
        if (!this.minValue || !this.maxValue) {
            var 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)) {
            var 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)) {
            var 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 (var 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(" - "));
        var 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]);
        var 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)) {
                var 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)) {
            var 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)) {
            var 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 (var 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!");
        var r = [];
        for (i = 0; i < t.length; i++) {
            var 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)) {
            var 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 + ")"
        }
        var 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) {
        var 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() {
        var 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
}();



var a = 5;
var b = 200;


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


//this function is to make regex for event key
function generateRegexForEventKey(id,havenot){
	if(id>=1){
    return "B" + id + "T\\d+";
  }
  else{
  	return "Id cannot be less than 1"
  }
}

function generateRegexForBoolean(value, flag, condition){
	var 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(){
		var str1 = generateRegexForEventRegex();
    var str2 = generateRegexForAttributeRegex();
    var str3 = generateRegexForValueRegex();
    return '(('+ str1 +')('+ str2 + '('+str3 +')+)*)*?';
}


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

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

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

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

//this function is to make regex for attribute array 
function generateRegexForAttribute(attribute,complex){
	var genericAttribute = '(' + attrRegex  + valueRegex +')*';
  var str = ''
  for(var i=0;i<attribute.length;i++){
    if(complex==true){
     str = str + genericAttribute; 
    }
    else{
      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'){
    	var str2 = 'V('
      for(var 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'){
    	var str2 = 'V'
      for(var j=0;j<attribute[i].value.length;j++){
      	str2 = str2 + "(?!"+ attribute[i].value[j] + ")";
      }
      str = str + str2;
    }
    else if(attribute[i].condition=='isb'){
    	var str2 = generateRegexForIntegerRange(attribute[i].value[0],attribute[i].value[1]);      
      str = str + str2;
    }
    else if(attribute[i].condition=='isnb'){
    	var str2 = generateRegexForIntegerRange(attribute[i].value[0],attribute[i].value[1]);      
      str2 = "(!" + str2 + ")";
      str = str + str2;
    }
    else if(attribute[i].condition=='lt'){
    	var str2 = generateRegexForIntegerRange(attribute[i].value[0],attribute[i].value[1]-1);      
      str = str + str2;
    }
    else if(attribute[i].condition=='gt'){
    	var str2 = generateRegexForIntegerRange(attribute[i].value[0]+1,attribute[i].value[1]);      
      str = str + str2;
    }
    else if(attribute[i].condition=='lte'){
    	var str2 = generateRegexForIntegerRange(attribute[i].value[0],attribute[i].value[1]);      
      str = str + str2;
    }
    else if(attribute[i].condition=='gte'){
    	var str2 = generateRegexForIntegerRange(attribute[i].value[0],attribute[i].value[1]);      
      str = str + str2;
    }
    
    
    if(i==attribute.length-1&&complex==true){
    	str = str + genericAttribute;
    }
  }
  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, complex){
  if(key<1){
    return "Id cannot be less than 1";
  }
  var str = ''
  if(complex==true){
    str = '('+ sessionStartRegex +'(('+ eventRegex +'('+ attrRegex + valueRegex +')*)*?)';
  }
  else{
    str = '.*?';
  }
  var str2 = generateRegexForEventKey(key);
  str = str + str2;
  if(attribute.length>=0){
    var str3 = generateRegexForAttribute(attribute, complex);
    str = str + str3;
  }
  if(complex==true){
   str = str + ')'; 
  }
  return str;
  
}

var 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);
});

/* var str = generateRegexForSkippingSteps() + generateRegexForStep('123',attribute);
alert(str); */

//fetch existing attribute value details
var fetchAttributeValueDetails = async function(attributeValueTable, value) {
  var FetchAttributeValueDetailQuery = "select id from "+ attributeValueTable + " where value = '"+ value +"'";
  var result = await pgsql.executeQuery(FetchAttributeValueDetailQuery)
  .then((result) => {
     
    return result;   
  })
  .catch((error)=>{
    logger.error(`error in fetching attribute value ${error}`);
    result = [];
  })
  return result;    
}

 //fetch existing attribute details
var fetchAttributeDetails = async function(attributeTable, key, name) {
  var FetchAttributeDetailQuery = "select id from "+ attributeTable + " where name = '"+ name +"' and key = '"+ key +"'";
  var result = await pgsql.executeQuery(FetchAttributeDetailQuery)
  .then((result) => {
     
    return result;   
  })
  .catch((error)=>{
    logger.error(`error in fetching attribute detail ${error}`);
    result = [];
  })
  return result;    
}


 //fetch data from app Events table
var fetchAppEventsData = async function(appEventTable, key) {
  var AppEventsQuery = "select DISTINCT id from "+ appEventTable + " where name = '"+ key +"'" ;
  //wait for response to get stored in result
  var result = await pgsql.executeQuery(AppEventsQuery)
  .then((result) => {
    return result;   
  })
  .catch((error)=>{
    logger.error(`error => ${error}`);
    result = [];
  })
  return result;  
}

//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;
      }
      //==============start=========================//
      //making date regex and formatting the required parameters to get date regex
      /*var currentDate = new Date(); 
      var day = currentDate.getDate();
      //if date is less than 10, it returns single digit, so converting it to required pattern
      if(day<10){
          day = "0" + day
      }

      var month = currentDate.getMonth() + 1;
      //if month is less than 10, it returns single digit, so converting it to required pattern
      if(month<10){
          month = "0" + month
      }
      //get full year
      var year = currentDate.getFullYear();
      //make the date in format YYYY-MM-DD
      var today = year + "-" + month + "-" + day
      var todayDate = new Date(today);
      var processDate1 = new Date();  // dates used for computing other dates
      processDate1.setDate(todayDate.getDate()-dateDifference) //current - given time
      var finalDate = processDate1
      //if month is less than 10, it returns single digit, so converting it to required pattern
      if((finalDate.getMonth()+1)<10){
          var final = finalDate.getFullYear()+"-0"+(finalDate.getMonth()+1)
      }
      else{
          var final = finalDate.getFullYear()+"-"+(finalDate.getMonth()+1)
      }
      //if date is less than 10, it returns single digit, so converting it to required pattern
      if(finalDate.getDate()<10){
          final = final + "-0" + finalDate.getDate();
      }
      else{
          final = final + "-" + finalDate.getDate();
      }

       
       
      var startdate= new Date(final);
      //get date regex from the computed parameters
      dateRegex = regex.getRegex(startdate, todayDate)*/
      //==============end=========================//
    }
    return epochDifference;
}


async function generateRegexForSteps( app_id, steps, startDate , endDate, sameSession){
	var appEventTable = 'app_events_' + app_id;
  var attributeTable = "attributes_" + app_id //attribute name table
  var attributeValueTable = "attribute_value_" + app_id //attribute value table
  //get date regex for default/provided dates
  var dateRegex = getRegex(startDate, endDate);

  var inputEndDate = new Date(endDate);
  var todaysDate = new Date();
  var complex = false
  inputEndDate = inputEndDate.getTime();
  todaysDate = todaysDate.getTime();
  logger.info(`time => ${inputEndDate} ${todaysDate}`);
  if(inputEndDate != todaysDate){
    complex = true;
  }  
   
  // if(inputEndDate.getDate()==todaysDate.getDate()&&inputEndDate.getMonth()==todaysDate.getMonth()&&inputEndDate.getFullYear()==todaysDate.getFullYear()){
  //   complex = false
  // }

  /* var who = steps.who */
  var what = steps.what
  /* var when = steps.when */
  /* var 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
  var finalRegex = ''
  //regex for all the steps
  var regexSteps = ''
  //initialise epoch time difference for have not conditon
  let epochDifference = 0;
  //loop around all the events coming in what condition
  for(var i = 0; i< what.length; i++){
    //get the operand which the key 
  	var temp = what[i].operand;	
    //fetch event id from the app events table
    var appEventData = await fetchAppEventsData(appEventTable, temp);
    //fetch attribute details from attribute table
    var attribute = []
    if(what[i].attr!=''){
      var getAttributeData = await fetchAttributeDetails(attributeTable, temp, what[i].attr)
      
      // check if value is in array or single object
      if(Array.isArray(what[i].value)){
      	var getAttributeValue = []
        //loop over all the values of value attribute
        for(var j=0;j<what[i].value.length;j++){
          //checking for int
          if(/^\d+$/.test(what[i].value[j])){
              getAttributeValue.push(what[i].value[j]);
          }
          //checking for float
          else if(/^[0-9]+\.[0-9]+$/.test(what[i].value[j])){
              getAttributeValue.push(what[i].value[j]);
          }
          //checking for string
          else if(typeof (what[i].value[j])=='string'){
            let attributeValueId = await fetchAttributeValueDetails(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,
        }]
      }
      else{    	
        var getAttributeValue = []
        logger.info(`VALUE, ${typeof (what[i].value)}`);
        //checking for int
        if(/^\d+$/.test(what[i].value[j])){
            getAttributeValue.push(what[i].value);
        }
        //checking for float
        else if(/^[0-9]+\.[0-9]+$/.test(what[i].value)){
            getAttributeValue.push(what[i].value);
        }
        //checking for string
        else if(typeof (what[i].value[j])=='string'){
          let attributeValueId = await fetchAttributeValueDetails(attributeValueTable, what[i].value[j])
          getAttributeValue.push(attributeValueId[0].id);
        }
        logger.info(`"getAttributeValue":> ${getAttributeValue}`);
        //making attribute object for generate regex for step and attribute
        attribute = [{
        'attribute': getAttributeData[0][0].id,
        'value': 100,
        'condition': what[i].operator,
        }]
      }
    }

    var havenot = false;
    if(what[i].since.have=='hn'){
      havenot = true;
      // epochDifference = computeTimeForHaveNot(what[i]);
    }
    let regexStep = generateRegexForStep(appEventData[0][0].id, attribute, complex);
    let regexSkipData = generateRegexForSkippingData(sameSession, dateRegex, complex);
    if(regexSkipData!=undefined){
      //append skipping data at every step, if it is to be checked in same session, then only required data will be skipped.
      regexSteps = regexSteps + regexSkipData + regexStep;
    }
    else{
      //append skipping data at every step, if it is to be checked in same session, then only required data will be skipped.
      regexSteps = regexSteps  + regexStep;
    }

  }
  // var str4 = generateRegexForSkippingData(sameSession, str1);
  if(havenot==false){
    finalRegex = "eventstring ~ " +  dateRegex + regexSteps;
  }
  else{
    finalRegex = "eventstring !~ " + dateRegex + regexSteps;
  }
  logger.info(`final regexxxx => ${finalRegex}`);
  return finalRegex;
}

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


// var steps = {
//   "who": [
//   ],
//   "what": [
//     {
//       "operand": "Session_Start",
//       "operator": "eq",
//       "value": "true",
//       "category": "Events",
//       "attr": "status",
//       "since": {
//       "have": "h"
//       }
//     },
//     {
//       "operand": "CompanyDetails",
//       "operator": "eq",
//       "value": "true",
//       "category": "Events",
//       "attr": "Name",
//       "since": {
//       "have": "h"
//       }
//     }
//   ],
//   "where": [
//   ],
//   "when": [
//   ]
// }

// var startDate = new Date("2020-04-01");
// var endDate = new Date("2021-04-05");



async function testcase1(){
  var startDate1 = new Date("2020-11-20");
  var endDate1 = new Date("2020-11-20");
  var sameSession1 = false;
  var steps1 = {"what":[{"operand":"CoronaCases","operator":"","value":"","category":"Events","attr":"","since":{"have":"h"}}]}
  var output1 = await generateRegexForSteps('5bebe93c25d705690ffbc758',steps1, startDate1, endDate1, sameSession1)
  logger.info(`output1 => ${output1}`); 
}



async function testcase2(){
  var startDate2 = new Date("2020-11-10");
  var endDate2 = new Date("2020-11-20");
  var sameSession2 = false;
  var steps2 = {"what":[{"operand":"CoronaCases","operator":"","value":"","category":"Events","attr":"","since":{"have":"h"}},{"operand":"CoronaCases","operator":"","value":"","category":"Events","attr":"","since":{"have":"h"}}]}
  var output2 = await generateRegexForSteps('5bebe93c25d705690ffbc758',steps2, startDate2, endDate2, sameSession2)
  logger.info(`output2 => ${output2}`); 
}

async function testcase3(){
  var startDate3 = new Date("2020-11-01");
  var endDate3 = new Date("2020-11-20");
  var sameSession3 = false;
  var steps3 = {"what":[{"operand":"CoronaCases","operator":"eq","value":100,"category":"Events","attr":"Attack","since":{"have":"hn"}}]}
  var output3 = await generateRegexForSteps('5bebe93c25d705690ffbc758',steps3, startDate3, endDate3, sameSession3)
  logger.info(`output3 => ${output3}`);
}

async function testcase4(){
  var startDate4 = new Date("2020-11-01");
  var endDate4 = new Date("2020-11-20");
  var sameSession4 = false;
  var steps4 = {"what":[{"operand":"CoronaCases","operator":"eq","value":10,"category":"Events","attr":"Attack","since":{"have":"h"}},{"operand":"CoronaCases","operator":"eq","value":10,"category":"Events","attr":"Attack","since":{"have":"hn"}}]}
  var output4 = await generateRegexForSteps('5bebe93c25d705690ffbc758',steps4, startDate4, endDate4, sameSession4)
  logger.info(`output4 => ${output4}`);
}


// testcase1();
// testcase2();
testcase3();
testcase4();


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};
