#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dynamic.h"
#include "dynamic.util.h"

/* External References into Lex */
extern FILE *yyin;
char   yytext[100];
extern int yylen;

void readDynamicConfig( configuration *currentConfig, 
			char *configName,
			char *configFileName )
{
   int done = 0;
   int tokenVal;

   /* An array to hold the layer configuration names */
   layer definedLayers[ MAX_LAYERS ];
   layer tempLayer;

   
   /* Now open the layer configuration file and ...      */
   /* call intializeLayers() to fill our structure with  */
   /* the shared library names associated with layers    */
   yyin = fopen( "config/Layers.conf", "r" );
   if( yyin == NULL )
   {
      fprintf( stderr, "Error: Cannot Find Layer Config File\n");
      exit( EXIT_FAILURE );
   }	
   initializeLayers( definedLayers );
   
   /* Open The Configuration File and assign it to yyin
      so that lex will parse Dynamic.conf 		     */
   yyin = fopen( configFileName, "r" );
   if( yyin == NULL )
   {
      fprintf( stderr, "Error: Cannot Find %s\n", configFileName );
      exit( EXIT_FAILURE );
   }
   
   /* Now read in the configuration file and fill the data structure */
   /* First we must search for the named configuration */
   while( !done )
   {
      tokenVal = yylex();
      if( tokenVal == ID )
      {
	 if( strcmp( yytext, configName ) == 0 )
	 {
	    done = 1;
	 }	
      }
      if( feof( yyin ) )
      {
	 done = 1;
      }
   }
   
   if( feof( yyin ) )
   {
      fprintf( stderr, "Error: Unable To Find Configuration\n");
      exit( EXIT_FAILURE );
   }
   
   /* We are now at the top of the required configuration, fill
      the data structure */
   
   /* Check for the opening block */	
   if( yylex() != LBLOCK )
   {
      fprintf( stderr, "Error: In Config File\n");
      exit( EXIT_FAILURE );
   }
   
   while( yylex() != RBLOCK )
   {
      if( strcmp( yytext, "configFile" ) == 0 )
      {
	 /* Get the Colon */
	 if( yylex() != COLON )
	 {
	    fprintf( stderr, "Error: In Config File\n");
	    exit(EXIT_FAILURE);
	 }
	 if( yylex() == ID )
	 {
	    strcat( currentConfig->configFile, yytext );
	 }
	 else
	 {
	    fprintf( stderr, "Error: In Config File\n");
	    exit(EXIT_FAILURE);
	 }
      }
      if( strcmp( yytext, "application" ) == 0 )
      {
	 /* Get the Colon */
	 if( yylex() != COLON )
	 {
	    fprintf( stderr, "Error: In Config File\n");
	    exit(EXIT_FAILURE);
	 }
	 
	 if( yylex() == ID )
	 {
	    tempLayer = getLayer( yytext, definedLayers );
	    strcat( currentConfig->appLibrary[0], 
		    tempLayer.library[0] );
	    strcat( currentConfig->appLibrary[1],
		    tempLayer.library[1] );
	 }
	 else
	 {
	    fprintf( stderr, "Error: In Config File\n");
	    exit(EXIT_FAILURE);
	 }
      }
      if( strcmp( yytext, "presentation" ) == 0 )
      {
	 /* Get the Colon */
	 if( yylex() != COLON )
	 {
	    fprintf( stderr, "Error: In Config File\n");
	    exit(EXIT_FAILURE);
	 }
	 
	 if( yylex() == ID )
	 {
	    tempLayer = getLayer( yytext, definedLayers );
	    strcat( currentConfig->preLibrary[0], 
		    tempLayer.library[0] );
	    strcat( currentConfig->preLibrary[1], 
		    tempLayer.library[1] );                                	 
	 }
	 else
	 {
	    fprintf( stderr, "Error: In Config File\n");
	    exit(EXIT_FAILURE);
	 }
	 
      }
      if( strcmp( yytext, "session" ) == 0 )
      {
	 /* Get the Colon */
	 if( yylex() != COLON )
	 {
	    fprintf( stderr, "Error: In Config File\n");
	    exit(EXIT_FAILURE);
	 }
	 if( yylex() == ID )
	 {
	    tempLayer = getLayer( yytext, definedLayers );              
	    strcat( currentConfig->sesLibrary[0], 
		    tempLayer.library[0] );
	    strcat( currentConfig->sesLibrary[1], 
		    tempLayer.library[1] );
	 }
	 else
	 {
	    fprintf( stderr, "Error: In Config File\n");
	    exit(EXIT_FAILURE);
	 }
      }
      if( strcmp( yytext, "transport" ) == 0 )
      {
	 /* Get the Colon */
	 if( yylex() != COLON )
	 {
	    fprintf( stderr, "Error: In Config File\n");
	    exit(EXIT_FAILURE);
	 }
	 if( yylex() == ID )
	 {
	    tempLayer = getLayer( yytext, definedLayers );    
	    strcat( currentConfig->traLibrary[0], 
		    tempLayer.library[0] );
	    strcat( currentConfig->traLibrary[1], 
		    tempLayer.library[1] );
	 }
	 else
	 {
	    fprintf( stderr, "Error: In Config File\n");
	    exit(EXIT_FAILURE);
	 }
      }
      if( strcmp( yytext, "network" ) == 0 )
      {
	 /* Get the Colon */
	 if( yylex() != COLON )
	 {
	    fprintf( stderr, "Error: In Config File\n");
	    exit(EXIT_FAILURE);
	 }
	 if( yylex() == ID )
	 {
	    tempLayer = getLayer( yytext, definedLayers );                            
	    strcat( currentConfig->netLibrary[0], 
		    tempLayer.library[0] );
	    strcat( currentConfig->netLibrary[1], 
		    tempLayer.library[1] );
	 }
	 else
	 {
	    fprintf( stderr, "Error: In Config File\n");
	    exit(EXIT_FAILURE);
	 }
      }
      if( strcmp( yytext, "datalink" ) == 0 )
      {
	 /* Get the Colon */
	 if( yylex() != COLON )
	 {
	    fprintf( stderr, "Error: In Config File\n");
	    exit(EXIT_FAILURE);
	 }
	 if( yylex() == ID )
	 {
	    tempLayer = getLayer( yytext, definedLayers );                        
	    strcat( currentConfig->dlkLibrary[0], 
		    tempLayer.library[0] );
	    strcat( currentConfig->dlkLibrary[1], 
		    tempLayer.library[1] );
	 }
	 else
	 {
	    fprintf( stderr, "Error: In Config File\n");
	    exit(EXIT_FAILURE);
	 }
      }
      if( strcmp( yytext, "physical" ) == 0 )
      {
	 /* Get the Colon */
	 if( yylex() != COLON )
	 {
	    fprintf( stderr, "Error: In Config File\n");
	    exit(EXIT_FAILURE);
	 }
	 if( yylex() == ID )
	 {
	    tempLayer = getLayer( yytext, definedLayers );
	    strcat( currentConfig->phyLibrary[0], 
		    tempLayer.library[0] );
	    strcat( currentConfig->phyLibrary[1], 
		    tempLayer.library[1] );
	 }
	 else
	 {
	    fprintf( stderr, "Error: In Config File\n");
	    exit(EXIT_FAILURE);
	 }
      }
      if( strcmp( yytext, "channel" ) == 0 )
      {
	 /* Get the Colon */
	 if( yylex() != COLON )
	 {
	    fprintf( stderr, "Error: In Config File\n");
	    exit(EXIT_FAILURE);
	 }
	 if( yylex() == ID )
	 {
	    tempLayer = getLayer( yytext, definedLayers );                        
	    strcat( currentConfig->chaLibrary[0],
		    tempLayer.library[0] );
	    strcat( currentConfig->chaLibrary[1],
		    tempLayer.library[1] );
	 }
	 else
	 {
	    fprintf( stderr, "Error: In Config File\n");
	    exit(EXIT_FAILURE);
	 }
      }
      if( strcmp( yytext, "reports" ) == 0 )
      {
	 /* Get the colon */
	 if( yylex() != COLON )
	 {
	    fprintf( stderr, "Error: In Config File\n");
	    exit(EXIT_FAILURE);
	 }
	 if( yylex() == ID )
	 {
	    tempLayer = getLayer( yytext, definedLayers );                        
	    strcat( currentConfig->repLibrary[0],
		    tempLayer.library[0] );
	 }
	 else
	 {
	    fprintf( stderr, "Error: In Config File\n");
	    exit(EXIT_FAILURE);
	 }
      }
   }
   
   /* Now that we've read in the entire configuration */
   /* and the format of the file seems correct name   */
   /* the configuration.				   */
   strcpy( currentConfig->configName, configName );
}


void initializeConfiguration( configuration *config )
{
   /* Put the subdirectory of each layer in the */
   /* correct locations 			     */

   strcpy( config->configFile, "config/" );
   
   strcpy( config->appLibrary[0], "appLayer/" );
   strcpy( config->appLibrary[1], "appLayer/" );
   
   strcpy( config->preLibrary[0], "preLayer/" );
   strcpy( config->preLibrary[1], "preLayer/" );
	
   strcpy( config->sesLibrary[0], "sesLayer/" );
   strcpy( config->sesLibrary[1], "sesLayer/" );

   strcpy( config->traLibrary[0], "traLayer/" );
   strcpy( config->traLibrary[1], "traLayer/" );

   strcpy( config->netLibrary[0], "netLayer/" );
   strcpy( config->netLibrary[1], "netLayer/" );

   strcpy( config->dlkLibrary[0], "dlkLayer/" );
   strcpy( config->dlkLibrary[1], "dlkLayer/" );

   strcpy( config->phyLibrary[0], "phyLayer/" );
   strcpy( config->phyLibrary[1], "phyLayer/" );

   strcpy( config->chaLibrary[0], "channels/" );
   strcpy( config->chaLibrary[1], "channels/" );

   strcpy( config->repLibrary[0], "reports/" );
}

void initializeLayers( layer layerArray[ MAX_LAYERS ] )
{
   int tokenVal;
   int i = 0;

   tokenVal = yylex();

   while( !feof( yyin ) )
   {
      if( tokenVal == ID )
      {
	 strcpy( layerArray[i].layerName, yytext );
      }
      else
      {
	 fprintf( stderr, "Layers.conf Incorrect Format at %s\n",
		  yytext );
	 exit( EXIT_FAILURE );
      }

      if( yylex() != COLON )
      {
	 fprintf( stderr, "Layers.conf Incorrect Format at %s\n",
		  yytext );		
	 exit( EXIT_FAILURE );
      }
		
      if( yylex() == ID )
      {
	 strcpy( layerArray[i].library[0], yytext );
      }
      else
      {
	 fprintf( stderr, "Layers.conf Incorrect Format at %s\n",
		  yytext );		
	 exit( EXIT_FAILURE );
      }
      if( yylex() == ID )
      {
	 strcpy( layerArray[i].library[1], yytext );
      }
      else
      {
	 fprintf( stderr, "Layers.conf Incorrect Format at %s\n",
		  yytext );		
	 exit( EXIT_FAILURE );
      }
      i++;
      tokenVal = yylex();

   }
}

layer getLayer( char *layerName, layer layers[MAX_LAYERS] )
{
   int i;

   i = 0;
   while( i < MAX_LAYERS && 
	  strcmp( layers[i].layerName, layerName ) != 0 )
   {
      i++;
   }
	
   if( i == MAX_LAYERS )
   {
      fprintf( stderr, "Error: Layer %s Not Defined\n", layerName );
      exit( EXIT_FAILURE );
   }
	
   return (layers[i]);
}
