/* vset_test.cc */

#include "vset_query.h"
#include <stdio.h>
#include "data_classes.h"
#include "parser.h"

bool check_switch( string switch_str, int argc, char *argv[] ) {
  for( int i = 0 ; i < argc ; i++ ) {
    if( switch_str == string( argv[i] ) ) return true;
  }
  return false;
}

bool get_bool( bool &b ) {
  string s;
  cin >> s;
  if( s == "true" ) b = true;
  else if( s == "false" ) b = false;
  else return true;
  return false;
}

bool get_int( long int &i ) { return ( scanf( "%ld", &i ) == 0 ); }
bool get_int( int &i ) { return ( scanf( "%d", &i ) == 0 ); }

bool get_num( double &d ) { return ( scanf( "%lf", &d ) == 0 ); }

bool get_matrix( Matrix &M ) {
  int i, j;
  if( get_int( j ) || get_int( i ) ) return true;
  int area = i * j;
  double *d = new double[area];
  for( int n = 0 ; n < area ; n++ ) {
    if( get_num( d[n] ) ) return true;
  }
  M.ReDimension( i, j );
  M << d;
  return false;
}

bool get_vector( ColumnVector &V ) {
  int i;
  if( get_int( i ) ) return true;
  double *d = new double[i];
  for( int n = 0 ; n < i ; n++ ) {
    if( get_num( d[n] ) ) return true;
  }
  V.ReDimension( i );
  V << d;
  return false;
}

bool get_distrib( double &a, double &b, double &c ) {
  return get_num( a ) || get_num( b ) || get_num( c );
}

int main( int argc, char *argv[] ) {
  set_trace_level( TRACE_FEW );
  init_parse();

  if( argc < 2 ) {
    cerr << "Usage : " << argv[0] << " <filename> [-s] [-noflush]\n";
    return 1;
  }
  
  string filename = string( argv[1] );
  if( check_switch( string( "-s" ), argc, argv ) ) {
    token_queue tq( filename );
    tq.flush_out();
    return 0;
  }

  if( check_switch( string( "-noflush" ), argc, argv ) ) {
    flush_on_death = false;
  }

  int nparsed = parse( filename );
  cout << nparsed << " ITEMS PARSED\n";

  if( nparsed == 0 ) {
    exit( 1 );
  }

  list_tags();

  const int nblks = 5;
  set_query_block sq_blk[nblks];

  ColumnVector V;
  Matrix M;

  cerr << "commands 'sq' or 'get'/'set''_''boolean'/'distrib'/'int'/'real'/"
       << "'rmatrix'/'vector'/'triple' <block#> [<value>]\n";
  cerr << "or set_path <path> or set_tag <tag>\n";
  while( 1 ) {
    for( int i = 0 ; i < nblks ; i++ ) {
      cout << i << " : " << sq_blk[i] << "\n";
    }

    string s;
    cerr << "> ";
    cin >> s;
    if( s == "q" || s == "quit" || s == "exit" ) break;
    
    if( s == "sq" ) {
      cerr << vset_query( nblks, sq_blk ) << "ERRORS\n";
    } else if( s == "set_path" ) {
      cin >> s;
      string path;
      cin >> path;
      int blknum;
      if( !sscanf( s, "%d", &blknum ) || blknum < 0 || blknum >= nblks ) 
	cerr << "ERROR\n";
      else {
	if( sq_blk[blknum].set_path( path ) ) cerr << "ERROR\n";
	else {
	  cerr << "DONE\n";
	}
      }
    } else if( s == "set_tag" ) {
      cin >> s;
      string tag_str;
      cin >> tag_str;
      int blknum;
      tag t;
      if( !sscanf( s, "%d", &blknum ) || !sscanf( tag_str, "%ld", &t ) || 
	  blknum < 0 || blknum >= nblks ) 
	cerr << "ERROR\n";
      else {
	if( sq_blk[blknum].set_tag( t ) ) cerr << "ERROR\n";
	else {
	  cerr << "DONE\n";
	}
      }
    } else if( s == "get_int" ) {
      cin >> s;
      long int I;
      int blknum;
      if( !sscanf( s, "%d", &blknum ) || blknum < 0 || blknum >= nblks ) 
	cerr << "ERROR\n";
      else {
	if( sq_blk[blknum].get( I ) ) cerr << "ERROR\n";
	else {
	  cerr << I << "\n";
	}
      }
    } else if( s == "get_real" ) {
      cin >> s;
      double d;
      int blknum;
      if( !sscanf( s, "%d", &blknum ) || blknum < 0 || blknum >= nblks ) 
	cerr << "ERROR\n";
      else {
	if( sq_blk[blknum].get( d ) ) cerr << "ERROR\n";
	else {
	  cerr << d << "\n";
	}
      }
    } else if( s == "get_boolean" ) {
      cin >> s;
      bool b;
      int blknum;
      if( !sscanf( s, "%d", &blknum ) || blknum < 0 || blknum >= nblks ) 
	cerr << "ERROR\n";
      else {
	if( sq_blk[blknum].get( b ) ) cerr << "ERROR\n";
	else {
	  cerr << b << "\n";
	}
      }
    } else if( s == "get_vector" ) {
      cin >> s;
      int blknum;
      if( !sscanf( s, "%d", &blknum ) || blknum < 0 || blknum >= nblks ) 
	cerr << "ERROR\n";
      else {
	if( sq_blk[blknum].get( V ) ) cerr << "ERROR\n";
	else {
	  cerr << V << "\n";
	}
      }
    } else if( s == "get_matrix" ) {
      cin >> s;
      int blknum;
      if( !sscanf( s, "%d", &blknum ) || blknum < 0 || blknum >= nblks ) 
	cerr << "ERROR\n";
      else {
	if( sq_blk[blknum].get( M ) ) cerr << "ERROR\n";
	else {
	  cerr << M << "\n";
	}
      }
    } else if( s == "get_distrib" ) {
      cin >> s;
      double d1, d2, d3, d4;
      int blknum;
      if( !sscanf( s, "%d", &blknum ) || blknum < 0 || blknum >= nblks ) 
	cerr << "ERROR\n";
      else {
	if( sq_blk[blknum].get( d1, d2, d3 ) || sq_blk[blknum].get( d1, d4 ) ) 
	  cerr << "ERROR\n";
	else {
	  cerr << "Mean = " << d1 << "\nMin = " << d2 << "\nMax = " << d3 
	       << "\nStdDev = " << d4 << "\n";
	}
      }
    } else if( s == "set_int" ) {
      cin >> s;
      long int I;
      int blknum;
      if( !sscanf( s, "%d", &blknum ) || blknum < 0 || blknum >= nblks || 
	  get_int( I ) ) 
	cerr << "ERROR\n";
      else {
	if( sq_blk[blknum].set( I ) ) cerr << "ERROR\n";
	else {
	  cerr << I << "\n";
	}
      }
    } else if( s == "set_real" ) {
      cin >> s;
      double d;
      int blknum;
      if( !sscanf( s, "%d", &blknum ) || blknum < 0 || blknum >= nblks 
	  || get_num( d ) ) 
	cerr << "ERROR\n";
      else {
	if( sq_blk[blknum].set( d ) ) cerr << "ERROR\n";
	else {
	  cerr << d << "\n";
	}
      }
    } else if( s == "set_boolean" ) {
      cin >> s;
      bool b;
      int blknum;
      if( !sscanf( s, "%d", &blknum ) || blknum < 0 || blknum >= nblks || 
	  get_bool( b ) ) 
	cerr << "ERROR\n";
      else {
	if( sq_blk[blknum].set( b ) ) cerr << "ERROR\n";
	else {
	  cerr << b << "\n";
	}
      }
    } else if( s == "set_vector" ) {
      cin >> s;
      int blknum;
      if( !sscanf( s, "%d", &blknum ) || blknum < 0 || blknum >= nblks || 
	  get_vector( V ) ) 
	cerr << "ERROR\n";
      else {
	if( sq_blk[blknum].set( V ) ) cerr << "ERROR\n";
	else {
	  cerr << V << "\n";
	}
      }
    } else if( s == "set_matrix" ) {
      cin >> s;
      int blknum;
      if( !sscanf( s, "%d", &blknum ) || blknum < 0 || blknum >= nblks || 
	  get_matrix( M ) ) 
	cerr << "ERROR\n";
      else {
	if( sq_blk[blknum].set( M ) ) cerr << "ERROR\n";
	else {
	  cerr << M << "\n";
	}
      }
    } else if( s == "set_distrib" ) {
      cin >> s;
      double d1, d2, d3, d4;
      int blknum;
      if( !sscanf( s, "%d", &blknum ) || blknum < 0 || blknum >= nblks || get_distrib( d1, d2, d3 ) ) 
	cerr << "ERROR\n";
      else {
	if( sq_blk[blknum].set( d1, d2, d3 ) || sq_blk[blknum].set( d1, d4 ) ) 
	  cerr << "ERROR\n";
	else {
	  cerr << "Mean = " << d1 << "\nMin = " << d2 << "\nMax = " << d3 
	       << "\nStdDev = " << d4 << "\n";
	}
      }
    } else cerr << "ERROR\n";
  }
  return 0;
}
