/*****************************************************
**
**  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 <string>
#include <sstream>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <cstring>
#include "shi.h"

void shi::saveFrameToFile( char *trajectoryFileName ){


    if( !ofile.is_open() ) {
        ofile.open( trajectoryFileName );
    }
    if( !ofile.good() ){
        cerr << "Error, could not open file:" << restartFileName << endl;
        exit( 8 );
    }
    
    
    save( &ofile );

    //ofile.close();

}
unsigned int shi::save( ostream *restartFile ){

    unsigned int bytesWritten;
    int          i, j;

    //required to track the number of bytes written.
    bytesWritten = restartFile->tellp();

    *restartFile << "# " << xSize << endl;
    *restartFile << "# " << ySize << endl;
    *restartFile << "# " << pbcShear << endl;
    
    /* write them out so that x-y axes are lines and line-numbers of the file */
#ifndef FILES_HEX
    for( j = 0; j < ySize; j++ ){
        for( i = 0; i < xSize; i++ ){
            if( spins[i][j] == SPIN_UP ){
                *restartFile << 1 ; 
            }       
            else{
                *restartFile << 0 ;
            }
        }
        *restartFile << endl;
    }
#else
{   
    unsigned int  outBytes;        
    unsigned int  count;
   
    count    = 8;
    outBytes = 0;

    *restartFile << hex;

    for( j = 0; j < ySize; j++ ){
        for( i = 0; i < xSize; i++ ){
            if( spins[i][j] == SPIN_UP ){
                outBytes += count;
            }      
            if( count == 1 ){
                *restartFile  << outBytes;
                outBytes = 0;
                count    = 8;
            }else{
                count = count >> 1;
            }
        }
        if( count != 8 ){
            *restartFile  << outBytes;
            outBytes = 0;
            count    = 8;
        }
        *restartFile << endl; 
    }    

    *restartFile << dec;
} 
#endif


    *restartFile << endl;
    *restartFile << endl;


    bytesWritten = (unsigned int)restartFile->tellp() - bytesWritten;

    return( bytesWritten );
}

void shi::reLoadFromFile( char *fileName ){


    ifstream infile;


    infile.open( fileName );
    if ( !infile.good() ) { //open and test parameter file
        cerr << "Error " << fileName << " not found\n";
        exit(8);
    }

    reLoad( &infile );


    infile.close();
}
void shi::reLoad(istream *inStream){

    char     quantity[2*SHI_MAX_X_SIZE], line[2*SHI_MAX_X_SIZE];
    char     value[2*SHI_MAX_X_SIZE];
    int      dataLine, j, check;

    dataLine = 0;

    nUpSpins = 0;

    //read config file
    while (inStream->peek() != EOF && dataLine < ySize ) {

        inStream->getline( line, 2 * SHI_MAX_X_SIZE * sizeof( char ) );

        //allow whitespace or #-delimited comments
        check = sscanf(line, "%s", quantity);
        if( check == 0 ) {
            continue;
        }
        if( quantity[0] == '#' ){
            check = sscanf(line, "%s%s", quantity, value );
            pbcShear = atoi( value );            
            continue;
        }
        if( quantity[0] == '\n' ){
            continue;
        }


        //have data-line read in so that x-axis reads along the line
        {
            char *pos, c[2];
            unsigned int nibble, count;;

            pos = line;
            c[1]  = '\0';
            j   = 0;
            while( *pos != '\n' && *pos != '\0' && j < xSize ){

#ifndef FILES_HEX
                if( *pos == '0' ){
                    spins[j++][dataLine] = SPIN_DOWN;
                }
                else if( *pos == '1'){
                    spins[j++][dataLine] = SPIN_UP;
                }
 
#else
                count  = 16;
                c[0]   = *pos;
                sscanf( c, "%x", &nibble );
                while( count >= 2 ) {
                    count = count >> 1; //right-shift: equiv to divide by 2
                    if( count & nibble ) {
                        spins[j++][dataLine] = SPIN_UP;    
                        nUpSpins++;       
                    }    
                    else{
                        spins[j++][dataLine] = SPIN_DOWN;
                    }
                    if( j >= xSize ){
                        break;
                    }
                }
#endif
                pos++;

            }
            dataLine++;
        }
    }

    if( dynamicsType ==  SHI_DYNAMICS_KAWASAKI ) {
       fillSpinList();
    }

  return;
}
