/************************* 
 * Owen Sullivan
 * CPSC 2310-002
 * opsulli@clemson.edu
*************************/

#ifndef FUNCTIONS_
#define FUNCTIONS_

#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>

// Buffer struct with values matching header struct, but using large char
// arrays instead of small char arrays or ints to hold comments that might
// be read from input file
typedef struct buffer {

    char type[100];
    char width[100];
    char height[100];
    char maxColor[100];

} buffer_t;

// Header struct with values for PPM type, image width, image height,
// and image maxColor
typedef struct header {

    char type[3];
    int width;
    int height;
    int maxColor;

} header_t;

// Pixel struct with unsigned chars for r, g, and b values in a single pixel
typedef struct pixel {

    unsigned char r;
    unsigned char g;
    unsigned char b;

} pixel_t;

/* Parameters: inFile - FILE pointer that points to all of the image data
                        in the input PPM file
 * Return:     header - header_t object containing header data
 * This function reads the header data from the input PPM file and returns
 * a struct with all the header data (minus removed comments).
*/
header_t readHeader(FILE *inFile);

/* Parameters: outFile - FILE pointer that points to the new PPM image being
                         created
               header - header_t object containing header data
 * Return:     N/A - function is of type void
 * This function writes the header data from the input PPM file (minus removed
 * comments) to a new PPM file.
*/
void writeHeader(FILE *outFile, header_t header);

/* Parameters: buffer - buffer_t object that was used to read header data 
                        that may have contained comments
 * Return:     header - header_t object containing input header data
 * This function converts a buffer object that may have been used to discard 
 * comments to a header object with integers instead of char arrays.
*/
header_t convertHeader(buffer_t buffer);

/* Parameters: width - int that represents the width of a PPM image
               height - int that represents the height of a PPM image
 * Return:     ptr - pixel_t pointer that has had its memory allocated
 * This function allocates memory for an image based on the number of pixels.
*/
pixel_t **allocateMemory(int width, int height);

/* Parameters: ptr - pixel_t double pointer which needs to be de-allocated
               width - int that represents the width of a PPM image
 * Return:     N/A - function is of type void
 * This function de-allocates memory for an image.
*/
void freeMemory(pixel_t **ptr, int width);

/* Parameters: inFile - file pointer representing an input file
               image - pixel_t double pointer representing a PPM image pixel
                       array
               width - int that represents the width of a PPM image
               height - int that represents the height of a PPM image
 * Return:     N/A - function is of type void
 * This function reads PPM data from an input image and stores it in an array.
*/
void readImage(FILE *inFile, pixel_t **image, int width, int height);

/* Parameters: outFile - file pointer representing an output file
               image - pixel_t double pointer representing a PPM image pixel
                       array
               width - int that represents the width of a PPM image
               height - int that represents the height of a PPM image
 * Return:     N/A - function is of type void
 * This function writes PPM data to an output image from an array.
*/
void writeImage(FILE *outFile, pixel_t **image, int width, int height);

/* Parameters: original - pixel_t double pointer representing an unmodified
                          PPM image
               resized - pixel_t double pointer representing a resized PPM image
               width - int that represents the width of a PPM image
               height - int that represents the height of a PPM image
               rWidth - double that represents the relative width scale of the
                        resized image
               rHeight - double that represents the relative height scale of the
                         resized image
 * Return:     N/A - function is of type void
 * This function assigns pixels to a resized PPM image array based on the
   relative scale of the transformation.
*/
void getResizedPixels(pixel_t **original, pixel_t **resized,
                      int width, int height, double rWidth, double rHeight);

/* Parameters: inFile - file pointer representing an input file
               outFile - file pointer representing an output file
 * Return:     N/A - function is of type void
 * This function performs a width/height transformation on a PPM image.
*/
void resizeImage(FILE *inFile, FILE *outFile);

/* Parameters: value - unsigned char representing r, g, or b pixel value
 * Return:     negativeValue - unsigned char representing the negative
                               of the input r, g, or b pixel value
 * This function finds the negative of a given r, g, or b value.
*/
unsigned char getNegativeValue(unsigned char value);

/* Parameters: original - pixel_t double pointer representing an unmodified
                          PPM image
               negative - pixel_t double pointer representing a negative
                          PPM image
               width - int that represents the width of a PPM image
               height - int that represents the height of a PPM image
 * Return:     N/A - function is of type void
 * This function assigns pixels to a negative PPM image by assigning the
   opposite of each R, G, and B value.
*/
void getNegativePixels(pixel_t **original, pixel_t **negative,
                       int width, int height);

/* Parameters: inFile - file pointer representing an input file
               outFile - file pointer representing an output file
 * Return:     N/A - function is of type void
 * This function creates a negative of a PPM image.
*/
void negativeImage(FILE *inFile, FILE *outFile);

#endif