import java.util.ArrayList;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

// NOTE: there will probably only be one instance of a school object ever
public class School {
	private ArrayList<Instructor> instructorList;
	private ArrayList<Course> courseList;
	private ArrayList<Student> studentList;
	private String name;

	public School(/*String file,*/ String schoolName) {
		this.instructorList = new ArrayList<Instructor>();
		this.courseList = new ArrayList<Course>();
		this.studentList = new ArrayList<Student>();

		this.name = schoolName;
		//readData(file);
	}
	public void readData(String filename) {
			try {
				BufferedReader reader = new BufferedReader(new FileReader(filename));
				// first line is how many instructors we want to add
				int inst_count = Integer.parseInt(reader.readLine());
				for(int i =0;i<inst_count;i++) {
					// now we shold begin to populate out instructor list
					String[] data = reader.readLine().split(",");
					int tmp_id = Integer.parseInt(data[0]);

					// ignoring the return value as those custom messages are in the method itself
					this.addInstructor(tmp_id, data[1], data[2],data[3]);
				}
				// next line should be number of courses to add
				int course_count = Integer.parseInt(reader.readLine());
				for(int i =0;i<course_count;i++) {
					String[] data = reader.readLine().split(",");
					int tmp_id = Integer.parseInt(data[0]);
					int inst_id = Integer.parseInt(data[2]);

					this.addCourse(tmp_id, data[1], inst_id, data[3]);
				}
				// finally the amount of students we want to add is next
				int student_count = Integer.parseInt(reader.readLine());
				for(int i =0;i<student_count;i++) {
					// parse items from the current line
					String[] data = reader.readLine().split(",");
					int stud_id = Integer.parseInt(data[0]);
					int cour_id = Integer.parseInt(data[2]);
					float fl_grade = Float.parseFloat(data[3]);

					// attempt to add the student
					this.addStudent(stud_id, data[1], cour_id, fl_grade, data[4]);
				}
				System.out.println("Done.");
			}
			catch(IOException e) {
				e.printStackTrace();
			}
		}
	public boolean addInstructor(int id, String name, String email, String phone) {
		// make sure that the new instructor isn't already in the system
		for(Instructor i : this.instructorList) {
			if(id == i.id) {
				System.out.println("Instructor ID already in use");
				return false;
			}
		}
		Instructor new_inst = new Instructor(id, name, email, phone);
		instructorList.add(new_inst);
		return true;
	}
	public boolean addCourse(int id, String title, int instructorID, String location) {
		// make sure we don't the same course twice
		for(Course c : this.courseList) {
			if(c.id == id) {
				System.out.println("Course addition failed – Course number already used.");
				return false;
			}
		}
		// check if the instructor exists
		boolean instructorExists = false;
		for(Instructor i : this.instructorList) {
			if(i.id == instructorID) {
				instructorExists = true;
			}
		}
		if(!instructorExists) {System.out.println("Course addition failed – Non-existing instructor.");}
		// check the instructor
		Course new_course = new Course(id, title, instructorID, location);
		courseList.add(new_course);
		return true;
	}

	public int courseEnrolled(int id) {
		// Helper function which simply counts up how many people are enrolled in a given cuorse
		int count = 0;
		for(Student s: this.studentList) {
			if(s.courseID == id) {
				count++;
			}
		}
		return count;
	}

	public String getInstructor(int id) {
		// find the instructor name given an id
		for(Instructor i : this.instructorList) {
			if(i.id == id) {
				return i.name;
			}
		}
		return "Not Found";
	}
	public float courseAverage(int id) {
		// gets average of all the students grades for a given course by id
		float sum = 0;
		int count = 0;
		for(Student s : this.studentList) {
			if(s.courseID == id) {
				sum += s.floatGrade;
				count++;
			}
		}
		if(count == 0) {
			return 0.00f;
		}

		return sum / (float)count;
	}

	public void courseInfo(int id) {
		boolean found = false;
		// look for the course given by the id
		for(Course i : this.courseList) {
			found = true;
			if(i.id == id) { 
				System.out.println("Course number: " + i.id);
				System.out.println("Instructor: "+ this.getInstructor(i.instructorID));
				System.out.println("Course title: " + i.title);
				System.out.println("Room: " + i.location);
				System.out.println("Total enrolled: " + this.courseEnrolled(id));
				System.out.println("Course average: " + this.courseAverage(id));
			}
		}
		if(!found) {
			System.out.println("Course not found: [id = " + id + "]");
		}
	}

	public void courseInfo() {
		System.out.println("Number of courses: " + this.courseList.size());
		for(Course c : this.courseList) {
			System.out.println(c.id + ": " + this.courseEnrolled(c.id) + " enrolled");
		}
	}
	public Course getCourse(int id) {
		for(int i =0;i<this.courseList.size();i++) {
			if(this.courseList.get(i).id == id) {
				return this.courseList.get(i);
			}
		}
		return null;
	}
	public boolean courseEmpty(int courseID) {
		for(Student s : this.studentList) {
			if(s.courseID == courseID) {
				return false;
			}
		}
		return true;
	}
	public boolean deleteCourse(int id) {
		for(int i =0;i<this.courseList.size();i++) {
			if(this.courseEmpty(this.courseList.get(i).id)) {
				if(this.courseList.get(i).id == id) {
					this.courseList.remove(i);
					return true;
				}
			}
		}
		return false;
	}
	public boolean addStudent(int id, String name, int courseID, float floatGrade, String letterGrade) {
		for(Student i : this.studentList) {
			if(i.id == id) {
				// attempt to regitser the student in case they're trying to add a new course
				// this method should also give us proper error msgs about registering
				if(this.register(id, courseID, floatGrade, letterGrade)) {
					return true;
				}
				return false;
			}
		}
		// check if the course even exists at all 
		boolean cFound = false;
		for(Course c : this.courseList) {
			if(c.id == courseID) {
				cFound = true;
			}
		}
		if(!cFound) {
			System.out.println("Course does not exist");
			return false;
		}

		// finally we can add the student into the system
		// this is assuming we didn't register them earlier
		Student new_student = new Student(id, name, courseID, floatGrade, letterGrade);
		studentList.add(new_student);
		return true;
	}
	private float studentAverage(int id) {
		float sum = 0.0f;
		int count = 0;
		for(Student s : this.studentList) {
			if(s.id == id) {
				sum += s.floatGrade;
				count++;
			}
		}
		return sum/(float)count;
	}
	private String studentCourses(int id) {
		String info = "";
		for(Student s : studentList) {
			if(s.id == id) {
				info += s.courseID + ": " + s.floatGrade +
					" " + s.letterGrade;
			}
		}
		return info;
	}
	public Student getStudentInfo(int id) {
		for(int i =0; i<this.studentList.size(); i++) {
			if(this.studentList.get(i).id == id) {

				this.studentList.get(i).average = studentAverage(id);
				this.studentList.get(i).courseInfo = studentCourses(id);

				return this.studentList.get(i);
			}
		}
		return null;
	}
	public boolean graduateStudent(int id) {
		// remove the student from all courses and set their only course id to graduated=0
		Student tmp =  getStudentInfo(id);
		if(tmp == null) {
			System.out.println("Student not found");
			return false;
		}
		tmp.courseID = 0;
		tmp.status = "Graduated";
		return true;
	}

	public boolean register(int studentID, int courseID, float floatGrade, String letterGrade) {
		Student tmp = this.getStudentInfo(studentID);
		if(tmp.courseID == courseID) {
			System.out.println("Student already enrolled");
			return false;
		}
		// make sure we don't try to regitster for a course that doesn't exist
		if(this.getCourse(courseID) == null) {
			return false;
		}
		// if the student is there but not enrolled in that course then just create a new student with new data
		Student new_student = new Student(tmp.id, tmp.name, courseID, floatGrade, letterGrade);
		studentList.add(new_student);
		return true;
	}
	public void drop(int studentID, int courseID) {
	}
	public void assign(int instructorID, int courseID) {
	}
	public void unassign(int instructorID, int courseID) {
	}
	// basic printout of school infor
	public void schoolInfo() {
		System.out.println("School name: " + this.name);
		// instructors
		System.out.println("Instructor info");
		for(Instructor i : this.instructorList) {
			System.out.println(i.name);
		}
		// courses
		System.out.println("Course Information");
		for(Course c : this.courseList) {
			System.out.println(c.title);
		}
		// students
		System.out.println("Student Information");
		for(Student s : this.studentList) {
			// grab the course which the student is enrolled in
			Course c_title = this.getCourse(s.courseID);
			System.out.println(s.name + ": " + c_title.title);
		}
	}
}
