#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>

#include "image.h"

/**
 * Manipulation d'images
 **/

pixel getPix(Image* img, int i, int j){
    assert(img != NULL && i >= 0 && i < img->haut && j >=0 && j < img->larg);
    return img->pixels[i * img->larg + j];
}

void setPix(Image* img, int i, int j, pixel v){
    assert(img != NULL && i >= 0 && i < img->haut && j >=0 && j < img->larg);
    img->pixels[i * img->larg + j] = v;
}

Image* creerImage(int haut, int larg) {
    Image* img = malloc(sizeof(Image));
    img->haut = haut;
    img->larg = larg;
    img->pixels = (pixel*) malloc(haut * larg * sizeof(pixel));
    return img;
}

void detruireImage(Image* img) {
    free(img->pixels);
    free(img);
}

/**
 *   Import / Export
 **/
// renvoie NULL en cas d'erreur
Image* importerImage(char* filename){
    FILE* f = fopen(filename, "r");
    if (f == NULL) {
        fprintf(stderr, "impossible d'ouvrir %s", filename);
        return NULL;
    } else {
        int haut, larg, maxi;
        if (fscanf(f, "P3\n%d %d\n%d\n", &larg, &haut, &maxi) != 3){
            fprintf(stderr, "entete image invalide %s", filename);
            fclose(f);
            return NULL;
        } else {
            if (haut >= 0 && larg >= 0 && maxi == 255) {
                Image* img = creerImage(haut, larg);
                pixel valeur;
                int r,v,b;
                int i = 0;
                int imax = haut * larg;
                while ((i < imax) && (fscanf(f, "%d %d %d", &r, &v, &b) == 3)) {
                    valeur.r = r; valeur.v = v; valeur.b = b;
                    img->pixels[i] = valeur;
                    i += 1;
                }
                if (i < imax) {
                    detruireImage(img);
                    fprintf(stderr, "valeur invalide %s", filename);
                    fclose(f);
                    return NULL;
                } else {
                    fclose(f);
                    return img;
                }
            } else {
                fprintf(stderr, "entete image invalide %s", filename);
                fclose(f);
                return NULL;
            }
        }
    }
}

// renvoie false en cas d'erreur
bool exporterImage(Image* img, char* filename){
    FILE* f = fopen(filename, "w");
    if (f == NULL) {
        fprintf(stderr, "impossible d'ouvrir %s", filename);
        return false;
    } else {
        fprintf(f, "P3\n%d %d\n255\n", img->larg, img->haut);
        int i = 0;
        const int imax = img->haut * img->larg;
        while (i < imax) {
            fprintf(f, "%d %d %d\n", (int) img->pixels[i].r, 
                (int) img->pixels[i].v, (int) img->pixels[i].b);
            i += 1;
        }
        fclose(f);
        return true;
    }
}