/*********************************************************************
----------------------------------------------------------------------

	filelist

----------------------------------------------------------------------
*********************************************************************/

#include <string.h>
#include <stdio.h>

#include <exec/lists.h>
#include <dos/dos.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/utility.h>
#include <proto/guigfx.h>

#include <clib/macros.h>

#include "global.h"
#include "filelist.h"
#include "tools.h"
#include "debug.h"



/*
**	 internal prototypes
*/

static struct FileListNode *CreateFileListNode(char *fullname, long filesize);
static void DeleteFileListNode(struct FileListNode *picnode);




/*********************************************************************

	node = FileList_FindBestKey(flist, key, &error, &orientation, BOOL allowx, BOOL allowy)

*********************************************************************/

struct FileListNode *FileList_FindBestKey(struct FileList *flist, PICTUREKEY *key, double *error, int *orientationptr, BOOL allowx, BOOL allowy)
{
	struct FileListNode *bestnode = NULL;

	assert(flist);
	assert(key);

	if (flist->list)
	{
		if (!IsListEmpty(flist->list))
		{
			BOOL success = FALSE;
		
			struct Node *node, *nextnode; 
			struct FileListNode *flnode;
			double value, bestvalue;
			
			node = flist->list->lh_Head;
			flnode = (struct FileListNode *) node;



			/*
			**	find ANY valid key
			*/	
			
			while (nextnode = node->ln_Succ)
			{
				flnode = (struct FileListNode *) node;
				
				if (flnode->key)
				{
					bestnode = flnode;
					bestvalue = CompareKeys(flnode->key, key);
					success = TRUE;
					break;
				}

				node = nextnode;
			}			



			/*
			**	if there are ANY keys, find the best one
			*/

			if (success)
			{
				int orientation;

				node = flist->list->lh_Head;
				flnode = (struct FileListNode *) node;
	
				while (nextnode = node->ln_Succ)
				{
					flnode = (struct FileListNode *) node;
					
					if (flnode->key)
					{
						value = CompareKeys(flnode->key, key);
					
						if (value < bestvalue)
						{
							bestvalue = value;
							bestnode = flnode;
							orientation = OR_NORMAL;
						}
						

						if (orientationptr)
						{
							if (allowx)
							{
								value = CompareKeysX(flnode->key, key);
							
								if (value < bestvalue)
								{
									bestvalue = value;
									bestnode = flnode;
									orientation = OR_FLIPX;
								}
							}
							
							if (allowy)
							{
								value = CompareKeysY(flnode->key, key);
						
								if (value < bestvalue)
								{
									bestvalue = value;
									bestnode = flnode;
									orientation = OR_FLIPY;
								}
							}
							
							if (allowx && allowy)
							{
								value = CompareKeysXY(flnode->key, key);
						
								if (value < bestvalue)
								{
									bestvalue = value;
									bestnode = flnode;
									orientation = OR_FLIPY + OR_FLIPX;
								}
							}
						}

					}
	
					node = nextnode;
				}
				
				if (orientationptr)
				{
					*orientationptr = orientation;
				}

				if (error)
				{				
					*error = bestvalue;
				}
			}


		}
	}		

	return bestnode;
}



/*********************************************************************

	complete = FileList_CreateKeys(flist, always, abortsignals)

*********************************************************************/

BOOL FileList_CreateKeys(struct FileList *flist, BOOL always, ULONG abortsignals)
{
	BOOL complete = TRUE;

	if (flist)
	{
		if (flist->list)
		{
			if (!IsListEmpty(flist->list))
			{
				struct Node *node = flist->list->lh_Head, *nextnode;
				
				while (nextnode = node->ln_Succ)
				{
					struct FileListNode *flnode = (struct FileListNode *) node;
				
					if (always || !flnode->key)
					{
						PICTURE *pic;
						Free(flnode->key);
						flnode->key = NULL;

						printf("    %s\n", flnode->fullname);
						
						if (pic = LoadPicture(flnode->fullname, NULL))
						{
							if (DoPictureMethod(pic, PICMTHD_AUTOCROP, TAG_DONE))
							{
								PICTUREKEY *key;
								char *keystring;
								
								if (key = CalcPictureKey(pic))
								{
									if (keystring = KeyToString(key))
									{
										SetComment(flnode->fullname, keystring);
										Free(keystring);
									}
								
									flnode->key = key;	
								}
							}
													
							DeletePicture(pic);				
						}
					}
					
					if (SetSignal(0,0) & abortsignals)
					{
						complete = FALSE;
						break;
					}
					
					node = nextnode;
				}
			}
		}
	}

	return complete;
}



/*********************************************************************

	flist = FileList_Create()

*********************************************************************/

struct FileList *FileList_Create(void)
{
	struct FileList *filelist;
	BOOL success = FALSE;
	
	if (filelist = Malloclear(sizeof(struct FileList)))
	{
		if (filelist->list = CreateList())
		{
			filelist->numentries = 0;
			filelist->numkeys = 0;
			success = TRUE;
		}
	}
	
	if (!success)
	{
		FileList_Delete(filelist);
		filelist = NULL;
	}

	return filelist;
}



/*********************************************************************

	FileList_Delete(flist)

*********************************************************************/

void FileList_Delete(struct FileList *filelist)
{
	if (filelist)
	{
		if (filelist->list)
		{
			struct FileListNode *fnode;
			
			while (fnode = (struct FileListNode *) RemHead(filelist->list))
			{
				DeleteFileListNode(fnode);
			}

			DeleteList(filelist->list);
		}

		Free(filelist);
	}
}



/*********************************************************************

	success = FileList_AddFile(flist, filename, usekeys)

*********************************************************************/

BOOL FileList_AddFile(struct FileList *flist, char *filename, BOOL usekeys)
{
	BOOL success = FALSE;
	long filesize = 0;
	char *filecomment = NULL;

	if (filename)
	{
		BPTR lock;
		if (lock = Lock(filename, ACCESS_READ))
		{
			struct FileInfoBlock *fib;
			if (fib = AllocDosObject(DOS_FIB, NULL))
			{
				if (Examine(lock, fib))
				{
					if (fib->fib_DirEntryType < 0)
					{
						filesize = fib->fib_Size;
						filecomment = StrDup(fib->fib_Comment);
						success = TRUE;
					}
				}
				FreeDosObject(DOS_FIB, fib);
			}

			UnLock(lock);
		}
	}
	
	
	if (success)
	{
		struct FileListNode *flnode;
		
		success = FALSE;
		
		if (flnode = CreateFileListNode(filename, filesize))
		{
			if (filecomment)
			{
				PICTUREKEY *key;
				if (key = StringToKey(filecomment))
				{
					flnode->key = key;
					flist->numkeys++;
					success = TRUE;
				}
			}


			if (!success && !usekeys)
			{
				success = IsPicture(filename, NULL);
			}


			if (success)
			{
				AddTail(flist->list, (struct Node *) flnode);
				flist->numentries++;
			}
			else
			{
				DeleteFileListNode(flnode);
			}
		}
	}


	Free(filecomment);

	return success;
}



/*--------------------------------------------------------------------

	DeleteFileListNode(flnode)

--------------------------------------------------------------------*/

static void DeleteFileListNode(struct FileListNode *fnode)
{
	if (fnode)
	{
		Free(fnode->key);
		Free(fnode->fullname);
		Free(fnode);
	}
}



/*--------------------------------------------------------------------

	flnode = CreateFileListNode(fullname, filesize)

--------------------------------------------------------------------*/

static struct FileListNode *CreateFileListNode(char *fullname, long filesize)
{
	struct FileListNode *pnode;
	BOOL success = FALSE;

	if (pnode = Malloc(sizeof(struct FileListNode)))
	{
		if (pnode->fullname = StrDup(fullname))
		{	
			pnode->node.ln_Type = NT_USER;
			pnode->node.ln_Pri = 0;

			pnode->filesize = filesize;
			pnode->key = NULL;
			
			success = TRUE;
		}
		
		if (!success)
		{
			DeleteFileListNode(pnode);
			pnode = NULL;
		}
	}

	return pnode;
}

