
// VOIP Awesome Click-and-Dial Extension for Google Chrome
// Templates Class JS
//
//  Copyright:  VOIP Awesome Inc, 2021
//  Author:     Jambu Atchison
//  @ Support:  cs@voipawesome.com
//


// Example usage:
// Single use:
/*
 var tpl = new Template('Some text with {@var_example} variables.');
 var out = tpl.output({ 'var_example' : 'Awesome' });
*/


// Loop use:
/*
 var person = { 'fname' : 'Example', 'lname': 'Person', 'phone': '1234567890' };
 var rows = [ person ];
 var tpl = new Template('{@fname},{@lname},{@phone},{@crp_num}');
 for (i = 0; i < 1; i++) {
    tpl.reset();
    var row = tpl.output(rows[i]).missed();
 }
*/



function Template(tpl, ntpl) {
  this.ntpl = ntpl||tpl;
  this.tpl = tpl;
} // end object constructor Template

Template.prototype.new = function(tpl, ntpl) {
  return new Template(tpl||this.tpl, ntpl||this.ntpl);
} // end method new

Template.prototype.reset = function() {
  this.tpl = this.ntpl;
  return this;
} // end method reset

Template.prototype.set = function(k, v, tpl, save=true, robj) {
  //console.log('Template->set(', k, v, ')');
  var i=0, l=0, rxkb, rxkbg, rxkc, rxkcg;
  if ((typeof tpl == 'undefined') || (typeof tpl != 'string') || (tpl == '')) { tpl = this.tpl; if (robj !== false) { robj=true; } }
  if (typeof k != 'undefined') {
    if ((typeof k == 'array') && (k.length > 0) && (typeof v == 'array') && (v.length == k.length)) {
      for (i=0, l=k.length; i<l; i++) {
        if ((typeof k[i] !== 'function') && (typeof v[i] !== 'function')) {
          tpl = this.set(k[i], v[i], tpl, false, false);
        } // end if k[i] && v[i]
      } // end foreach k
    } else if ((typeof k == 'array') && (k.length > 0)) {
      for (i=0, l=k.length; i<l; i++) {
        if (typeof k[i] !== 'function') {
          tpl = this.set(k[i], v, tpl, false, false);
        } // end if k[i]
      } // end foreach k
    } else if (typeof k == 'object') {
      for (i in k){
        if (typeof k[i] !== 'function') {
          tpl = this.set(i, k[i], tpl, false, false);
        } // end if k[i]
      } // end foreach i => v
    } else if (typeof v == 'object') {
      for (i in v){
        if (typeof v[i] !== 'function') {
          if ((typeof k == 'string') && (k != '')) {
            tpl = this.set(i, v[i], tpl, false, false);
            tpl = this.set(k+'_'+i, v[i], tpl, false, false);
          } else {
            tpl = this.set(i, v[i], tpl, false, false);
          } // end if k
        } // end if v[i]
      } // end foreach i => v
    } else if ((typeof k == 'string') && (k != '')) {
      // make sure that we escape non-alphabetic in the key
      if (/[.*+?^${}()|[\]\\]/.test(k)) { k = k.replace(/[.*+?^${}()|[\]\\]/g, '\\\\\\$&'); }
      rxkbg = new RegExp('\\\[@' + k + '\\\]', 'g');
      rxkcg = new RegExp('\\\{@' + k + '\\\}', 'g');
      rxkb = new RegExp('\\\[@' + k + '\\\]');
      rxkc = new RegExp('\\\{@' + k + '\\\}');

      if (typeof v == 'undefined') { v = ''; }
      if ((typeof v !== 'array') && (typeof v !== 'object')) {
        // define our regex exp
        // replace the key with the value in the tpl
        if (rxkb.test(tpl)) { tpl = tpl.replace(rxkbg, v); }
        if (rxkc.test(tpl)) { tpl = tpl.replace(rxkcg, v); }
      } else if ((typeof v == 'array') && (v.length > 0)) {
        for (i=0, l=v.length; i<l; i++) {
          // replace the key with the value in the tpl
          if (rxkb.test(tpl)) { tpl = tpl.replace(rxkb, v[i]); }
          if (rxkc.test(tpl)) { tpl = tpl.replace(rxkc, v[i]); }
        } // end foreach k
        if (rxkb.test(tpl)) { tpl = tpl.replace(rxkbg, ''); }
        if (rxkc.test(tpl)) { tpl = tpl.replace(rxkcg, ''); }
      } // end if v
    } // end if typeof k
  } // end if k
  if (save||robj) { this.tpl = tpl; }
  return (robj ? this : tpl);
} // end method set

Template.prototype.missed = function(tpl, robj) {
  if ((typeof tpl == 'undefined') || (typeof tpl != 'string') || (tpl == '')) { tpl = this.tpl; if (robj !== false) { robj=true; } }
  if ((typeof tpl == 'string') && (tpl != '')) {
    var i=0, l=0, m, mr, mx, rxmb = /\[\@([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\]/g, rxmc = /\{\@([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}/g;
    //console.log(rxmb, tpl);
    if(rxmb.test(tpl)) {
      m = tpl.match(rxmb);
      //console.log(m);
      for (i=0, l=m.length; i<l; i++) {
        if (/[.*+?^${}()|[\]\\]/.test(m[i])) { mr = m[i].replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); }
        mx = new RegExp(mr, 'g');
        //console.log(mx);
        if (mx.test(tpl)) { tpl = tpl.replace(mx, ''); }
      } // end foreach match
    } // end if rxm
    //console.log(rxmc, tpl);
    if(rxmc.test(tpl)) {
      m = tpl.match(rxmc);
      //console.log(m);
      for (i=0, l=m.length; i<l; i++) {
        if (/[.*+?^${}()|[\]\\]/.test(m[i])) { mr = m[i].replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); }
        mx = new RegExp(mr, 'g');
        //console.log(mx);
        if (mx.test(tpl)) { tpl = tpl.replace(mx, ''); }
      } // end foreach match
    } // end if rxm
    //console.log(tpl);
    if (robj) { this.tpl = tpl; }
  } // end if tpl
  return (robj ? this : tpl);
} // end method missed

Template.prototype.output = function(v, tpl, missed=false) {
  if ((typeof tpl == 'undefined') || (typeof tpl !== 'string') || (tpl == '')) { tpl = this.tpl; }
  if (typeof v != 'undefined') { if (((typeof v == 'array') && (v.length > 0)) || (typeof v == 'object')) {
    tpl = this.set(v, null, tpl, false, false);
  } } // end if v
  return tpl;
} // end method output
