/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// image.c
//
// Image file functions
//
// Copyright (c) 1995-96 Jim Nelson.  Permission to distribute
// granted by the author.  No warranties are made on the fitness of this
// source code.
//
*/

#include "htp.h"

#include "gif.h"
#include "jpeg.h"
#include "png.h"

typedef struct tagIMAGEURL
{
    char               *url;
    char               *path;
    struct tagIMAGEURL *next;
} IMAGEURL;

static IMAGEURL* imageurl_store = NULL;

IMAGEURL *FindImageUrl (const char *url) {
    IMAGEURL* urls;
    urls = imageurl_store;
    while (urls != NULL) {
        if (stricmp(url, urls->url) == 0) {
            return urls;
        }
        urls = urls->next;
    }
    return NULL;
}

BOOL ExistsImageUrl (const char *url)
{
    return (FindImageUrl(url) != NULL);
}


BOOL StoreImageUrl (const char *url, char* path) {
    IMAGEURL* urls;
    DEBUG_PRINT(("Storing image URL (%s,%s)...",url, path));
    urls = FindImageUrl(url);
    if (urls == NULL) {
        if((urls = AllocMemory(sizeof(IMAGEURL))) == NULL)
        {
            DEBUG_PRINT(("unable to allocate memory for new image URL"));
            return FALSE;
        }
        if((urls->url = DuplicateString(url)) == NULL) 
        {
            FreeMemory(urls);
            DEBUG_PRINT(("unable to allocate memory for new URL"));
            return FALSE;
        }
        urls->next = imageurl_store;
        imageurl_store = urls;
    } else {
        FreeMemory(urls->path);
    }
    urls->path = path;
    return TRUE;
}


BOOL RemoveImageUrl (const char *url) {
    IMAGEURL *urls, **prev;
    prev = &imageurl_store;
    urls = imageurl_store;
    while (urls != NULL) {
        if (stricmp(url, urls->url) == 0) {
            break;
        }
        prev = &urls->next;
        urls = urls->next;
    }
    if (urls == NULL) {
        DEBUG_PRINT(("unable to find image URL for remove"));
        return FALSE;
    }
    *prev = urls->next;
    
    FreeMemory(urls->url);
    FreeMemory(urls->path);
    FreeMemory(urls);
    return TRUE;
}
    
    
    
char *GetPathFor (IMAGEURL *imageurl, const char *src) {
    uint urlsize, srcsize, pathsize, suffixsize, length;
    char *filename, *suffix;
    DEBUG_PRINT(("GetPathFor (%s,%s) %s",imageurl->url,imageurl->path,src));
    
    urlsize = strlen(imageurl->url);
    srcsize = strlen(src);
    if (srcsize < urlsize) {
        return NULL;
    }
    if (strnicmp(imageurl->url,src,urlsize) != 0) {
        return NULL;
    }
    pathsize   = strlen(imageurl->path);
    suffix     = ConvertDirDelimiter(src + urlsize);
    suffixsize = strlen(suffix);
    length     = pathsize + suffixsize ;

    if ((filename = AllocMemory(length+1)) == NULL) {
        DEBUG_PRINT(("unable to allocate memory for filename in GetPathFor"));
        return NULL;
    }
    StringCopy(filename, imageurl->path, pathsize + 1);
    StringCopy(filename + pathsize, suffix, suffixsize +1);
    filename[length] = NUL;

    FreeMemory(suffix);
    return filename;
}
    


typedef struct {
    BOOL (*checkFormat) (FILE * file);
    BOOL (*readDimensions) (FILE * file, DWORD *height, DWORD *width);
} ImageOps;

ImageOps ops[] = {
    { GifFormatFound , GifReadDimensions  },
    { JpegFormatFound, JpegReadDimensions },
    { PngFormatFound , PngReadDimensions  }
};

#define IMAGE_TYPE_COUNT (sizeof(ops) / sizeof(ImageOps))
#define IMAGE_TYPE_UNKNOWN IMAGE_TYPE_COUNT

BOOL OpenImageFile(const char *filename, IMAGEFILE *imageFile)
{
    uint type;
    IMAGEURL* imageurl;
    assert(filename != NULL);
    assert(imageFile != NULL);
    imageFile->name = NULL;

    DEBUG_PRINT(("trying imageurls..."));
    imageurl = imageurl_store;
    while (imageurl) {
        DEBUG_PRINT(("trying imageurl %s for %s",imageurl->url,filename));
        if ((imageFile->name = GetPathFor(imageurl, filename))) {
            break;
        }
        imageurl = imageurl->next;
    }

    if (imageFile->name == NULL) {
        if ((imageFile->name = ConvertDirDelimiter(filename)) == NULL)
        {
            DEBUG_PRINT(("could not duplicate filename string"));
            return FALSE;
        }
    }
        
    imageFile->file = fopen(imageFile->name, "rb");
    if (imageFile->file == NULL) {
        DEBUG_PRINT(("could not open image file %s", imageFile->name));
        FreeMemory(imageFile->name);
        return FALSE;
    }

    /* build the rest of the image file structure */

    /* by default, unknown image type */
    for (type = 0; type < IMAGE_TYPE_COUNT; type++) {
        if (ops[type].checkFormat(imageFile->file))
            break;
    }

    /* If type is unknown, the variable type is already
     * IMAGE_TYPE_COUNT == IMAGE_TYPE_UNKNOWN.
     */
    imageFile->imageType = type;
    return TRUE;
}   

void CloseImageFile(IMAGEFILE *imageFile)
{
    assert(imageFile != NULL);
    assert(imageFile->name != NULL);
    assert(imageFile->file != NULL);

    FreeMemory(imageFile->name);
    fclose(imageFile->file);

    imageFile->name = NULL;
    imageFile->file = NULL;
}   

BOOL GetImageDimensions(IMAGEFILE *imageFile, DWORD *width, DWORD *height)
{
    assert(imageFile != NULL);
    assert(width != NULL);
    assert(height != NULL);

    /* unknown file type */
    if(imageFile->imageType == IMAGE_TYPE_UNKNOWN)
	return FALSE;

    return ops[imageFile->imageType].readDimensions(imageFile->file, 
						    height, width);
}   

