//
//  Library containing CSTempl object.  Template formatter.
//
//  Author: Giles Mullen
//  Date:   08/29/2001
//
//  Requires: CS00_Lib_<Language> (i.e. CS00_Lib_English)
//            CS10_Lib_Shared
//            CS20_Lib_Parser
//            CS25_Lib_CSErr
//

var CS_TMPLKWDS = "A+\\d*|U+\\d*|L+\\d*|X+\\d*|N+\\d*|S+\\d*|\\.+\\d*";
var CS_TMPLKWDSRGX = new RegExp( CS_TMPLKWDS, "g" );
var CS_TMPLKWDPRS  = new RegExp( "(\\D+)(\\d*)" );
var CS_TMPLSEPS = " ";
var CS_TMPLRGXSEPS = "\\ ";

//
//    CSTempl
//
CSTempl.ERR_FAM               = 0x4000;
CSTempl.ERR_TEMPLATE_INVALID  = CSTempl.ERR_FAM | 0x0001;
CSTempl.ERR_FORMAT_INVALID    = CSTempl.ERR_FAM | 0x0002;

CSTempl.ERR_TEMPLATE_INVALID_STR  = CS_DTOBJ_ERR_TEMPLATE_INVALID_STR;
CSTempl.ERR_FORMAT_INVALID_STR    = CS_DTOBJ_ERR_FORMAT_INVALID_STR;

function CSTempl_getErrorStringStat( num, ex ) 
{
  var ret = CSErr.ERR_UNDEFINED_STR;
  if (num == CSTempl.ERR_TEMPLATE_INVALID) {
    ret = CSTempl.ERR_TEMPLATE_INVALID_STR;
  } else if (num == CSTempl.ERR_FORMAT_INVALID) {
    ret = CSTempl.ERR_FORMAT_INVALID_STR;
    if (ex != null)
      ret = ret.replace( /\%s/, ex );
  }
  return ret;
}

function CSTempl_getErrorString()
{
  return CSTempl_getErrStrStat( this.err );
}

function CSTempl_getErrStrStat( err ) 
{
  return CSTempl_getErrorStringStat( err.no, err.ex );
}

function CSTempl_normalizeKWDStat( kwdchk )
{
  if (kwdchk.type != CS_KWD)
    return null;
  var res = CS_TMPLKWDPRS.exec( kwdchk.chunk );
  if (res == null)
    return null;
  var i = parseInt( res[2] );
  kwdchk.chunk = kwdchk.chunk.charAt( 0 );
  kwdchk.chunk += res[1].length + ( isNaN( i ) || i == 0 ? 0 : i - 1 );
  return kwdchk;
}

function CSTempl_parseTemplate( templ )
{
  var ret = null;
  this.err = new CSErr( CSTempl.ERR_TEMPLATE_INVALID );
  do {
    var tok = CS_buildTokenArray( templ, CS_TMPLSEPS, CS_TMPLKWDSRGX );
    if (tok == null)
      break;
    var i = 0;
    for (i = 0; i < tok.length; i++)
      if (tok[i].type == CS_KWD) 
        tok[i] = CSTempl_normalizeKWDStat( tok[i] );
    this.err = new CSErr( CSErr.ERR_SUCCESS );
    ret = tok;
  } while (false);
  return ret;
}

function CSTempl_buildRegExp( tok, hard )
{
  var ret = null;
  this.err = new CSErr( CSTempl.ERR_TEMPLATE_INVALID );
  do {
    if (tok == null)
      break;
    if (hard == null)
      hard = false;
    var rgx = "^";
    var i = 0;
    for (i = 0; i < tok.length; i++) {
      if (tok[i].type == CS_SEP) {
        var el = CS_EscapeRegExpLiterals( tok[i].chunk ) 
        if (hard) {
          rgx += "(" + el + ")";
        } else {
          rgx += "([\\W" + el + "]*)";
        }
      } else if (tok[i].type == CS_BRK) {
      } else if (tok[i].type == CS_KWD) {
        var r = null;
        var c = tok[i].chunk.charAt( 0 );
        var n = parseInt( tok[i].chunk.slice( 1 ) ); 
          if (isNaN( n ) || n == 0)
            break;
        switch (c) {
          case "A":
            r = CS_TEXT_ALPHA;
            break;
          case "U":
            r = CS_TEXT_UPPER;
            break;
          case "L":
            r = CS_TEXT_LOWER;
            break;
          case "X":
            r = CS_TEXT_ALNUM;
            break;
          case "N":
            r = CS_TEXT_NUM;
            break;
          case "S":
            r = CS_TEXT_PUNC;
            break;
          case ".":
            r = ".";
            break;
        }
        if (r != null) {
          if (r == ".") {
            rgx += "(.{" + n + "})";
          } else {
            rgx += "([" + r + "]{" + n + "})";
          }
        }
      }
    }
    rgx += "$";
    ret = new RegExp( rgx );
    if (ret != null)    
      this.err = new CSErr( CSErr.ERR_SUCCESS );
  } while (false);
  return ret;
}

function CSTempl_buildTemplStr( toks )
{
  var ret = null;
  do {
    if (toks == null)
      break;
    ret = "";
    var i = 0;
    for (i = 0; i < toks.length; i++) {
      if (toks[i].type == CS_SEP) {
        ret += toks[i].chunk;
      } else if (toks[i].type == CS_KWD) {
        ret += toks[i].chunk.charAt( 0 );
        var n = parseInt( toks[i].chunk.charAt( 1 ) );
        if (n != 0) {
          var j = 1;
          for (j = 1; j < n; j++)
            ret += toks[i].chunk.charAt( 0 );
        }
      }
    }
  } while (false);
  return ret;
}

function CSTempl_evaluate( rgx, toks, val )
{
  var ret = null;
  this.err = new CSErr( CSErr.ERR_UNDEFINED );
  do {
    if (rgx == null || toks == null) {
      this.err = new CSErr( CSTempl.ERR_TEMPLATE_INVALID );
      break;
    }
    var rres = rgx.exec( val );
    if (rres == null) {
      this.err = new CSErr( CSTempl.ERR_FORMAT_INVALID, CSTempl_buildTemplStr( toks ));
      break;
    }
    ret = rres;
    this.err = new CSErr( CSErr.ERR_SUCCESS );
  } while (false);
  return ret;
}

function CSTempl_format( rres, toks, bSeps )
{
  var ret = null;
  this.err = new CSErr( CSErr.ERR_UNDEFINED );
  do {
    if (toks == null) {
      this.err = new CSErr( CSTempl.ERR_TEMPLATE_INVALID );
      break;
    }
    if (rres == null) {
      this.err = new CSErr( CSTempl.ERR_FORMAT_INVALID, CSTempl_buildTemplStr( toks ));
      break;
    }
    if (bSeps == null)
      bSeps = true;
    var res = new Array;
    var i, j = 0, k = 1, v = "";
    res[0] = res[k] = "";
    for (i = 0; i < toks.length; i++) {
      v = "";
      switch (toks[i].type) {
        case CS_SEP:
          j++;
          v = toks[i].chunk;
          break;
        case CS_KWD:
          j++;
          v = rres[j];
          break;
        case CS_BRK:
          k++;
          res[k] = "";
          break;
      }
      res[0] += v;
      if (toks[i].type != CS_SEP)
        res[k] += v;
    }
    ret = res;
    this.err = new CSErr( CSErr.ERR_SUCCESS );
  } while (false);
  return ret;
}

function CSTempl_toString()
{
  return   "err: " + this.err + "\r"
         + "error: " + this.getErrorString() + "\r";
}

function CSTempl_reset()
{
  this.err = new CSErr( CSErr.ERR_UNDEFINED );
}

function CSTempl()
{
  this.reset();
}

CSTempl.prototype.reset          = CSTempl_reset;
CSTempl.prototype.parseTemplate  = CSTempl_parseTemplate;
CSTempl.prototype.buildRegExp    = CSTempl_buildRegExp;
CSTempl.prototype.evaluate       = CSTempl_evaluate;
CSTempl.prototype.format         = CSTempl_format;
CSTempl.prototype.toString       = CSTempl_toString;
CSTempl.prototype.getErrorString = CSTempl_getErrorString;

CSTempl.getErrorString           = CSTempl_getErrStrStat;
