#include <lodepng/lodepng.h>

#include "images/PNGReader.h"

PNGReader::PNGReader()
    : width(0), height(0), channels(0), rawData(nullptr), data(nullptr) {
}

PNGReader::~PNGReader() {
    clean();
}

Error PNGReader::load(const char* path) {
    clean();
    Error error = loadIntern(path);
    if(error.has()) {
        clean();
    }
    return error;
}

Error PNGReader::loadIntern(const char* path) {
    size_t rawSize;
    unsigned int error = lodepng_load_file(&rawData, &rawSize, path);
    if(error) {
        Error e = {"cannot load file '"};
        e.message.append(path).append("': ").append(lodepng_error_text(error));
        return e;
    }

    LodePNGState state;
    lodepng_state_init(&state);
    error = lodepng_decode(&data, &width, &height, &state, rawData, rawSize);
    if(error) {
        Error e = {"cannot decode file '"};
        e.message.append(path).append("'").append(lodepng_error_text(error));
        return e;
    }
    channels = lodepng_get_channels(&state.info_png.color);

    if(channels < 1 || channels > 4) {
        Error error = {"'"};
        error.message.append(path)
            .append("' has unsupported number of channels: ")
            .append(channels);
        return error;
    } else if(state.info_png.color.bitdepth != 8) {
        Error error = {"bit depth of '"};
        error.message.append(path).append("' is not 8");
        return error;
    }
    return {};
}

void PNGReader::clean() {
    free(rawData);
    free(data);
    rawData = nullptr;
    data = nullptr;
    width = 0;
    height = 0;
    channels = 0;
}

int PNGReader::getWidth() const {
    return width;
}

int PNGReader::getHeight() const {
    return height;
}

int PNGReader::getChannels() const {
    return channels;
}

const ColorChannel* PNGReader::getData() const {
    return data;
}