#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <zlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "file.h"

int isGZIPFile(char *fileName);
int isJPEGFileName(char *fileName);

File *fileopen (const char *path, const char *mode)
{
    File* stream;
    
    assert(path!=NULL);

    stream=(File*)calloc(1,sizeof(File));
    if(stream==NULL)
        return(stream);
    
    if(isGZIPFile((char*)path)==1)
    {
        stream->type=Compressed;

        if(strcmp(mode,"r")==0)
        {
            stream->read=1;
            stream->write=0;
            if ((stream->gzfd=open(path,O_RDONLY))<0)
            {
                fprintf(stderr, "Unable to open %s.\n", path);
                free(stream);
                stream=NULL;
                return(stream);
            }
            stream->gzfp = gzdopen(stream->gzfd, "rb");
            if(stream->gzfp==NULL)
            {
                free(stream);
                stream=NULL;
                return(stream);
            }
        }
        else
        if(strcmp(mode,"w")==0)
        {
            char outmode[20];
            strcpy(outmode, "wb6 ");
            
            stream->read=0;
            stream->write=1;
//            printf("File open for write is not currently working for gz files.\n");
//            free(stream);
//            return(NULL);

            if ((stream->gzfd=creat(path,00600))<0)
            {
                fprintf(stderr, "Unable to open %s for gz write.\n",path);
                free(stream);
                return(NULL);
            }

            stream->gzfp=gzdopen(stream->gzfd,"wb6 ");
            if(stream->gzfp==NULL)
            {
                printf("Error opening gz file.\n");
                close(stream->gzfd);
                free(stream);
                return(NULL);
            }
            return(stream);
        }
        else
        {
            printf("ERROR mode %s is not supported for gz files\n",mode);
            free(stream);
            return(NULL);
        }

    }
    else
    {
        if(isJPEGFileName((char*)path)==1)
        {
            stream->type=Jpeg;
        }
        else
        {
            stream->type=Normal;
            stream->fp=fopen(path,mode);
            if(stream->fp==NULL)
            {
                free(stream);
                stream=NULL;
            }
        }
    }

    return(stream);
}

int fileclose(File *stream)
{
    int returnValue;

    if(stream==NULL)
        return(0);

    if(stream->type==Compressed)
    {
        if (gzclose(stream->gzfp) != Z_OK)
            printf("Failed gzclose\n");
        returnValue=close(stream->gzfd);
        free(stream);
        return(returnValue);
    }

    if(stream->type==Jpeg)
    {
        free(stream);
        return(1);
    }

    
    returnValue=fclose(stream->fp);
    free(stream);
    return(returnValue);
}


int fileread( void *ptr, int size, int nmemb, File *stream)
{
    if(stream==NULL)
        return(0);

    if(stream->type==Compressed)
    {
        if(stream->read==0)
        {
            printf("Error file not opened for reading\n");
            return(-1);
        }

        return(gzread(stream->gzfp, ptr, size*nmemb));
    }

    if(stream->type==Jpeg)
    {
        return(0);
    }
    
    return(fread(ptr,size,nmemb,stream->fp));
}

int filewrite( const void *ptr, int size, int nmemb, File *stream)
{
    int len;
    if(stream==NULL)
        return(0);

    if(stream->type==Compressed)
    {
        if(stream->write==0)
        {
            printf("Error file not opened for writing\n");
            return(-1);
        }

        if ((len=gzwrite(stream->gzfp, (void*)ptr, nmemb*size))!=nmemb*size)
            printf("GZIP Write Error %d %d %d\n",len,nmemb,size),exit(-1);
        return(nmemb*size);
    }

    if(stream->type==Jpeg)
    {
        return(0);
    }

    
    return(fwrite(ptr,size,nmemb,stream->fp));
}

char *filegets(char *s, int size, File *stream)
{
    if(stream==NULL)
        return(NULL);

    if(stream->type==Compressed)
    {
        if(stream->read==0)
        {
            printf("Error file not opened for reading\n");
            return(NULL);
        }

        return(gzgets(stream->gzfp, s, size));
    }

    if(stream->type==Jpeg)
    {
        return(NULL);
    }

    
    return(fgets(s,size,stream->fp));
}

int filegetc(File *stream)
{
    if(stream==NULL)
        return(EOF);

    if(stream->type==Compressed)
    {
        if(stream->read==0)
        {
            printf("Error file not opened for reading\n");
            return(EOF);
        }

        return(gzgetc(stream->gzfp));
    }

    if(stream->type==Jpeg)
    {
        return(EOF);
    }

    
    return(fgetc(stream->fp));
}

int fileeof(File *stream)
{
    if(stream==NULL)
        return(1);

    if(stream->type==Compressed)
        return(gzeof(stream->gzfp));

    if(stream->type==Jpeg)
    {
        return(1);
    }

    
    return(feof(stream->fp));
}

int fileputs(const char *s, File *stream)
{
    if(stream==NULL)
        return(0);

    if(stream->type==Compressed)
    {
        if(stream->write==0)
        {
            printf("Error file not opened for writing\n");
            return(-1);
        }

        return(gzputs(stream->gzfp,s));
    }

    if(stream->type==Jpeg)
    {
        return(0);
    }

    
    return(fputs(s,stream->fp));
}



int isGZIPFile(char *fileName)
{
/*    printf("%c%c%c",fileName[strlen(fileName)-3],
       fileName[strlen(fileName)-2],
       fileName[strlen(fileName)-1]);*/

    if(strlen(fileName)<4)
        return(0);
    
    if(fileName[strlen(fileName)-3]=='.' &&
       fileName[strlen(fileName)-2]=='g' &&
       fileName[strlen(fileName)-1]=='z')
        return(1);
    else
        return(0);

}

int isJPEGFileName(char *fileName)
{
/*    printf("%c%c%c",fileName[strlen(fileName)-3],
       fileName[strlen(fileName)-2],
       fileName[strlen(fileName)-1]);*/

    if(strlen(fileName)<5)
        return(0);
    if(
       fileName[strlen(fileName)-4]=='.' &&
       fileName[strlen(fileName)-3]=='j' &&
       fileName[strlen(fileName)-2]=='p' &&
       fileName[strlen(fileName)-1]=='g')
        return(1);
    else
        return(0);

}

int isJpegFile(File *stream)
{
    if(stream->type==Jpeg)
    {
        return(1);
    }
    return(0);
}
