#!/usr/local/bin/perl

# this section opens the file and reads in all the information into a dummy variable
if(@ARGV > 0){
	open (FILE, $ARGV[0]) ||
		die "Can't open file $ARGV[0].\n";
}
else{
	die "Need a file on the command line.\n";
}
chomp (@allStudentInfo = <FILE>);
close FILE;

$#students = @allStudentInfo - 1; # create storage for all student info
$#names = @allStudentInfo - 1;    # create storage for all student names
$#gpas = @allStudentsInfo - 1;    # create storage for all student gpas

# this section puts all the information from the dummy variable into the 3 storage areas
for($count = 0; $count < @allStudentInfo; $count++){
	@{$students[$count]} = split(/ /, @allStudentInfo[$count]);
	$names[$count] = $students[$count][0];
	$sum = 0;
	for($i = 2; $i < @{$students[$count]}; $i++){
		$sum += $students[$count][$i];
	}
	$gpas[$count] = $sum/($i - 2);
}

# I want my menu to continue until quit - make it last forever and use die to exit
while(true){
	print "Print a student\'s report                             - p\n";
	print "Print an ascending sorted list of students           - a\n";
	print "Print a descending sorted list of students           - d\n";
	print "Print a list of passing/failing students             - l\n";
	print "Change or add or remove a grade for any student      - c\n";
	print "Quit                                                 - q\n";
	print "Save to $ARGV[0] and quit - s\n";
	chomp ($choice = <STDIN>);

# finds an input student and outputs their detailed info
	if($choice eq 'p'){
		print "What is the student's name?\n";
		chomp ($name = <STDIN>);
		for($count = 0; $count < @names; $count++){
			if($names[$count] eq $name){
				print "Name:\t$students[$count][0]\n";
				print "RIN:\t$students[$count][1]\n";
				print "Grades:\n";
				for($i = 2; $i < @{$students[$count]}; $i++){
					print "\t$students[$count][$i]\n";
				}
				print "GPA:\t$gpas[$count]\n";
				last;
			}
		}
		if ($count == @names){
			print "$name is not listed as a student.\n";
		}
	}

# Displays a list of sorted names in ascending order or a list of names and gpas
# with the gpas in ascending order.  It continues looping until 'n', 'g', or 'q'
# are pressed.  Uses brute force to display the gpa sorted list.  Does not change
# the order of students or gpas.
	elsif($choice eq 'a'){
		while(true){
			print "Sort by name - n\n";
			print "Sort by gpa  - g\n";
			print "Cancel       - q\n";
			chomp ($input = <STDIN>);
			if($input eq 'n'){
				print join("\n", sort {$a cmp $b} @names), "\n";
				last;
			}
			elsif($input eq 'g'){
				@sorted = sort {$a <=> $b} @gpas;
				for($i = 0; $i < @sorted; $i++){
					for($j = 0; $j < @gpas; $j++){
						if($sorted[$i] == $gpas[$j]){
							print "$names[$j] $gpas[$j]\n";
							if($sorted[$i] == $sorted[$i+1]){
								$i++;
							}
							else{
								last;
							}
						}
					}
				}
				last;
			}
			elsif($input eq 'q'){
				last;
			}
			else{
				print "Please enter \'n\' or \'g\'.\n\n";
			}
		}
	}

# Displays a list of sorted names in descending order or a list of names and gpas
# with the gpas in descending order.  It continues looping until 'n', 'g', or 'q'
# are pressed.  Uses brute force to display the gpa sorted list.  Does not change
# the order of students or gpas.
	elsif($choice eq 'd'){
		while(true){
			print "Sort by name - n\n";
			print "Sort by gpa  - g\n";
			print "Cancel       - q\n";
			chomp ($input = <STDIN>);
			if($input eq 'n'){
				print join("\n", reverse sort {$a cmp $b} @names), "\n";
				last;
			}
			elsif($input eq 'g'){
				@sorted = reverse sort {$a <=> $b} @gpas;
				for($i = 0; $i < @sorted; $i++){
					for($j = 0; $j < @gpas; $j++){
						if($sorted[$i] == $gpas[$j]){
							print "$names[$j] $gpas[$j]\n";
							if($sorted[$i] == $sorted[$i+1]){
								$i++;
							}
							else{
								last;
							}
						}
					}
				}
				last;
			}
			elsif($input eq 'q'){
				last;
			}
			else{
				print "Please enter \'n\' or \'g\'.\n\n";
			}
		}
	}

# Lists all passing or all failing students.  Loops until 'p' or 'f' are pushed.
	elsif($choice eq 'l'){
		while(true){
			print "List passing students >= 65 - p\n";
			print "List failing students <  65 - f\n";
			chomp ($input = <STDIN>);
			if($input eq 'p'){
				print "Passing students:\n";
				for($i = 0; $i < @gpas; $i++){
					if($gpas[$i] >= 65){
						print "\t$names[$i]\n";
					}
				}
				last;
			}
			elsif($input eq 'f'){
				print "Failing students:\n";
				for($i = 0; $i < @gpas; $i++){
					if($gpas[$i] < 65){
						print "\t$names[$i]\n";
					}
				}
				last;
			}
			else{
				print "Please enter \'p\' or \'f\'.\n\n";
			}
		}
	}

# Changes, adds, or removes a grade of a student.  Searches for the input student initially;
# if not on the list, returns to the menu.  Otherwise, it will either add a grade of your 
# choice, change a grade after entering a number from another menu or remove a grade chosen
# by a similar menu (to change a grade).  Handles error of choosing the wrong number from the 
# change grade list.  Upadates appropriate gpa.
	elsif($choice eq 'c'){
		print "Student's name?\n";
		chomp ($name = <STDIN>);
		for($ind = 0; $ind < @names; $ind++){
			if($name eq $names[$ind]){
				last;
			}
		}
		if($ind == @names){
			print "$name is not listed as a student.\n";
			next;
		}
		while(true){
			print "Add a grade    - a\n";
			print "Change a grade - c\n";
			print "Remove a grade - r\n";
			print "Cancel         - q\n";
			chomp ($input = <STDIN>);
			if($input eq 'a'){
				print "Enter a grade:\n";
				chomp ($input = <STDIN>);
				splice (@{$students[$ind]}, @{$students[$ind]}, 0, $input);
				$sum = 0;
				for($i = 2; $i < @{$students[$ind]}; $i++){
					$sum += $students[$ind][$i];
				}
				$gpas[$ind] = $sum/($i - 2);
				last;
			}
			elsif($input eq 'c'){
				print "Choose a grade:\n";
				for($i = 2; $i <@{$students[$ind]}; $i++){
					print "Enter \'" . ($i-1) . "\' for $students[$ind][$i]\n";
				}
				chomp ($input = <STDIN>);
				if($input > 0 && $input < @{$students[$ind]} - 1){
					print "Enter new grade:\n";
					chomp ($newGrade = <STDIN>);
					$students[$ind][$input+1] = $newGrade;
					$sum = 0;
					for($i = 2; $i < @{$students[$ind]}; $i++){
						$sum += $students[$ind][$i];
					}
					$gpas[$ind] = $sum/($i - 2);
				}
				else{
					print "$input is out of range.\n";
				}
				last;
			}
			elsif($input eq 'r'){
				print "Choose a grade:\n";
				for($i = 2; $i <@{$students[$ind]}; $i++){
					print "Enter \'" . ($i-1) . "\' for $students[$ind][$i]\n";
				}
				chomp ($input = <STDIN>);
				if($input > 0 && $input < @{$students[$ind]} - 1){
					splice(@{$students[$ind]}, $input+1, 1);
					$sum = 0;
					for($i = 2; $i < @{$students[$ind]}; $i++){
						$sum += $students[$ind][$i];
					}
					$gpas[$ind] = $sum/($i - 2);
				}
				else{
					print "$input is out of range.\n";
				}
				last;
			}
			elsif($input eq 'q'){
				last;
			}
			else{
				print "Please enter \'a\' or \'c\'.\n\n";
			}
		}
	}

# Saves any changes to grades back to the input file and quits.  Backs up old
# data onto <INPUTFILE>.bak
	elsif($choice eq 's'){
		open (OUT, ">" . $ARGV[0] . ".bak");
		print OUT join("\n", @allStudentInfo);
		close OUT;
		open (OUT, ">" . $ARGV[0]);
		for($i = 0; $i < @students; $i++){
			print OUT "@{$students[$i]}\n";
		}
		close OUT;
		die "File saved to $ARGV[0]; old file backed up as $ARGV[0].bak, now quitting.\n";
	}

# Quits the program
	elsif($choice eq 'q'){
		die "Thank you for using Student Information Services.\n";
	}

# Handles error of inputing non-option
	else{
		print "\'$choice\' is not an option, please choose again.\n";
	}
	print "\n";	# Makes sure there is a gap between a sub-menu and the main menu
}