Download get_new_entry.h
//Function for getting user date for new entry.
////Brian Smith 2022-04-10

/*Copyright (C) 2022  Brian R. Smith
 * Contact: briansmith2865@gmail.com

**The source code in this file is free software: you can
**redistribute it and/or modify it under the terms of the GNU
**General Public License (GNU GPL) as published by the Free Software
**foundation, either version 3 of the License, or (at your option)
**any later version.  The code is distributed WITHOUT ANY WARRANTY;
**without even the implied warranty of MERCHANTABILITY or FITNESS
**FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.
**
**As additional permission under GNU GPL version 3 section 7, you
**may distribute non-source (e.g., minimized or compacted) forms of
**that code without the copy of the GNU GPL normally required by
**section 4, provided you include this license notice and a URL
**through which recipients can access the Corresponding Source.
**
** @licend  The above is the entire license notice
**for the source code in this file.
*/

#ifndef GET_NEW_ENTRY_H
#define GET_NEW_ENTRY_H


//User data should have format 'KEYWORD: DATA'
//Commands with no data (print, cancel, clear) do not need a colon.
//command 'done' needs a colon: should be entered 'done:'


//KEYWORDS::
//done --- finished, exit func., ret_code for 'entry to be saved'.
//cancel ---- finished, exit func., ret_code for 'do not save'.
//print --- show entry.
//clear -- clear screen
//date --- command format -- 'date: yy-mm-dd'
//start --- command format -- 'start: hh:mm'
//end --- command format -- 'end:hh:mm'
//type --- sesion type after colon. Format 'type: sessiontype'
//	types are 'ausk, lekt, meet, conv'. Anything else will result in NOTSET.
//with --- format: 'with: anystring'. max string length 20 bytes.
//comments --- format: 'comments: whaterveryouwant'. Max length 1024 bytes.
//
//WARNING: I'm not always checking if user data will fit in buffers :-/


#include"parse_log_entry.h"

char* EMPTY_STRING = ""; //An empty string as macro. This is sometimes needed since comments
//is a pointer to comments ... needs somewhere to point even if empty.

//Aux functions: declared here, defined after next func.
int noMatch(LOG_ENTRY* entry, LOG_INDEX* schedule_start);
int schedOverlap(LOG_ENTRY* entry, LOG_INDEX* schedule_start);


void getNewEntry (LOG_INDEX** index_start, int* NUM_ELEMS, LOG_INDEX* schedule_start) {
	

	char ds = 0, t1 = 0, t2 = 0, cs = 0, ws = 0; //Set to 1 if, respectively, 
	//date is set, startime is set, endtime is set, comments are given, 'with' is set. 

	//Allocate a LOG_ENTRY.
	LOG_ENTRY* entry = (struct LOG_ENTRY*) malloc(sizeof(struct LOG_ENTRY));
	init_entry(entry); //Set all bytes to 0, sessiontype to NOTSET.
	//NOTE: I should probably free this before program exit. I'm also allocating
	//in insertentry().

	char comments[2048];  //Buffer for comments.
	memset(comments, 0, 2048); //All bytes to 0.

	char buff[2048]; //Buffer for user commands. 
	int ret_code= 0;

	char no_colon; //Record if colon was found in string.
	char* keyword; //Will be pointer to keyword.
	while(1) {
		printf("\033[0;35m>>>>>>>>\033[0m ");
		getmaline(buff);
		char* rest = toColon(&no_colon, buff);
		if(no_colon){
			keyword = strip(buff);
			if(strcmp(keyword, "print") == 0)
				printEntry(entry, comments);
			else if(strcmp(keyword, "cancel") == 0){
				free(entry);
				return;
			}
			else if(strcmp(keyword, "clear") == 0)
				system("clear");

			else
				printf("Colon expected.\n");
		}
		else {
			keyword = strip(buff);

			if (strcmp(keyword, "cancel") == 0) {//Can also enter 'cancel:'
				free(entry);
				return;
			}
			else if(strcmp(keyword, "print") == 0) //Can alos enter 'print:'
				printEntry(entry, comments);
			else if(strcmp(keyword, "date")==0) {
				if(getdate(&(entry->date), rest) != 0)
					printf("INVALID DATE\n");
				else { 
					ds = 1;
					setWday(entry); //Don't forget to set day of week!
				}
			}
			else if(strcmp(keyword, "start")==0) {
				if(gettime(&(entry->startTime), rest) != 0)
					printf("INVALID TIME\n");
				else t1 = 1;
			}
			else if(strcmp(keyword, "end")==0) {
				if(gettime(&(entry->endTime), rest) != 0)
					printf("INVALID TIME\n");
				else t2 = 1;
			}
			else if(strcmp(keyword, "type")==0) {
				rest = strip(rest);
				entry->sessiontype = fromString(rest);
			}

			else if (strcmp(keyword, "with") == 0) {
				rest = strip(rest);
				if(strlen(rest) >= 20)
					printf("\033[0;31mONLY 20 BYTES ALLOWED IN FIELD.\033[0m\n");
				else {
					strcpy(entry->with, rest);
					ws = 1;
				}
			}
			else if (strcmp(keyword, "comments") == 0) {
				rest = strip(rest);
				strcpy(comments, rest);
				cs = 1;
			}
			else if (strcmp(keyword, "done") == 0){ //Logic below may get a bit convoluted :-/
				if (ds && t1 && t2 && cs  && ws && cmptm(&(entry->startTime), &(entry->endTime)) < 0) {
					char* new_comments = NULL;
					int comm_len = strlen(comments);
					if(comm_len > 0) {
						new_comments = (char*)malloc(comm_len+1);
						strcpy(new_comments, comments);
					}
					else new_comments=EMPTY_STRING;
					if(entry != NULL) {  //Insert new_entry in list:
						if(noMatch(entry, schedule_start)){ //Check to see if entry matches
						//schedule on file.
							printf("\033[0;31mNO ENTRY MADE.\033[0m.\n");
						}
						else if(schedOverlap(entry, schedule_start)){//Check if non-scheduled
							//even conflicts with schedule. schedOverlap() defined after current func.
							printf("\033[0;31mNO ENTRY MADE.\033[0m\n");
						}
						else {
							LOG_INDEX* ret_p = insertentry(index_start, entry, new_comments);
							//ret_p points to overlaping entry if overlap; NULL otherwise.	
							if(ret_p == NULL) {
								++(*NUM_ELEMS); //DON'T FORGET THIS!
								printf("\033[0;32m\nNEW ENTRY INSERTED IN LIST.\033[0m\n\n");
								return;	
							}
							else {
								printf("\033[0;31mOVERLAP WITH:\n");
								printEntry(ret_p -> entryPtr, ret_p->comments);
							}
							
						}
					}
					else  {
							printf("\033[0;31m\nNO NEW LOG ENTRY MADE.\033[0m\n\n");
							free(entry);
					}
				}
				
				else {
					if(cmptm(&(entry->startTime), &(entry->endTime)) >= 0)
						printf("\033[0;31mEnd TIME SAME AS OR BEFORE START TIME.\033[0m\n");
					else
						printf("\033[0;31mSOME FIELDS HAVE NOT BEEN FILLED.\033[0m\n");
				}
			}
			else {
				printf("INVALD KEYWORD\n");
			}
		}
	}
}



//If type is ausk or lekt checks for missmatch with schedule.
//Returns 1 if missmatch and user does not wish to proceed.
//0 otherwise.
int noMatch(LOG_ENTRY* entry, LOG_INDEX* schedule_start) {
	char buff[10];
	char* s;

	if(entry->sessiontype != AUSK && entry->sessiontype != LEKT)
		return 0;
	
	for(LOG_INDEX* p = schedule_start; p != NULL; p = p->next) {
		if(
			(entry->date).wday == ((p->entryPtr)->date).wday
		 	&& memcmp(&(entry->startTime), &((p->entryPtr)->startTime), sizeof(struct mytime)) == 0
			&& memcmp(&(entry->endTime), &((p->entryPtr)->endTime), sizeof(struct mytime)) == 0
			&& entry->sessiontype == (p->entryPtr)->sessiontype
			&& strcmp(entry->with, (p->entryPtr)->with) == 0
		) return 0;
	}

	printf("\033[0;31mLESSON/AUDIT: SCHEDULE MISSMATCH!!\n DO YOU WISH TO PROCEED? (y/n)\033[0m\n");
	getmaline(buff); s = strip(buff);
	if(strcmp(s, "y") == 0)
		return 0;
		
	return 1;
}


//Checks if non-scheduled event overlaps with schedule. 
//If overlap and user does not wish to proceed returns 1.
//0 otherwise.
int schedOverlap(LOG_ENTRY* entry, LOG_INDEX* schedule_start) {
	char buff[10];
	char* s;

	if(entry->sessiontype == LEKT || entry->sessiontype == AUSK)
		return 0;

	for(LOG_INDEX* p = schedule_start; p != NULL; p = p->next) {
		if(overlap2(entry, p->entryPtr)) {
			printf("\033[0;31mCONFLICT WITH: \n\033[0m");
			printEntry(p->entryPtr, p->comments);
			printf("\033[0;31mDO YOU WISH TO PROCEED? (y/n)\033[0m");
			getmaline(buff); s = strip(buff);
			if(strcmp(s,"y") == 0)
				return 0;
			return 1;
		}
	}
	return 0;
}



#endif