/*
** build.c
*/

#include <stdio.h>
#include <malloc.h>
#include "peek.h"

/*
** image_alloc()
** sets image to point to newly allocated space for an image
*/
int
image_alloc(Image **image) {
  *image = (Image *) malloc(sizeof(Image));
  if (NULL == *image) {
    sprintf(err, "image_alloc: couldn't alloc for new image!!\n");
    return(-1);
  }
  else
    return(0);
}

/*
** part_alloc()
** sets part to point to a newly allocated space for a part
*/
int
part_alloc(Part **part) {
  *part = (Part *) malloc(sizeof(Part));
  if (NULL == *part) {
    sprintf(err, "part_alloc: couldn't alloc for new part!!\n");
    return(-1);
  }
  else
    return(0);
}

/*
** piece_alloc()
** sets piece to point to a newly allocated space for a piece
*/
int
piece_alloc(Piece **piece) {

  *piece = (Piece *) malloc(sizeof(Piece));
  if (NULL == *piece) {
    sprintf(err, "piece_alloc: couldn't alloc for new piece!!\n");
    return(-1);
  }
  return(0);
}

/*
** build_part()
** given info for new part, does the part_alloc(), puts in the info,
** returns a pointer to it. Sets thought and result to NULL.
** Does not set the ID field because that is the job of tag().
*/
int
build_part(Part **part, int d, int done, int spare, float *color, 
	   float *coord) {
  int i;
  char err2[ERRSTRLEN];
  
  if (part_alloc(part)) {
    sprintf(err2, "build_part: couldn't do part_alloc()\n");
    strcat(err, err2); return(-1);
  }
  else {
    (*part)->d = d;
    (*part)->done = done;
    for (i=0; i<COLORS; ++i)
      (*part)->color[i] = (color ? color[i] : 0);
    for (i=0; i<= MAXSPACED - 1; ++i) {
      (*part)->coord[i] = (coord ? coord[i] : 0);
      (*part)->coord_hold[i] = (coord ? coord[i] : 0);
    }
    bzero((*part)->coord_view, THREE*sizeof(float));
    bzero((*part)->coord_screen, TWO*sizeof(float));
    bzero((*part)->norm, MAXSPACED*sizeof(float));
    (*part)->result = NULL;
    (*part)->thought = NULL;
    return(0);
  }
}

/*
** build_piece()
** given info for new piece, does the piece_alloc(), puts in the info 
** (piece_d), returns a pointer to it.  Sets thought and result to NULL, 
** ID_count to 0. Sets xform matrix to identity.
*/
int
build_piece(Piece **piece, int piece_d, int space_d, float *color, 
	    float **xform) {
  int i,j;
  char err2[ERRSTRLEN];
  
  if (piece_alloc(piece)) {
    sprintf(err2, "build_piece: couldn't do piece_alloc()\n");
    strcat(err, err2); return(-1);
  }
  (*piece)->piece_d = piece_d;
  (*piece)->space_d = space_d;
  (*piece)->xform = (Matx *) malloc(sizeof(Matx));
  for (i=0; i<=MAXSPACED; ++i)
    for (j=0; j<=MAXSPACED; ++j)
      (*piece)->xform->m[i][j] = (xform ? xform[i][j] : (i == j ? 1 : 0));
  (*piece)->catalog = (Part **) malloc(PARTSPERPIECE * sizeof(Part *));
  (*piece)->ID_count = 0;
  (*piece)->cat_size = 1;
  (*piece)->offset = NULL;
  (*piece)->result = NULL;
  (*piece)->thought = NULL;
  for (i=0; i<COLORS; ++i)
    (*piece)->color[i] = (color ? color[i] : 0);
  return(0);
}

/*
** tag()
** tags given part with an ID unique for that piece, adds that part to 
** the piece's catalog.
*/
int
tag(Piece *piece, Part *part) {
  int i, n_elem;
  Part **new_cat;
  char err2[ERRSTRLEN];

  part->ID = piece->ID_count;
  piece->catalog[piece->ID_count] = part;
  ++(piece->ID_count);
  if (piece->ID_count > piece->cat_size * PARTSPERPIECE) {
    printf("**** expanding catalog (%d to %d), does this work? ... \n",
	   piece->cat_size, piece->cat_size+1);
/*    ++(piece->cat_size);
      new_cat = realloc(piece->catalog, 
		      piece->cat_size * PARTSPERPIECE * sizeof(Part *)); */
    n_elem = piece->cat_size * PARTSPERPIECE;
    new_cat = (Part **) calloc(n_elem + PARTSPERPIECE, sizeof(Part *));
    if (NULL == new_cat) {
      sprintf(err2, "tag: couldn't alloc space for new cat; cat_size = %d\n",
	      piece->cat_size);
      strcat(err, err2); return(-1);
    }
    memcpy(new_cat, piece->catalog, n_elem *sizeof(Part *));
    free(piece->catalog);
    piece->catalog = new_cat;
    (piece->cat_size)++;
  }
  return(0);
}
