/*****************************************************
**
**  S-PRES Copyright (c) 2010
**
**  Joshua T Berryman
**
**  This file is part of S-PRES
**
**  S-PRES is Free software: you can redistribute it and/or modify
**  it under the terms of the GNU General Public License as published by
**  the Free Software Foundation, either version 3 of the License, or
**  (at your option) any later version.
**
**  S-PRES is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**  GNU General Public License for more details.
**
**  You should have received a copy of the GNU General Public License
**  along with this program.  If not, see <http://www.gnu.org/licenses/>.
**
**  If you make use of this program for research 
**  resulting in a publication, please cite:
**
**  Joshua T Berryman and Tanja Schilling, 
**  Sampling rare events in nonequilibrium and nonstationary systems. 
**  
**  J Chem Phys, 133(24):244101, Dec 2010.
**
******************************************************/
// 
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include "shi.h"
#include "shiStats.h"

double shiStats::calcStat( shiStatsOp *s, shi *state ) {

    double value;


    switch( s->myOp ) {
      case SHI_STATSOP_LARGEST_NUCLEUS:
        value = double( largestClusterSize( state, &s->logFile ) );
        break;
      case SHI_STATSOP_ENERGY:
        value = state->systemEnergy();
        break;
      case SHI_STATSOP_NUM_UPSPINS:
        value = state->count_nUpSpins();
        break;
      case SHI_STATSOP_NUM_BURIED:
        value = double( numberBuried( state ) );
        break;
      case SHI_STATSOP_STRUCTURE_FACTOR:
        value = double( structureFactor( state ) );
        break;
      case SHI_STATSOP_CLUSTER_MOMENT:
        value = double( state->clusterMoment() );
        break;
      case SHI_STATSOP_LARGEST_CLUSTER:
        value = double( state->largestCluster() );
        break;
      case SHI_STATSOP_N_HOPS:
        value = double( state->nHops );
        break;
      case SHI_STATSOP_N_ASEP_FLUXES:
        value = double( state->nFluxEvents );
        break;
      default:
          cerr << "Error! stats op not recognised: " << s->nameInHeader << ":" << s->myOp << endl;
          exit( 8 );
    }
    
    return( value );

}



void shiStats::requestOperation( string name, int id, string logFileName ){
    requestOperation( name, shiOpId(id), logFileName );
}
void shiStats::requestOperation( string name, shiOpId id, string logFileName ){
   
    shiStatsOp *s;

    //a little error checking
    if( opsRequested >= SHI_STATSOP_NUM_OPS ){
      cerr << "Error: requested too many stats operations" << endl;
      cerr << "Ignoring operation: " << name << endl;
      return;
    }

    s = &opsList[opsRequested];
    s->setOp( name, id, logFileName );
    opsRequested++;
}

void shiStats::calcFrameStats( shi *shiState ){
        
    double   value;
    shiStatsOp  *s;
    int      opIndex;

    haveClusters = false;

    for( opIndex = 0; opIndex < opsRequested; opIndex++ ) {

        s           = &opsList[opIndex];
        value       = calcStat( s, shiState );
        opsValues[opIndex] = value;

    }

}

void shiStats::printStatsHeader(){
        
    int opIndex;        
    cout << "#";
    for( opIndex = 0; opIndex < opsRequested; opIndex++ ) {
        cout << opsList[opIndex].nameInHeader << " ";
    }
    cout << endl;
}

void shiStats::printStatsSnap(){
        
    int opIndex;        
    //cout << frameIndex << " ";
    for( opIndex = 0; opIndex < opsRequested; opIndex++ ) {
        cout << opsValues[opIndex] << " ";
    }
    cout << endl;
}
