#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <png.h>
#include "gr3.h"
#include "gr3_internals.h"

int gr3_export_png_(const char *filename, int width, int height) {
  FILE *pngfp;
  int *pixels;
  int err;
  int i;
  
  png_structp png_ptr;
  png_infop info_ptr;
  png_bytepp row_pointers;
  
  pngfp = fopen(filename, "wb");
  if (!pngfp) {
    return GR3_ERROR_CANNOT_OPEN_FILE;
  }
  pixels = (int *)malloc(width * height * sizeof(int));
  if (!pixels) {
    return GR3_ERROR_OUT_OF_MEM;
  }
  
  err = gr3_getimage(width, height, 1, (char *)pixels);
  if (err != GR3_ERROR_NONE) {
    fclose(pngfp);
    free(pixels);
    return err;
  }
  
  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (!png_ptr) {
    fclose(pngfp);
    free(pixels);
    return GR3_ERROR_EXPORT;
  }
  info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr) {
    fclose(pngfp);
    free(pixels);
    png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
    return GR3_ERROR_EXPORT;
  }
  png_init_io(png_ptr, pngfp);
  png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
  
  row_pointers = malloc(height*sizeof(png_bytep));
  for (i = 0; i < height; i++) {
    row_pointers[i]=(png_bytep)(pixels+(height-i-1)*width);
  }
  png_set_rows(png_ptr, info_ptr, (void *)row_pointers);
  png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
  
  png_destroy_write_struct(&png_ptr, &info_ptr);
  fclose(pngfp);
  free(row_pointers);
  free(pixels);
  return GR3_ERROR_NONE;
}

int gr3_readpngtomemory_(int *pixels, const char *pngfile, int width, int height) {
  FILE *png_fp;
  png_structp png_ptr;
  png_infop info_ptr = NULL;
  png_infop end_info = NULL;
  unsigned char sig[8];
  png_bytep *row_pointers;
  int i;
  png_fp = fopen(pngfile,"rb");
  if (!png_fp) {
    return 1;
  }
  i = fread(sig, 1, 8, png_fp);
  if (!png_check_sig(sig, 8)){
    return 2;
  }
  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (!png_ptr) {
    return 3;
  }
  info_ptr = png_create_info_struct(png_ptr);
  end_info = png_create_info_struct(png_ptr);
  if (!info_ptr || !end_info) {
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    return 4;
  }
  png_init_io(png_ptr, png_fp);
  png_set_sig_bytes(png_ptr, 8);
  png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
  row_pointers = png_get_rows(png_ptr, info_ptr);
  for (i = 0; i < height; i++) {
    memcpy(pixels+(height-1-i)*width,row_pointers[i],width*sizeof(int));
  }
  png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
  fclose(png_fp);
  return 0;
}
