﻿// Assignment 8 is based on the project for Assignment 7.
// Number-prefixed comments refer to specific assignment requirements, e.g. //A8.3 means assignment 8, requirement 3

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Module_8_Assignment
{
    //====================================================================================
    public class Person
    {
        // public properties
        public string FirstName { get; set; }
        public string LastName { get; set; }

        // public constructors
        public Person()
        {
        }
        public Person(string firstNameIn, string lastNameIn)
        {
            this.FirstName = firstNameIn;
            this.LastName = lastNameIn;
        }
    }
    //====================================================================================
    public class Student : Person
    {
        // private member variables
        private static int count = 0; // static variable to count number of students
        private Stack<String> grades = new Stack<String>(); // A8.3: Create a Stack<T> object, of the proper data type, inside the Student object, called Grade, to store test scores.

        // public properties
        public DateTime BirthDate { get; set; }
        public static int Count
        {
            get
            {
                return count;
            }
        }
        public Stack<String> Grades
        {
            get
            {
                return grades;
            }
        }

        // public constructors
        public Student(string firstNameIn, string lastNameIn, DateTime birthDateIn)
        {
            this.FirstName = firstNameIn;
            this.LastName = lastNameIn;
            this.BirthDate = birthDateIn;
            count++; // increment the Student object counter
        }

        // methods
        public void TakeTest()
        {
            // not implemented...throw an exception for now
            throw new System.NotImplementedException();
        }
        public void AddGrade(string grd)
        {
            Grades.Push(grd); // push a grade on the grade stack
        }
    }
    //====================================================================================
    public class Teacher : Person
    {
        // public properties
        public int OfficeNumber { get; set; }

        // public constructors
        public Teacher(string firstNameIn, string lastNameIn, int officeNumberIn)
        {
            this.FirstName = firstNameIn;
            this.LastName = lastNameIn;
            this.OfficeNumber = officeNumberIn;
        }

        // methods
        public void GradeTest()
        {
            // not implemented...throw an exception for now
            throw new System.NotImplementedException();
        }
    }
    //====================================================================================
    public class Degree
    {
        // public properties
        public string DegreeName { get; set; }
        public Course Crs1 { get; set; }

        // public constructors
        public Degree(string degreeNameIn)
        {
            this.DegreeName = degreeNameIn;
        }
        public Degree(string degreeNameIn, Course crs1In)
        {
            this.DegreeName = degreeNameIn;
            this.Crs1 = crs1In;
        }
    }
    //====================================================================================
    public class Course
    {
        // members
        // A8.1: Create a List<T>, of the proper data type, to replace the ArrayList and to hold students, inside the Course object.
        private List<Student> studentsL = new List<Student>();

        // public properties
        public string CourseName { get; set; }
        public int CourseNumber { get; set; }
        public List<Student> StudentsL
        {
            get
            {
                return studentsL;
            }
        }
        public Teacher[] Teachers { get; set; }

        // public constructors
        public Course(string courseName)
        {
            this.CourseName = courseName;
        }

        // methods
        public void AddStudent(Student stdnt)
        {
            studentsL.Add(stdnt); // add a student to the List
        }
        // A8.5: Using a foreach loop, iterate over the Students in the List<T> and output their first and last names to the console window.
        // (For this exercise, casting is no longer required. Also, place each student name on its own line)
        public void ListStudents()
        {
            foreach (Student stdnt in StudentsL)
            {
                Console.WriteLine("Student: {0} {1}\n", stdnt.FirstName, stdnt.LastName);
            }
        }
    }
    //====================================================================================
    public class UProgram
    {
        // public properties
        public string ProgramName { get; set; }
        public Degree Dgr1 { get; set; }

        // public constructors
        public UProgram(string programName)
        {
            this.ProgramName = programName;
        }
    }
    //====================================================================================
    public class Program
    {
        static void Main(string[] args)
        {
            // A8.4, A7.5, A5.1: Instantiate three Student objects.
            Student s1 = new Student("Ted", "Wilson", new DateTime(1995, 11, 2));
            Student s2 = new Student("Brian", "Cripe", new DateTime(1997, 2, 23));
            Student s3 = new Student("Nelson", "Mills", new DateTime(1999, 7, 13));

            // A8.5: Add 5 grades to the Stack<T> in each Student object.
            s1.AddGrade("A");
            s1.AddGrade("A");
            s1.AddGrade("F");
            s1.AddGrade("C");
            s1.AddGrade("B");
            s1.AddGrade("D");
            s2.AddGrade("A");
            s2.AddGrade("F");
            s2.AddGrade("C");
            s2.AddGrade("B");
            s2.AddGrade("D");
            s3.AddGrade("A");
            s3.AddGrade("F");
            s3.AddGrade("C");
            s3.AddGrade("B");
            s3.AddGrade("D");

            // A5.2: Instantiate a Course object called Programming with C#.
            Course mycourse = new Course("Programming with C#");


            Course c1 = new Course("Programming with F#");
            c1.ListStudents();

            // A8.6: Add the three Student objects to the List<T> inside the Course object.
            mycourse.AddStudent(s1);
            mycourse.AddStudent(s2);
            mycourse.AddStudent(s3);

            // A8.9: Call the ListStudents() method from Main().
            mycourse.ListStudents();

            // A5.4: Instantiate at least one Teacher object.
            Teacher t1 = new Teacher("William", "Hooper", 201);
            Teacher t2 = new Teacher("Bill", "Farmer", 312);
            Teacher t3 = new Teacher("Fred", "Clegg", 407);

            // A5.5: Add the Teacher object(s) to your Course object.
            Teacher[] teachers = new Teacher[] { t1, t2, t3 };
            mycourse.Teachers = teachers;

            // A5.6: Instantiate a Degree object, such as Bachelor.
            Degree mydegree = new Degree("Bachelor of Science");

            // A5.6: Add your Course object to the Degree object.
            mydegree.Crs1 = mycourse;

            // A5.8: Instantiate a UProgram object called Information Technology.
            UProgram myprogram = new UProgram("Information Technology");

            // A5.9: Add the Degree object to the UProgram object.
            myprogram.Dgr1 = mydegree;

            // A5.10: Using Console.WriteLine statements, output the following information to the console window:

            // A5.10a: The name of the program and the degree it contains
            Console.WriteLine("The {0} program contains the {1} degree.", myprogram.ProgramName, myprogram.Dgr1.DegreeName);

            // A5.10b: The name of the course in the degree
            Console.WriteLine("The {0} degree contains the course {1}.", mydegree.DegreeName, mydegree.Crs1.CourseName);

            // A5.10c: The count of the number of students in the course
            Console.WriteLine("The {0} course contains {1} student(s).", mycourse.CourseName, Student.Count.ToString());

            // Display console window until user presses any key.
            Console.ReadKey();

        }
    }
}