#include <euredit_sys.h>


int main (int argc, char *argv[])
{
    long          rec1 = 0;
    long          nrec = 89;
    long          nvar = 8;
    long          dblk = 89;
    double       *data, *idata;
    long          ninde = 6;
    long          inde[] = {1,2,4,5,6,7};
    long          dep = 3;
    long          ws = 4;
    double        w[89];
    long          ncat[]={0,2,2,2,3,5,10,11};
    double        tol = 1.0e-3;
    long          maxit = 20;
    double        c;
    long          mnc = 1;
    long          mns = 10;
    int           root;
    long          opt_build = 1; /* if 1, store dependent values at leaf nodes.       */
    long          opt_rand = 0;  /* if 1, use random number to resolve flow problems. */
    long          opt_score;     /* imputation type: 1 - mean; 2 - mode; 3 - random.  */
    long          seed[5];
    double       *results, *acc, *dwork;
    int           info;
    long          idblk = 11;
    const char    file[] = "complete.dat";
    const char    ifile[] = "impute.dat";
    const char    sfile[] = "waid_save";
/*  N.B. Categories in data labelled 1,2,3,..,n for n categories. */


    if (!(data = (double *)malloc (dblk*nvar * sizeof (double))))
    {
        printf ("Memory allocation failure.\n");
        exit (2);
    }

    if (!(idata = (double *)malloc (idblk*nvar * sizeof (double))))
    {
        printf ("Memory allocation failure.\n");
        free (data);
        exit (2);
    }

    
    {/* Read data: */
        FILE         *fp;
        long          i, j;
        
        
        if ((fp = fopen (file, "r")) == NULL)
        {
            free (data);
            free (idata);
            printf ("Error cannot open data file: %s.\n", file);
            exit (2);
        }

        for (i=0; i<dblk; ++i)
        {
            for (j=0; j<nvar; ++j)
            {
                fscanf(fp, "%lf", &data[i*nvar+j]);

                /* Add 1 to zero-based categories: */
                if (j==6 || j==7)
                    data[i*nvar+j]++;
            }
            fscanf(fp, "\n");
        }
        fclose(fp);

        
        if ((fp = fopen (ifile, "r")) == NULL)
        {
            free (data);
            free (idata);
            printf ("Error cannot open data file: %s.\n", ifile);
            exit (2);
        }

        for (i=0; i<idblk; ++i)
        {
            for (j=0; j<nvar; ++j)
            {
                fscanf(fp, "%lf", &idata[i*nvar+j]);
            }
            fscanf(fp, "\n");
        }
        fclose(fp);
    }
    

    /* Recommended constant value for weight function:
       1 = OLS,
       2 = Andrew's Sine
       3 = Tukey Biweight
       4 = Huber MINMAX
    */
    if (ws == 1)
        c = 0.0;
    else if (ws == 2)
        c = 5.5;
    else if (ws == 3)
        c = 5.5;
    else
        c = 1.0;


    info = 0;
    waid_tree (rec1, nvar, nrec, dblk, data, NULL, ninde, inde, dep, ws, w, ncat,
               tol, maxit, c, mns, mnc, opt_build, &root, &info);

    if (info == -999)
	{
		printf (" Obtain a licence from NAG to run this component.\n");
		free (data);
		exit (2);
	}
	else if (info > 0)
    {
        printf ("waid_tree error code: %i.\n", info);
        free (data);
        exit (2);
    }
    else if (info < 0)
    {
        printf ("waid_tree warning code: %i.\n", info);
    }


    info = 0;
    
    tree_save (root, sfile, &info);
    if (info > 0)
    {
        printf ("tree_save error code: %i.\n", info);
        tree_free (root);
        exit (2);
    }
    else if (info < 0)
    {
        printf ("tree_save warning code: %i.\n", info);
    }


    free (data);
    tree_free (root);

    root = info = 0;
    tree_load (&root, sfile, &info);
    if (info > 0)
    {
        printf ("tree_load error code: %i.\n", info);
        exit (2);
    }

    /* Imputed values: */
    if (!(dwork = (double *)malloc (idblk*2 * sizeof (double))))
    {
        free (idata);
        tree_free (root);
        exit (2);
    }

    results = dwork;
    acc = dwork + idblk;

    set_rand_seed (34, seed);

    info = 0;

    /* Imputation using mean values: */
    opt_score = 1;
    
    tree_score (rec1, nvar, idblk, idblk, idata, NULL, root, opt_rand, opt_score,
                seed, results, acc, &info);
    if (info > 0)
    {
        printf ("tree_score error code: %i.\n", info);
        free (idata);
        free (dwork);
        tree_free (root);
        exit (2);
    }
    else if (info < 0)
    {
        printf ("tree_score warning code: %i.\n", info);
    }

    {
        int i;
        for (i=0; i<idblk; ++i)
            printf ("%8.4f (%E)\n", results[i], acc[i]);
    }

    /* Imputation using modal class values: */
    opt_score = 2;
    
    tree_score (rec1, nvar, idblk, idblk, idata, NULL, root, opt_rand, opt_score,
                seed, results, acc, &info);
    if (info > 0)
    {
        printf ("tree_score error code: %i.\n", info);
        free (idata);
        free (dwork);
        tree_free (root);
        exit (2);
    }
    else if (info < 0)
    {
        printf ("tree_score warning code: %i.\n", info);
    }

    {
        int i;
        for (i=0; i<idblk; ++i)
            printf ("%8.4f (%E)\n", results[i], acc[i]);
    }

    /* Imputation using random class values: */
    opt_score = 3;
    
    set_rand_seed (34, seed);

    tree_score (rec1, nvar, idblk, idblk, idata, NULL, root, opt_rand, opt_score,
                seed, results, acc, &info);
    if (info > 0)
    {
        printf ("tree_score error code: %i.\n", info);
        free (idata);
        free (dwork);
        tree_free (root);
        exit (2);
    }
    else if (info < 0)
    {
        printf ("tree_score warning code: %i.\n", info);
    }

    {
        int i;
        for (i=0; i<idblk; ++i)
            printf ("%8.4f (%E)\n", results[i], acc[i]);
    }

    free (idata);
    free (dwork);

    return 0;
}
