var MAX_EVAL_COUNT = 10;
var phVars;
var nCount;


function Template( sHtmlTemplate )
{
  this.getBlock = Template_getBlock;
  this.init = Template_init;
  this.evalString = Template_evalString;
  this.getVarValue = Template_getVarValue;
  this.setVarValue = Template_setVarValue;

  this.sHtmlTemplate = sHtmlTemplate;
  this.phVars = new Array();

  this.init();
}

function Template_getBlock( p_sPattern1, p_sPattern2 )
{
  var sBlockId = p_sPattern1 + '|' + p_sPattern2;

  var raTab = new Array();
  //alert( 'this.phBlocks[ ' + sBlockId + ' ]= ' + this.phBlocks[ sBlockId ] );
  if( this.phBlocks[ sBlockId ] != null )
  {
    //alert( sBlockId );
    raTab.push( this.phBlocks[ sBlockId ].join( ' ' ) );
  }
  else
  {
    var sPattern1 = p_sPattern1;

    for( var i in this.phBlocks[ 'aBlockOrder' ] )
    {
      var sKey = this.phBlocks[ 'aBlockOrder' ][ i ];
      //alert( sKey );
      var aTmp = sKey.split( '|' );

      var sPat1 = aTmp[0];
      var sPat2 = aTmp[1];

      if( sPat1 == sPattern1 )
      {
        var sBlockId = sPat1 + '|' + sPat2;
        raTab.push( this.phBlocks[ sBlockId ].join( ' ' ) );

        sPattern1 = sPat2;

        if( sPat2 == p_sPattern2 )
        {
          break;
        }
      }
    }
  }
  //alert( 'before=' + raTab );
  for( var nI = 0; nI < raTab.length ; nI++ )
  {
    raTab[ nI ] = this.evalString( raTab[ nI ] );
  }
  //alert( 'after=' + raTab );
  //alert( raTab.join( ' ') );
  return raTab.join(' ');
}

function Template_init()
{
  this.phBlocks = new Array();

  var sStartBlock = '';
  var sEndBlock   = '';

  this.phBlocks[ 'aBlockOrder' ] = new Array();

//   my $rAddCarriage = engine::regex::get('(<!--[\s\w=\"\-]+?-->)');
//   my $rEmptyLine   = engine::regex::get('^\s*$');
//   my $rGetTag      = engine::regex::get('^<!--([\s\w=\"\-]+)-->$');
//   my $rTab         = engine::regex::get('\t');
//   my $rLineFeed    = engine::regex::get('\r');

  var paBlock = new Array();
  this.sHtmlTemplate = new String( this.sHtmlTemplate ).replace( /<!--/g, "\n<!--" );
  this.sHtmlTemplate = new String( this.sHtmlTemplate ).replace( /-->/g, "-->\n" );
  
  var asLines = this.sHtmlTemplate.split( '\n' );
  //  alert( this.sHtmlTemplate );
  //  alert( asLines );
  for( var i in asLines )
  {
    var sLine = asLines[i];
    //alert( sLine );
    if( !sLine.match( /^\s*$/ ) && sLine.match( /^<!--([\s\w=\"\-]+)-->$/ ) )
    {
      var sEndBlock = RegExp.$1;

      var sBlockId = sStartBlock + '|' + sEndBlock;

      this.phBlocks[ sBlockId ] = paBlock;
      //alert( sBlockId + ' paBlock=' + paBlock );
      this.phBlocks[ 'aBlockOrder' ].push( sBlockId );

      paBlock = new Array();

      sStartBlock = sEndBlock;
    }

    if( sLine.match( /\[LANG_(.*?)\]/ ) )
      this.setVarValue("LANG_"+RegExp.$1, getUserMessage("LANG_"+RegExp.$1));

    paBlock.push( sLine );
  }

  sBlockId = sStartBlock + '|';

  this.phBlocks[ sBlockId ] = paBlock;
  this.phBlocks[ 'aBlockOrder' ].push( sBlockId );

  for( var t in this.phBlocks )
  {
    //alert( 'this.phBlocks[ ' + t + ']=' + this.phBlocks[t] );
  }
}

function Template_evalString( p_sString )
{
  nCount = 0;
  phVars = this.phVars;

  return new String( p_sString ).replace( /([^\\])\[(\w+)\]|^\[(\w+)\]/g,
                                          function ( str, x1, x2, x3 )
                                          {
                                            return replaceString( x1, x2, x3 )
                                            //return '1';
                                          } );
}

function replaceString( p_sPrefix, p_sVar, p_sVar2 )
{
  //alert( p_sPrefix + ',' + p_sVar + ',' + p_sVar2 );

  nCount += 1;

  if( p_sVar == '' )
  {
    p_sVar = p_sVar2;
  }

  var r_sVal = phVars[ p_sVar ];

  //alert( 'p_sVar=' + p_sVar + ' r_sVal=' + r_sVal );

  if( nCount >= MAX_EVAL_COUNT )
  {
    return p_sPrefix + r_sVal;
  }

  return p_sPrefix + new String( r_sVal ).replace( /([^\\])\[(\w+)\]|^\[(\w+)\]/g,
                                                   function ( str, x1, x2, x3 )
                                                   {
                                                     return replaceString( x1, x2, x3 )
                                                   } );
}

function Template_getVarValue( sVar )
{
  return this.phVars[ sVar ];
}

function Template_setVarValue( sVar, sValue )
{
  this.phVars[ sVar ] = sValue;
}
