'''lecture_25_student.py
Our very first class! Represents a Student
Oliver W. Layton
CS 151: Computational Thinking: Visual Media
Spring 2021

TODO:
Make Student class with methods:
- Constructor with 2 parameters: name and year
- get methods
- set methods
    - Main code: Create two students, get and print their names and years
    - Main code: Loop thru students calling common method
    - Main code: Set one of their years, print both years
    - Discuss self parameter in method definition vs calling method.
- Function vs method: wite a printName() as function and method. Show differences.
- Calling methods inside class: Add grades IV, write addGrade printGrades methods.
- Add gpa to constuctor (show keyword args)
- addBonusPoints method
'''


def printName():
    print('Hi, my name is Oliver!')


class Student:
    def __init__(self, name, year, gpa=4.0):
        '''The Student constructor'''
        # print('name is:', name)
        # print('year is:', year)
        self.name = name
        self.year = year
        # defining instance variances called name (self.name) and year (self.year) based on
        # function parameter values (name) and (year)

        # Make a instance variable for the student's grades
        self.grades = []

        # Create gpa instance variable
        self.gpa = gpa

    def getName(self):
        '''get the student's name stored in the instance variable self.name'''
        return self.name  # <- instance variables live on throughout the object
        # return name #<- does not work! name was a variable that went away after constructor ended
        
    def getYear(self):
        return self.year

    def getGrades(self):
        return self.grades

    def getGPA(self):
        return self.gpa

    def setYear(self, newYear):
        self.year = newYear

    def setName(self, newName):
        self.name = newName

    def setFirstGrade(self, newGrade):
        self.grades[0] = newGrade

    def printName(self):
        print('Hi, my name is', self.name)

    def addGrade(self, newGrade):
        self.grades.append(newGrade)

    def setGrades(self, newGrades):
        '''newGrades: list.
        Will wipe/clear out the existing grades list and replace it entirely with new list'''
        self.grades = newGrades

    def printGrades(self):
        # get grades first
        # print(self.grades)  # Using the instance variable
        print(self.getGrades())  # Calling a METHOD from within the same class

    def changeFirstGradeToA30(self):
        self.setFirstGrade(30)

    def addBonusPoints(self, numBonusPoints):
        for i in range(len(self.grades)):
            self.grades[i] = self.grades[i] + numBonusPoints





if __name__ == '__main__':
    # jane = Student('Jane', 2021)
    # bobby = Student('Bobby', 2024)
    # print('The 1st student\'s name:', jane.getName(), 'graduating in year', jane.getYear())
    # print('The 2nd student\'s name:', bobby.getName(), 'graduating in year', bobby.getYear())

    # We want to delay Jane's graduation year to 2022
    # print('Jane\'s graduation year (before):', jane.getYear())
    # jane.setYear(2022) # <-- usually NOT the case
    # something = jane.setYear(2022) # <-- usually NOT the case
    # print('Jane\'s graduation year is now:', jane.getYear())

    # get methods: we return something:
    # studentName = jane.getName()
    # print('Name is:', studentName)

    # students = [jane, bobby]
    # for student in students:
    #     print('Student graduating in:', student.getYear())
    

    # function vs method
    # call the printName function
    # printName()

    # call the printName method. Need to call methon ON a SPECIFIC student
    # jane.printName()
    # bobby.printName()

    # Let's be able to record and update student grades
    # jane = Student('Jane', 2021)
    # print('Jane\'s current grades:', jane.getGrades())
    # print('Adding a 27 to Jane\'s grades...')
    # jane.addGrade(27)
    # print('Jane\'s current grades:', jane.getGrades())
    # jane.printGrades()

    # jane.changeFirstGradeToA30()
    # jane.printGrades()

    # jane = Student('Jane', 2021)
    # for i in range(5):
    #     jane.addGrade(30)
    # jane.printGrades()

    # jane.setGrades([27, 27])
    # jane.addGrade(27)
    # jane.addGrade(27)
    # jane.printGrades()

    jane = Student('Jane', 2021)  # assume GPA is 4.0
    bobby = Student('Bobby', 2024, gpa=3.0)  # overide GPA to 3.0
    # print(jane.getGPA())
    # print(bobby.getGPA())

    # Enter their current grades:
    for i in range(5):
        jane.addGrade(27)

    for i in range(3):
        bobby.addGrade(25)

    # Add bonus points to their grades
    jane.addBonusPoints(3)
    bobby.addBonusPoints(3)
    jane.printGrades()
    bobby.printGrades()
