#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winb.h>
#include <te.h>
#include <fntb.h>
#include <gui.h>

#include <egb.h>
#include <guidbg.h>

#include "ysmacro.h"
#include "ysgui.h"
#include "ysansi.h"
#include "ysmalloc.h"
#include "ysrename.h"



typedef struct FileList
{
	struct FileList *prev,*next;
	char src[80],dst[80];
} FILELIST;




/*
  QUE                  リストとなる構造体メンバprevとnextが入っていること
  QUEAPPFUNC(lst,neo)  リストlstの最後に要素neoを結合したリストを返す
  QUEDELFUNC(mem)      要素memを削除したリストを返す
  QUEFREEFUNC(lst)     リストlstを消去する
  QUESEEKFUNC(lst,id)  リストのid番目の要素のポインタを返す(先頭=1)
  QUESEEKTOPFUNC(mem)  要素memのリストを返す
  QUESEEKENDFUNC(mem)  要素memの属するリストの末尾の要素を返す
  QUECOUNTFUNC(lst)    リストlstの要素個数を返す
  QUENUMFUNC(lst,mem)  リストlstの要素memの番号を返す(1が先頭  0はエラー)
*/

/* ↓ここの#defineを変更して何にでも使っちゃおう */
#define QUE FILELIST
#define QUEAPPFUNC FlAppendLst
#define QUEDELFUNC FlDeleteLst
#define QUEFREEFUNC FlFreeLst
#define QUESEEKFUNC FlSeek
#define QUESEEKTOPFUNC FlSeekTopLst
#define QUESEEKENDFUNC FlSeekEndLst
#define QUECOUNTFUNC FlCount
#define QUENUMFUNC FlNumList

QUE *QUEAPPFUNC(QUE *lst,QUE *neo);
QUE *QUEDELFUNC(QUE *mem);
void QUEFREEFUNC(QUE *lst);
QUE *QUESEEKFUNC(QUE *lst,int id);
QUE *QUESEEKENDFUNC(QUE *mem);
QUE *QUESEEKTOPFUNC(QUE *mem);
int QUECOUNTFUNC(QUE *lst);
int QUENUMFUNC(QUE *lst,QUE *mem);

static QUE *QUEAPPFUNC(QUE *lst,QUE *neo)
{
	QUE *appPtr;

	if(lst==NULL)
	{
		return neo;
	}
	else
	{
		appPtr=QUESEEKENDFUNC(lst);
		appPtr->next=neo;
		neo->prev=appPtr;
		neo->next=NULL;
		return lst;		
	}
}

static QUE *QUEDELFUNC(QUE *mem)
{
	QUE *lst;

	if(mem==NULL)
	{
		return NULL;
	}
	else if(mem->prev==NULL && mem->next==NULL)
	{
		FREEFUNC(mem);
		return NULL;
	}
	else if(mem->prev==NULL)
	{
		lst=mem->next;
		lst->prev=NULL;
		FREEFUNC(mem);
		return lst;
	}
	else if(mem->next==NULL)
	{
		lst=QUESEEKTOPFUNC(mem);
		mem->prev->next=NULL;
		FREEFUNC(mem);
		return lst;
	}
	else
	{
		lst=QUESEEKTOPFUNC(mem);
		mem->next->prev=mem->prev;
		mem->prev->next=mem->next;
		FREEFUNC(mem);
		return lst;
	}
}

static void QUEFREEFUNC(QUE *lst)
{
	if(lst->next!=NULL)
	{
		QUEFREEFUNC(lst->next);
	}
	FREEFUNC(lst);
}

QUE *QUESEEKFUNC(QUE *lst,int id)
{
	int i;
	QUE *ptr;

	if(id==0)
	{
		return NULL;
	}

	ptr=lst;
	for(i=1; i<id; i++)
	{
		ptr=ptr->next;
		if(ptr==NULL)
		{
			return NULL;
		}
	}

	return ptr;
}

static QUE *QUESEEKENDFUNC(QUE *mem)
{
	if(mem==NULL)
	{
		return NULL;
	}
	else
	{
		while(mem->next!=NULL)
		{
			mem=mem->next;
		}
		return mem;
	}
}

static QUE *QUESEEKTOPFUNC(QUE *mem)
{
	if(mem==NULL)
	{
		return NULL;
	}
	else
	{
		while(mem->prev!=NULL)
		{
			mem=mem->prev;
		}
		return mem;
	}
}

static int QUECOUNTFUNC(QUE *lst)
{
	int n;

	n=0;
	while(lst!=NULL)
	{
		n++;
		lst=lst->next;
	}
	return n;
}

static int QUENUMFUNC(QUE *lst,QUE *mem)
{
	int n;

	n=1;
	while(lst!=NULL)
	{
		if(lst==mem)
		{
			return n;
		}
		n++;
		lst=lst->next;
	}
	return 0;
}

#undef QUE
#undef QUEAPPFUNC
#undef QUEDELFUNC
#undef QUEFREEFUNC
#undef QUESEEKTOPFUNC
#undef QUESEEKENDFUNC
#undef QUECOUNTFUNC
#undef QUENUMFUNC




static FILELIST *newFileList();

static char curDir[80];
static FILELIST *fLst;

int FlInitialize(void)
{
	fLst=NULL;
	curDir[0]=0;
	return FL_NOERR;
}

int FlGetCurrentDirPtr(char **cur)
{
	*cur=curDir;
	return FL_NOERR;
}

int FlInsertFile(char *ful)
{
	FILELIST *neo,*ptr;
	int id;
	char pth[80],fil[80],ren[80];
	int tp,nf;

	FlNumFiles(&nf);
	NfGetType(&tp);
	if(nf>'Z'-'A'+1 && tp==NFTYPE_ALPHA)
	{
		return FL_TOOMANY;
	}

	/* ファイル名を取得して二重登録のチェック */
	YsSeparatePathFile(pth,fil,ful);
	for(ptr=fLst; ptr!=NULL; ptr=ptr->next)
	{
		if(strcmp(fil,ptr->src)==0)
		{
			return FL_SAME;
		}
	}

	/* 新しい要素用のメモリ確保 */
	neo=newFileList();
	if(neo==NULL)
	{
		return FL_NOMEMORY;
	}

	/* カレントディレクトリのセット | 確認 */
	if(fLst==NULL)
	{
		strcpy(curDir,pth);
	}
	else
	{
		if(strcmp(curDir,pth)!=0)
		{
			return FL_NOTSAMEDIR;
		}
	}

	/* リスト追加 , ファイル名とリネーム後ファイル名のセット */
	fLst=FlAppendLst(fLst,neo);
	id=FlNumList(fLst,neo);
	NfGetNewFileName(ren,id);
	strcpy(neo->src,fil);
	strcpy(neo->dst,ren);
	return FL_NOERR;
}

int FlNumFiles(int *num)
{
	*num=FlCount(fLst);
	return FL_NOERR;
}

int FlGetFileList(char *fil[])
{
	int n;
	FILELIST *lst;

	n=0;
	for(lst=fLst; lst!=NULL; lst=lst->next)
	{
		fil[n]=lst->src;
		n++;
	}
	return FL_NOERR;
}

int FlGetNewFileList(char *fil[])
{
	int n;
	FILELIST *lst;

	n=0;
	for(lst=fLst; lst!=NULL; lst=lst->next)
	{
		fil[n]=lst->dst;
		n++;
	}
	return FL_NOERR;
}

int FlDelete(char *fil)
{
	FILELIST *ptr;

	for(ptr=fLst; ptr!=NULL; ptr=ptr->next)
	{
		if(strcmp(fil,ptr->src)==0)
		{
			fLst=FlDeleteLst(ptr);
			return FL_NOERR;
		}
	}
	return FL_NOERR;
}

int FlClear(void)
{
	FlFreeLst(fLst);
	fLst=NULL;
	curDir[0]=0;
	return FL_NOERR;
}

int FlResetNewFile(void)
{
	int n;
	FILELIST *ptr;

	n=1;
	for(ptr=fLst; ptr!=NULL; ptr=ptr->next)
	{
		NfGetNewFileName(ptr->dst,n);
		n++;
	}

	return FL_NOERR;
}

int FlGetSrcFile(char *fil,int id)
{
	FILELIST *ptr;

	ptr=FlSeek(fLst,id);
	if(ptr==NULL)
	{
		strcpy(fil,"");
		return FL_NOERR;
	}

	strcpy(fil,ptr->src);
	return FL_NOERR;
}

int FlGetDstFile(char *fil,int id)
{
	FILELIST *ptr;

	ptr=FlSeek(fLst,id);
	if(ptr==NULL)
	{
		strcpy(fil,"");
		return FL_NOERR;
	}

	strcpy(fil,ptr->dst);
	return FL_NOERR;
}


static FILELIST *newFileList()
{
	FILELIST *neo;
	neo=(FILELIST *)MALLOCFUNC(sizeof(FILELIST));
	if(neo!=NULL)
	{
		neo->src[0]=0;
		neo->dst[0]=0;
		neo->next=NULL;
		neo->prev=NULL;
	}
	return neo;
}
