#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <time.h>
#include "kernel.h"
#include "swis.h"

#define Buggy "<Obey$Dir>.Buggy"
#include "Buggy.h" // my debugging code
#include "Wimpy.h" // some Wimp definitions

_kernel_swi_regs  SWIRegs;
#define SWI(swi)  SWIcall(swi,True,#swi,__FILE__,__LINE__)
#define SWIX(swi) SWIcall(swi,False,#swi,__FILE__,__LINE__)
#define SWIE(swi) SWIcall(-1,True,#swi,__FILE__,__LINE__)

// dummy since I am on commandline mode
void WimpCloseDown(void) { }

// Call an SWI and abort in case of error...
// Call with SWI NULL to just abort
_kernel_oserror *SWIcall(int SWIName, int AbortOnError, char *AbortMessage, char *File, int Line) {
	_kernel_oserror *OSError;

	//BuggyRegs(AbortMessage,4);

	// Call the SWI (if I have one)
	if (SWIName != -1) {
		OSError = _kernel_swi(SWIName,&SWIRegs,&SWIRegs);
		if (OSError == NULL) { return(OSError); }
	}

	// In case of error write debug log and optionally abort
	BuggyError(AbortMessage,File,Line);
	if (AbortOnError) {
		SWIRegs.r[0] = (int)OSError;
		SWIRegs.r[1] = 1;
		SWIRegs.r[2] = (int)AbortMessage;
		_kernel_swi(Wimp_ReportError,&SWIRegs,&SWIRegs);
		WimpCloseDown();
	}

	return(OSError);
}

typedef struct {
	int Objecttype, Filetype;
	unsigned Length;
	t_OSTimestamp Timestamp;
	t_DateTimeOrdinalBlock DateTime;
	int Age;
	char Name[FileNameMax];
} t_Directory_Entry;


char              MyPath[4096];
t_Directory_Entry MyDirectoryEntry;
int               MyNext = 0;

void Bla(char *Lab,char *Tim, int n) {
	char *t = Tim;
	int i;
	printf("%s: ",Lab);
	for (i=0;i<n;i++) { printf("%02X ",*t++); }
	printf("\n");
}


void ShowDateTime(char *Bla,t_OSTimestamp *Timestamp) {

	t_DateTimeOrdinalBlock DateTime;
	int i;

	printf("\n%s: ",Bla);
	for (i=0;i<5;i++) { printf("%02X ",Timestamp->All[i]); }
	printf("\n");

	SWIRegs.r[0] = -1;
	SWIRegs.r[1] = (int)(Timestamp);
	SWIRegs.r[2] = (int)(&DateTime);
	SWIX(Territory_ConvertTimeToOrdinals);

	printf("TT.MM.YY HH:MM:SS %02d.%02d.%04d %02d:%02d:%02d\n",DateTime.Day,DateTime.Month,DateTime.Year,DateTime.Hour,DateTime.Minute,DateTime.Second);
}


t_Centiseconds Centiseconds(t_OSTimestamp *OSTimestamp) {
	t_Centiseconds c = 0;
	int i;

	for (i=4;i>=0;i--) {
		c = (c<<8) + (t_Centiseconds)(OSTimestamp->All[i]);
	}
	return(c);
}

int Time_AgeDays(t_OSTimestamp *OSTimestamp) {

	t_Centiseconds f,n;
	t_OSTimestamp  Now;

	SWIRegs.r[0] = 14;
	Now.All[0] = 3;
	SWIRegs.r[1] = (int)(&Now);
	SWIX(OS_Word);
	n = Centiseconds(&Now);

	f = Centiseconds(OSTimestamp);
	return ((int)((n-f) / (100 * 60 * 60 * 24)));
}


#define Directory_GetNextEntry(Path,Next,Buffer) Directory_GetNextEntryNamed(Path,Next,Buffer,0)

int Directory_GetNextEntryNamed(char *Path, int *Next, t_Directory_Entry* Buffer, char *Wildcard) {

	t_OSGBPB10Block Entry;

	// get next entry...
	SWIRegs.r[0] = 10;
	SWIRegs.r[1] = (int)(Path);
	SWIRegs.r[2] = (int)(&Entry);
	SWIRegs.r[3] = 1;
	SWIRegs.r[4] = *Next;
	SWIRegs.r[5] = sizeof(t_OSGBPB10Block);
	SWIRegs.r[6] = (int)(Wildcard);
	if (SWIX(OS_GBPB) != NULL) { *Next = -1; return(False); }
	*Next = SWIRegs.r[4];

	// nothing gotten
	if (SWIRegs.r[3] == 0) { return(False); }

	// Simple ones
	Buffer->Length = Entry.Length;
	strcpy(Buffer->Name,Entry.Name);

	// Enhance type of object
	Buffer->Objecttype = Entry.Objecttype;
	// Image flag
	if (Buffer->Objecttype == (FilerMask_TypeFolder | FilerMask_TypeFile)) {
		Buffer->Objecttype =  Buffer->Objecttype | FilerMask_TypeImage;
	}
	// Application flag
	if ((Buffer->Objecttype & FilerMask_TypeFolder) == FilerMask_TypeFolder) {
		if (Buffer->Name[0] == '!') {
			Buffer->Objecttype = (Buffer->Objecttype & ~FilerMask_TypeFolder) | FilerMask_TypeApplication;
		}
	}

	// LoadExec Timestamp
	if ((Entry.Load & LoadExecMask) == LoadExecMask) {
		Buffer->Filetype = (Entry.Load >> 8) & 0xFFF;
		Buffer->Timestamp.Parts.High = (char)(Entry.Load & 0xff);
		Buffer->Timestamp.Parts.Low  = Entry.Exec;
		}
	else {
		Buffer->Filetype = -1;
		Buffer->Timestamp.Parts.High = 0;
		Buffer->Timestamp.Parts.Low  = 0;
		}

	// Get age
	Buffer->Age = Time_AgeDays(&(Buffer->Timestamp));

	// Format timestamp
	SWIRegs.r[0] = -1;
	SWIRegs.r[1] = (int)((char*)(&(Buffer->Timestamp)));
	SWIRegs.r[2] = (int)(&(Buffer->DateTime));
	SWIX(Territory_ConvertTimeToOrdinals);

	return(True);
}



int Directory_GetNextEntryFiltered(char *Path, int *Next, t_Directory_Entry* Buffer, char *Wildcard, int Filetype, int MinAge, int MaxAge, int NoFile, int NoFolder, int NoApplication) {

	while (True) {

		// get next entry and if none return that
		if (!Directory_GetNextEntryNamed(Path,Next,Buffer,Wildcard)) { return(False); }

		//printf("DGEF %d %s\n",*Next,Buffer->Name);

		// Check Filetype - if no good or not a file get next one
		if (Filetype >= 0) {
			if ((Buffer->Filetype != Filetype) || (Buffer->Objecttype & FilerMask_TypeFile) == 0) { continue; }
		}

		// Check Objecttype
		if ((NoFile)        && (Buffer->Objecttype & FilerMask_TypeFile)        != 0) { continue; }
		if ((NoFolder)      && (Buffer->Objecttype & FilerMask_TypeFolder)      != 0) { continue; }
		if ((NoApplication) && (Buffer->Objecttype & FilerMask_TypeApplication) != 0) { continue; }

		// Check age
		if ((MinAge != -1) && (Buffer->Age < MinAge)) { continue; }
		if ((MaxAge != -1) && (Buffer->Age > MaxAge)) { continue; }

		// I got one...
		return(True);
	}

}


int main (int argc, char *argv[]) {


	char typ[8];

	if (argc != 2) {
		printf("'nen Pfad braucht's schon als Parameter! \n");
		return 4;
	}

	// get my path
	strcpy(MyPath,argv[1]);

	do {
		//if (Directory_GetNextEntry((char*)&MyPath,&MyNext,&MyDirectoryEntry)) {
		if (Directory_GetNextEntryFiltered((char*)&MyPath,&MyNext,&MyDirectoryEntry,"*",-1,20,-1,False,False,False)) {
		//if (Directory_GetNextEntryNamed((char*)&MyPath,&MyNext,&MyDirectoryEntry,"flat*")) {
			if ((MyDirectoryEntry.Objecttype & FilerMask_TypeApplication) != 0) { strcpy(typ,"app");  }
			if ((MyDirectoryEntry.Objecttype & FilerMask_TypeFolder)      != 0) { strcpy(typ,"dir");  }
			if ((MyDirectoryEntry.Objecttype & FilerMask_TypeImage)       != 0) { strcat(typ,"!");    }
			else                                                          { strcat(typ," ");    }
			if ((MyDirectoryEntry.Objecttype & FilerMask_TypeFile)        != 0) { strcpy(typ,"file"); }
			printf("%s %03X %03X %d %s\n",typ,MyDirectoryEntry.Objecttype,MyDirectoryEntry.Filetype,MyDirectoryEntry.Age,MyDirectoryEntry.Name);
		}
	} while (MyNext != -1);


	return 0;
}
