/* Get Akaike information criterion corrected  */

/*      GENERAL DESCRIPTION
	This program reads in a set of parameters, a log likelihood, and a frequency matrix
	for a rating scale. It calculates the Akaike information criterion corrected from these
	data. Parameters include the number of stimuli and responses and the decision rule.

	  DECISION RULE   PR1   PR2    PR3
	        11         1     0      0
		12         0     1      0
		13         0     0      1
		14         f    -1      0
		15         f     0     -1
		16         0     f     -1
		17         f     f     -1
		(f=free; -1 means probability determined by free PR)
  

        INITIALIZATION

        Input to the program is via a file (*.AICc) with the following
        control parameters in free form.
          header: a general header of up to 50 characters
	  nums: The number of stimuli 
	  numr: The number of responses
	  decr_r: Decision rule (11=Rule 1 only; 12=Rule 2 only; 13=Rule 3 only; 14=Rules 1 and 2;
	                         15=Rules 1 and 3;16=Rules 2 and 3; 17=all three rules)
	  S-R matrix with nums rows and numr columns                                          */


// Includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <gpklib.h>
#include "gpklib/NaN.h"

// Function declarations
void open_file( char gen_name [ 50 ] );
void get_AICc ( );


// Read routimes
static float ReadFloat(FILE* inPtr) {
    char ahold[1024];
    bool ok = fscanf ( inPtr, "%s", ahold ) == 1;
    assert(ok);
    double rv = safe_atof(ahold);
    assert( finite(rv) );
    return rv;
}

static int ReadInt(FILE* inPtr) {
    char ahold[1024];
    bool ok = fscanf ( inPtr, "%s", ahold ) == 1;
    assert(ok);
    int rv = safe_atoi(ahold);
    assert( rv != INT_NAN && rv != INT_Max && rv != INT_Min);
    return rv;
}

// Globals
    FILE *inPtr;

int main( int argc, char *argv[  ] )
{

    if ( argc < 2 ) exit( 1 );
    open_file( argv [ 1 ] );
    get_AICc( );
    return 0;
}

void open_file( char gen_name [ 50 ] )
{
    char sf_name[ 50 ];
    short open_indic = 0;

    while ( open_indic == 0 ) {
	strcpy( sf_name, gen_name );
	strcat( sf_name, ".aicc" );
	inPtr = fopen( sf_name, "a+" );
	if ( inPtr == NULL ) {
	    printf( "\n Error opening input file %s\n", sf_name );
	    printf( " get another name.\n" );
	    printf( "\n Program quitting." );
	    exit( 0 );
        }
	else  open_indic = 1;
    }
}

// Read in the parameters, logP, and data; calculate AICc
void get_AICc ( )
{

    int dec_r, freepars, numobs = 0, numr, nums;
    double AICc, logP;
    char header [ 1024 ];


    /* Read control variables from file */
    bool ok = fscanf ( inPtr, "%s", header ) == 1;
    assert (ok);

    nums = ReadInt( inPtr );
    numr = ReadInt( inPtr );
    dec_r = ReadInt( inPtr );

    /* Calculate other needed values */
    freepars = 2 * ( nums + numr - 1 );
    if ( dec_r > 13 ) freepars++;
    if ( dec_r == 17 ) freepars++;

    // Get number of observations
    for ( int i = 0; i < nums; i++ )
      for ( int j = 0; j < numr; j++ ) numobs += ReadInt( inPtr );
    // Calculate AICCc
    AICc = 2 * ( freepars - logP ) + ( 2 * freepars * ( freepars + 1 ) / ( numobs - freepars - 1 ) );
    fprintf( inPtr, "\n\n\n AICc = %10.4f", AICc );
    fclose( inPtr );
}
