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

const int ROWS = 10;
const int COLS = 4;
#define MAX_BUFFER_SIZE 100
const int ERROR = -1;
const int FIRST_SEAT = 'A';

// const int ADD_PASSENGER_OPT = 1;
#define ADD_PASSENGER_OPT 1
#define LOOKUP_BY_NAME_OPT 2
#define LOOKUP_BY_SEAT_OPT 3
#define DISPLAY_PASSENGERS_OPT 4
#define DISPLAY_SEATING_CHART_OPT 5
#define QUIT_OPT 6

struct Passenger {
	char first_name[MAX_BUFFER_SIZE];
	char last_name[MAX_BUFFER_SIZE];
	int seat_row;
	int seat_col;
	int num_bags;
};


/*
char * bad_read_string() {
	// DON'T USE THIS
	char name[MAX_BUFFER_SIZE];
	fgets(name, sizeof(name), stdin);
	return name;
}
*/

void read_string(char * destination, int num_chars_to_read) {
	fgets(destination, num_chars_to_read, stdin);

	// Strip the final new line character
	destination[strcspn(destination, "\n")] = 0;
}

/*
 * This function returns -1 if it fails
 */
char read_char() {
	char return_value;

	char buffer[MAX_BUFFER_SIZE];
	read_string(buffer, MAX_BUFFER_SIZE);
	char garbage[MAX_BUFFER_SIZE]; // this is to collect any garbage AFTER the integer

	if (1 != sscanf(buffer, "%c%s", &return_value, garbage)) {
		// couldn't read an integer
		return_value = ERROR;
	}
	// printf("Garbage: %s", garbage);


	return return_value;
}

/*
 * This function returns -1 if it fails
 */
int read_integer() {
	int return_value;

	char buffer[MAX_BUFFER_SIZE];
	read_string(buffer, MAX_BUFFER_SIZE);
	char garbage[MAX_BUFFER_SIZE]; // this is to collect any garbage AFTER the integer

	if (1 != sscanf(buffer, "%d%s", &return_value, garbage)) {
		// couldn't read an integer
		return_value = ERROR;
	}
	// printf("Garbage: %s", garbage);

	return return_value;
}


void print_main_menu() {
	printf("****************MENU****************\n");
	printf("1. Add passenger (this just books them, not seats them)\n");
	printf("2. Lookup passenger by name (for seating, checking, etc)\n");
	printf("3. Lookup passenger by seat (for seating, checking, etc)\n");
	printf("4. Display all passengers (all booked, seated or not)\n");
	printf("5. Display seating chart\n");
	printf("6. Quit\n");
}

void editPassengerName(struct Passenger *passenger, struct Passenger * chart[][COLS]) {
	
	char user_input[MAX_BUFFER_SIZE];
	
	printf("Input passenger first name: ");
	read_string(user_input, MAX_BUFFER_SIZE);
	strcpy(passenger->first_name, user_input);
	
	printf("Input passenger last name: ");
	read_string(user_input, MAX_BUFFER_SIZE);
	strcpy(passenger->last_name, user_input);

	printf("Input passenger seat row: ");
	passenger->seat_row = read_integer();

	printf("Input passenger seat letter: ");
	passenger->seat_col = read_char() - 'A';

	chart[passenger->seat_row][passenger->seat_col] = passenger;

	// printf("Passenger name is %s %s\n", passenger->first_name, passenger->last_name);
}


/*
Print a formatted version of the seating chart (to look like a plane) to the console
Prints 'X' for occupied seats and '_' for unnoccupied seats
Also prints row and seat labels for easy reference
@param seating_chart current seating chart
*/
void display_seating_chart(struct Passenger * seating_chart[][COLS]) {
	//First print a row of seat labels (e.g., A, B, C, D)
	printf("    ");
	for (int seat = 0; seat < COLS; seat++) {
		if (seat == COLS / 2) {
			printf("   ");
		}
		// NOTE: the NOTE in the lookup_passenger_by_seat function explains
		//       the relationship between the seat label (e.g., 'A') and the seat index (e.g., 0)
		char seat_char = FIRST_SEAT + seat;
		printf("%c ",seat_char);
	}
	printf("\n");

        // Print the 2D seating chart matrix
	for (int row = 0; row < ROWS; row++) {
		printf("%d | ",row); // row label and left cabin wall
		for (int seat = 0; seat < COLS; seat++) {
			if (seat == COLS / 2) {
				printf("   "); // aisle
			}
			if (seating_chart[row][seat] == NULL) {// if seat is unoccupied
				printf("_ "); // unoccupied
			}
			else {
				printf("X "); // occupied
			}
		}
		printf("|\n"); // right cabin wall
	}

	printf("\n");
}


int main() {

	int user_choice = 1;

	// data structures

	// list of Passengers
	struct Passenger passenger_list[ROWS*COLS];
	int passenger_count = 0;

	// a seating of Passengers
	struct Passenger * seating_chart[ROWS][COLS];


	// While the user doesn't choose QUIT
	while (user_choice != 6) {
		user_choice = 6;	
		// Print the main menu
		print_main_menu();


		printf("Please enter your choice: ");
		user_choice = read_integer();

		if (user_choice > QUIT_OPT || user_choice < ADD_PASSENGER_OPT)
		{
			printf("Bad choice (%d). Please try again.\n", user_choice);
			continue;
		}

		// Solicit the user's choice
		printf("User selected option %d\n", user_choice);

		// Based on the users choice
		switch (user_choice) {
			case ADD_PASSENGER_OPT:
			struct Passenger *new_passenger = &passenger_list[passenger_count];
			editPassengerName(new_passenger, seating_chart);
			passenger_count++;

			break;

			case LOOKUP_BY_NAME_OPT:
			printf("USER CHOSE 2\n");
			break;

			case LOOKUP_BY_SEAT_OPT:
			case DISPLAY_PASSENGERS_OPT:
			printf("PASSENGER LIST:\n");
			for (int i = 0; i < passenger_count; i++) {
				printf("%i. %s %s\n", (i+1), passenger_list[i].first_name, passenger_list[i].last_name);
			}
			printf("\n");

			break;
			case DISPLAY_SEATING_CHART_OPT:
			printf("SEATING CHART:\n");
			display_seating_chart(seating_chart);
			break;
			case QUIT_OPT:

			default:
			printf("UNREACHABLE CODE EXECUTED\n");
			break;
		}

	}
	return 0;
}
