// Parameters: Options Path Command
// Path must point to a folder
// Command should include "%p" for the path to be put someplace
// Options (just first character is used):
// -Placeholder Placeholder for path in Command
// -ErrorIgnore Continue on error
// -Type        file type in hex notation
// -File        I take files
// -Directory   I take directories
// -Application I take applications (i.e. directories starting with !)
// -Verbose     I say a bit more...

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

#define  False 0
#define  True  !(False)

void Abort(char *oops) { printf("Aborting: %s\n",oops); exit(4); }

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

	// My interface variables for RISC OS
	_kernel_swi_regs regs;
	_kernel_oserror *error;

	// Variables can be really useful...
	char *ParmPath = NULL;
	char *ParmCommand = NULL;
	int  ParmError = False;
	int  ParmType = -1;
	int  ParmFile = False;
	int  ParmDirectory = False;
	int  ParmApplication = False;
	int  ParmAll = True;
	int  ParmVerbose = False;
	char ParmPlaceholder = '*';

	// And some working variables for loops etc.
	int  i;
	char *s;


	// Read parameters and check them
	if (argc < 1) { Abort("No parameter given - so nothing to do\n"); }

	for (i=1; i<argc; i++) {
		if (argv[i][0] == '-') {
			// Option...
			if (strlen(argv[i]) == 1) { Abort("Useless option given"); }
			switch (argv[i][1]) {
				case 'p':
				case 'P':
					i++; if (i >= argc) { Abort("Placeholder value not given"); }
					ParmPlaceholder = argv[i][0];
					break;
				case 't':
				case 'T':
					i++; if (i >= argc) { Abort("Type value not given"); }
					ParmType = (int)strtol(argv[i],(char**)NULL,16);
					break;
				case 'e':
				case 'E':
					ParmError = True;
					break;
				case 'f':
				case 'F':
					ParmAll = False; ParmFile = True;
					break;
				case 'd':
				case 'D':
					ParmAll = False; ParmDirectory = True;
					break;
				case 'a':
				case 'A':
					ParmAll = False, ParmApplication = True;
					break;
				case 'v':
				case 'V':
					ParmVerbose = True;
					break;
				default:
					Abort("Unknown option given");
			}
		}
		else {
			// no option, so first path, then command and then too much
			if (ParmPath == NULL) { ParmPath = argv[i]; }
			else if (ParmCommand == NULL) { ParmCommand = argv[i]; }
			else Abort("Too many parameters given");
		}
	}

	// I do need these two to have something to do...
	if (ParmPath == NULL)    { Abort("No path given"); }
	if (ParmCommand == NULL) { Abort("No command given"); }

	// Is the command useful, i.e. contains one placeholder?
	s = strchr(ParmCommand,ParmPlaceholder);
	if (s == NULL) { Abort("Command lacks the place holder"); }
	if (strchr(++s,ParmPlaceholder) != NULL) { Abort("Command has more than one place holder"); }

	// Nosy bastard...
	if (ParmVerbose) {
		printf("Path: %s\n",ParmPath);
		printf("Command: %s\n",ParmCommand);
		if (ParmError) { printf("- Ignore Errors\n"); }
		if (!ParmAll) {
			printf("- I take only ");
			if (ParmFile) { printf("Files "); }
			if (ParmDirectory) { printf("Directories "); }
			if (ParmApplication) { printf("Applications "); }
			printf("\n");
		}
		if (ParmType != -1) { printf("- I take only this file type: &%X\n",ParmType); }
	}

	// Check that the path points to a folder
	regs.r[0] = 17;
	regs.r[1] = (int)ParmPath;
	if ((error = _kernel_swi(OS_File,&regs,&regs)) != NULL) { Abort("Seems that you did not pass me an existing path"); }
	if (regs.r[0] == 0) { Abort("You passed me something that does not exist"); }
	if (regs.r[0] == 1) { Abort("You passed me just a simple file"); }

	// OK, now we are good to go
	struct {
		int LoadAddress;
		int ExecAddress;
		int Length;
		int Attributes;
		int ObjectType;
		char FileNameBuffer[256]; // RISC OS allows 255 chars in a file name; add one for the trailing 0
	} FileBuffer;
	int  NextFile;
	char *FileName = (char*)&(FileBuffer.FileNameBuffer);
	int FileType;
	int ILikeIt;

	char *Buffer;
	int BufferLength;
	BufferLength = strlen(ParmPath) + strlen(ParmCommand) + 256 + 1;
	Buffer = malloc(BufferLength);
	if (Buffer == NULL) { Abort("I do need a little more RAM please"); }

	// Read the directory now
	NextFile = 0;
	do {
		regs.r[0] = 10;
		regs.r[1] = (int)ParmPath;
		regs.r[2] = (int)&FileBuffer;
		regs.r[3] = 1;
		regs.r[4] = NextFile;
		regs.r[5] = sizeof(FileBuffer);
		regs.r[6] = 0;
		if ((error = _kernel_swi(OS_GBPB,&regs,&regs)) != NULL) { Abort("Oops, error reading in the directory"); }
		NextFile = regs.r[4];
		if (regs.r[3] > 0) {
			// If LoadAddress has top 12 bits set then next 12 bits are the file type
			if ((FileBuffer.LoadAddress & 0xFFF00000) == 0xFFF00000) {
				FileType = (FileBuffer.LoadAddress & 0x000FFF00) >>8;
			}
			else { FileType = -1; }
//printf("I found %s\n",FileName);

			// Did I limit the object type
			ILikeIt = False;
			if (ParmAll) {
				ILikeIt = True;
			}
			else {
				if (ParmFile) {
					if ((FileBuffer.ObjectType & 0x1) == 0x1) { ILikeIt = True; }
				}
				if (ParmDirectory) {
					if ((FileBuffer.ObjectType & 0x2) == 0x2 && FileName[0] != '!') { ILikeIt = True; }
				}
				if (ParmApplication) {
					if ((FileBuffer.ObjectType & 0x2) == 0x2 && FileName[0] == '!') { ILikeIt = True; }
				}
			}
			// Did I limit the FileType
			if (ParmType != -1 && (FileBuffer.ObjectType & 0x1) == 0x1) {
				if (ParmType != FileType) { ILikeIt = False; }
			}
			if (ILikeIt) {
//printf("I like %s\n",FileName);
				strcpy(Buffer,ParmCommand);
				s = strchr(Buffer,ParmPlaceholder);
				strcpy(s,ParmPath);
				strcat(Buffer,".");
				strcat(Buffer,FileName);
				s = strchr(ParmCommand,ParmPlaceholder);
				s++;
				strcat(Buffer,s);
				if (ParmVerbose) { printf("Executing %s\n",Buffer); }
				regs.r[0] = (int)Buffer;
				if ((error = _kernel_swi(OS_CLI,&regs,&regs)) != NULL) {
					if (ParmVerbose) printf("Result: %s\n",(char*)&(error->errmess));
					if (!ParmError) { Abort("The command failed"); }
				}
				else {
					if (ParmVerbose) printf("Result: OK\n");
				}
			}
		}
	}
	while (NextFile != -1);

	return 0;
}


