// version 1.0.0 14Feb2018
#include "stplugin.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mycalcsw.h"

//Unicode characters can make Stata names up to 32*4+1 bytes
STDLL stata_call(int argc, char *argv[])
{
    ST_int       first, last, nVars, nObs  ; 
    ST_int       i  ; 
    ST_retcode   rc ;
    char         bname[130], vname[130], nname[130], msg[81] ;
    ST_double    *bmat, *vmat  ;

    bmat  = NULL ;
    vmat  = NULL ;

// Put number of variables in varlist in to nVars
    nVars = SF_nvars() ;
// Put the first observation in sample into first
    first = SF_in1();
// Put the last observation in sample into last
    last  = SF_in2();

// Check that arguments are not too long for buffers
    for(i=0; i<3; i++) {
        if (strlen(argv[i])>129) {
            sprintf(msg, "Argument %d is more than 129 bytes long\n",i+1);
            SF_error(msg) ;
            return((ST_retcode) 198) ;
        }
    }
// Store arguments into strings 
// NB: No more checking required
//     SPI functions will return nonzero codes if arguments specify bad names
    strcpy(bname,argv[0]) ;
    strcpy(vname,argv[1]) ;
    strcpy(nname,argv[2]) ;

    // Allocate space for bmat and initialize to 1 x c matrix of zeros
    rc = InitCmat(&bmat, (ST_int) 1, nVars ) ; 
    if (rc>0) {
        return( rc ) ;
    }
    
    // Allocate space for vmat and initialize to nVars x nVars matrix of zeros
    rc = InitCmat(&vmat, nVars, nVars ) ; 
    if (rc>0) {
        free(bmat) ;
        return( rc ) ;
    }

    // Put sample averages in bmat and number of obs in n
    rc = MyAve(bmat, first, last, nVars, &nObs) ;
    if(rc>0) {
        free(bmat) ;
        free(vmat) ;
        return(rc) ;
    }

    // Put VCE in vmat
    rc = MyV(bmat, vmat, first, last, nVars, nObs) ;
    if(rc>0) {
        free(bmat) ;
        free(vmat) ;
        return(rc) ;
    }

    // Copy sample averages from bmat to Stata matrix bname
    rc = CopyCtoStataMatrix(bmat, bname, (ST_int) 1, nVars) ;
    if(rc>0) {
        free(bmat) ;
        free(vmat) ;
        return(rc) ;
    }

    // Copy VCE from vmat to Stat matrix vname
    rc = CopyCtoStataMatrix(vmat, vname,  nVars, nVars) ;
    if(rc>0) {
        free(bmat) ;
        free(vmat) ;
        return(rc) ;
    }

    // Copy number of obs from nObs to nname
    rc = SF_scal_save(nname, (ST_double) nObs);
    if(rc>0) {
        free(bmat) ;
        free(vmat) ;
        return(rc) ;
    }

    free(bmat) ;
    free(vmat) ;
    return(rc) ;
}