time_t plGetFileModifiedTime(const char *path)
{
	struct stat sAttributes;
	if (stat(path, &sAttributes) == -1)
	{
		plSetError("Failed to get modification time!\n");
		return 0;
	}
	return sAttributes.st_mtime;
}
/*	Checks whether a file has been modified or not.
*/
bool plIsFileModified(time_t oldtime, const char *path)
{
	if (!oldtime)
	{
		plSetError("Invalid time, skipping check!\n");
		return false;
	}

	struct stat sAttributes;
	if (stat(path, &sAttributes) == -1)
	{
		plSetError("Failed to get file stats!\n");
		return false;
	}

	if (sAttributes.st_mtime > oldtime)
		return true;

	return false;
}
PLresult _plLoadPPMImage(FILE *fin, PLImage *out) {
    plSetErrorFunction("_plLoadPPMImage");

    char header[PPM_HEADER_SIZE];
    memset(&header, 0, sizeof(header));

    fgets(header, PPM_HEADER_SIZE, fin);
    if (strncmp(header, "P6", 2)) {
        plSetError("Unsupported PPM type!\n");
        return PL_RESULT_FILEVERSION;
    }

    int i = 0, d;
    unsigned int w = 0, h = 0;
    while (i < 3) {
        fgets(header, PPM_HEADER_SIZE, fin);
        if (header[0] == '#')
            continue;

        if (i == 0)
            i += sscanf(header, "%d %d %d", &w, &h, &d);
        else if (i == 1)
            i += sscanf(header, "%d %d", &h, &d);
        else if (i == 2)
            i += sscanf(header, "%d", &d);
    }

    memset(out, 0, sizeof(PLImage));

    out->size = w * h * 3;
    out->data = new PLbyte*[1];
    out->data[0] = new PLbyte[out->size];

    fread(out->data[0], sizeof(uint8_t), out->size, fin);

    out->width = w;
    out->height = h;
    out->format = PL_IMAGEFORMAT_RGB8;

    return PL_RESULT_SUCCESS;
}
PLresult _plLoadVTFImage(FILE *fin, PLImage *out) {
    plFunctionStart();

    VTFHeader header;
    memset(&header, 0, sizeof(VTFHeader));
#define VTF_VERSION(maj, min)   ((maj == header.version[1] && min <= header.version[0]) || maj < header.version[0])

    if (fread(&header, sizeof(VTFHeader), 1, fin) != 1) {
        return PL_RESULT_FILEREAD;
    } else if (VTF_VERSION(7, 5)) {
        return PL_RESULT_FILEVERSION;
    } else if (!plIsValidImageSize(header.width, header.height)) {
        return PL_RESULT_IMAGERESOLUTION;
    } else {
        if(header.lowresimageformat != VTF_FORMAT_DXT1) {
            plSetError("Invalid texture format for lowresimage in VTF");
            return PL_RESULT_IMAGEFORMAT;
        }

        if ((header.lowresimagewidth > 16) || (header.lowresimageheight > 16) ||
            (header.lowresimagewidth > header.width) || (header.lowresimageheight > header.height)) {
            return PL_RESULT_IMAGERESOLUTION;
        }
    }

    // todo, use the headersize flag so we can load this more intelligently!

    VTFHeader72 header2;
    if (header.version[1] >= 2) {
        memset(&header2, 0, sizeof(VTFHeader72));
        if (fread(&header2, sizeof(VTFHeader72), 1, fin) != 1)
            return PL_RESULT_FILEREAD;
    }
    VTFHeader73 header3;
    if (header.version[1] >= 3) {
        memset(&header3, 0, sizeof(VTFHeader73));
        if (fread(&header3, sizeof(VTFHeader73), 1, fin) != 1)
            return PL_RESULT_FILEREAD;
    }

    memset(out, 0, sizeof(PLImage));

    out->width = header.width;
    out->height = header.height;

    _plConvertVTFFormat(out, header.highresimageformat);

    out->levels = 1;
    out->data = (PLbyte**)calloc(1, sizeof(PLbyte*));

    /*
    if (header.version[1] >= 3) {
        for (PLuint i = 0; i < header3.numresources; i++) {
            // todo, support for later VTF versions.
        }
    } else */ {
        PLuint faces = 1;
        if(header.flags & VTF_FLAG_ENVMAP) {
            faces = 6;
        }

        // VTF's typically include a tiny thumbnail image at the start, which we'll skip.
        fseek(fin, header.lowresimagewidth * header.lowresimageheight / 2, SEEK_CUR);

        for (PLuint mipmap = 0; mipmap < header.mipmaps; ++mipmap) {
            for(PLuint frame = 0; frame < header.frames; ++frame) {
                for(PLuint face = 0, mipw = 1, miph = 1; face < faces; ++face) {
                    // We'll just skip the smaller mipmaps for now, can generate these later.
                    mipw *= (PLuint)pow(2, mipmap); //(out->width * (mipmap + 1)) / header.mipmaps;
                    miph *= (PLuint)pow(2, mipmap); //(out->height * (mipmap + 1)) / header.mipmaps;
                    PLuint mipsize = _plGetImageSize(out->format, mipw, miph);
                    if(mipmap == (header.mipmaps - 1)) {
                        out->data[0] = (PLbyte*)calloc(mipsize, sizeof(PLbyte));
                        if (fread(out->data[0], sizeof(PLbyte), mipsize, fin) != mipsize) {
                            _plFreeImage(out);
                            return PL_RESULT_FILEREAD;
                        }
                    } else {
                        fseek(fin, mipsize, SEEK_CUR);
                    }

                    if(feof(fin)) {
                        perror(PL_FUNCTION);
                        break;
                    }
                }
            }
        }
    }

    return PL_RESULT_SUCCESS;
}