##Year 2, Term 2 - Programming challenge##
##Solution##


def get_data(): 
##Reads in data from file and stores in 2-dimensional data structure loyaltyScheme.##
    fileToUse = 'SampleMembershipData.txt'
    rawData = open(fileToUse, "r")
    inputData = rawData.readlines()
    rawData.close()

    #Splits up each line into a list of strings and appends each list to loyaltyScheme.
    loyaltyScheme = []
    index = 0
    for line in inputData:
        loyaltyScheme.append(inputData[index].split(","))
        index += 1

        #Converts the data type of variables nightsBooked and pointsBalance to integer.
        for record in loyaltyScheme: 
                record[4] = int(record[4])
                record[5] = int(record[5])

    return loyaltyScheme
##endfunction##


def menu():
##Displays the menu and allows users to make a selection.##
    again = True
    while again == True:
        print("\n____________Cygnet Hotel Group Loyalty Scheme___________\n\n")
        print("MENU\n")
        
        print("Option 1\tAdd a new member\n") 
        print("Option 2\tDelete a member\n") 
        print("Option 3\tDisplay a member's status\n")
        print("Option 4\tMake a booking\n")
        print("Option 5\tRedeem points\n")
        print("Option 6\tDisplay scheme status\n")
        print('Press Q to quit the menu\n')

        optionsChoice = input('Please enter an option (1, 2, 3, 4, 5, 6 or Q): ')
        if optionsChoice == "1":
            add_new_member()
        elif optionsChoice == "2":
            delete_a_member()
        elif optionsChoice == "3":
            display_member_status()
        elif optionsChoice == "4":
            make_a_booking()
        elif optionsChoice == "5":
            redeem_points()
        elif optionsChoice == "6":
            display_scheme_status()
        elif optionsChoice.upper() == "Q":
            again = False
            quit_program()
 
##endfunction##


def return_to_menu():
##Prompts to return to menu after one of the menu options has been selected.##
    backToMenu = False
    print("")
    while backToMenu == False:
        choice = input("Enter Y to return to menu. ")
        if choice.upper() == "Y":
            backToMenu = True          
##endfunction##


def display_record(memberRecord):
##Displays a member's record.##
        print("Member ID:", memberRecord[0])
        print("Surname:", memberRecord[1])
        print("Year joined:", memberRecord[2])
        print("Current membership status:", memberRecord[3])
        print("Number of nights booked:", memberRecord[4])
        print("Current points balance:", memberRecord[5])
##endfunction##


def get_member_details(member):
##Takes in a member's ID and uses a linear search to find their record.##
    memberRecord = []

    found = False
    index = 0
    while found == False and index < len(loyaltyScheme): 
            if loyaltyScheme[index][0] == member:
                    found = True
            else:
                    index += 1
    if not found:
        print("The member ID you entered does not exist.")
    else:
        memberRecord = loyaltyScheme[index]
        display_record(memberRecord)
        
    return(memberRecord)
##endfunction##

           
def add_new_member():
##Adds a new member to the loyalty scheme.##
    print("\n____________Cygnet Hotel Group Loyalty Scheme___________\n")
    print("\n1: Add a new member")
    print("_" * 34,'\n')
    surname = input("Enter surname: ")
    
    now = datetime.datetime.now() #Looks up current year.
    yearJoined = str(now.year)
    year = yearJoined[2:] #Extracts last two digits of year to use in new ID.
    
    membershipStatus = 'Silver'
    nightsBooked = 0
    pointsBalance = 0

    
    if len(surname) == 1: #Adds extra letter(s) to short surnames.
        first3Letters = surname + "ZZ"
    elif len(surname) == 2:
        first3Letters = surname + "Z"
    else:
        first3Letters = surname[:3]
        
    global nextNumber #Changes the value of the global variable nextNumber.
    memberID = first3Letters + str(nextNumber) + year #Constructs new ID.
    nextNumber = nextNumber + 1
    
    newMember = [memberID, surname, yearJoined, membershipStatus, nightsBooked, pointsBalance]
    #Creates the new record.
    display_record(newMember) #Displays the new record.
    
    newMember =[memberID, surname, yearJoined, membershipStatus, nightsBooked, pointsBalance]
    loyaltyScheme.append(newMember) #Appends the new record to loyaltyScheme.

    return_to_menu()
##endfunction##


def delete_a_member():
##Deletes a member from the loyalty scheme.##
    print("\n____________Cygnet Hotel Group Loyalty Scheme___________\n")
    print("\n2. Delete a member")
    print('_' * 33,'\n')

    whichMember = input("Enter the member's ID number: ")
    memberRecord = get_member_details(whichMember)
    print('')
    confirm = input("Is this the member you want to delete? ")
    if confirm.upper() == "Y":
        loyaltyScheme.remove(memberRecord)
        print("\nThis record has been deleted.\n")

    return_to_menu()   
##endfunction##


def display_member_status():
##Displays a member's record.##
    print("\n____________Cygnet Hotel Group Loyalty Scheme___________\n")
    print("\n3. Display a member's status")
    print('_' * 33,'\n')
    whichMember = input("Enter the member's ID number: ")
    memberRecord = get_member_details(whichMember)

    return_to_menu()
##endfunction##


def make_a_booking():
##Updates a member's record when a new booking is made.##
     print("\n____________Cygnet Hotel Group Loyalty Scheme___________\n")
     print("\n4. Make a booking")
     print('_' * 33,'\n')

     whichMember = input("Enter the member's ID number: ")
     memberRecord = get_member_details(whichMember)

     #Adds extra nights, updates points balance and - if appropriate - updates status.
     numbNights = int(input("Enter the number of nights: "))
     if numbNights > 14:
        print("A single booking must be no more than 14 nights.")
     else:
        memberRecord[4] = memberRecord[4] + numbNights
        if memberRecord[3] == "Silver":
            memberRecord[5] = memberRecord[5] + (numbNights * 2500)
            if memberRecord[4] >= 30:
                memberRecord[3] = "Gold"
        elif memberRecord[3] == "Gold":
            memberRecord[5] = memberRecord[5] + (numbNights * 3000)
            if memberRecord[4] >= 100:
                memberRecord[3] = "Platinum"
        else:
            memberRecord[5] = memberRecord[5] + (numbNights * 4000)

        #Displays updated record.
        print("\nCurrent membership status:", memberRecord[3])
        print("Number of nights booked is now:", memberRecord[4])
        print("New points balance:", memberRecord[5])

     return_to_menu()   
##endfunction##


def redeem_points(): 
##Updates a member's record when points are redeemed.##
    print("\n____________Cygnet Hotel Group Loyalty Scheme___________\n")
    print("\n5. Redeem points")
    print('_' * 33,'\n')

    whichMember = input("Enter the member's ID number: ")
    memberRecord = get_member_details(whichMember)
    
    nights = int(input("How many nights? "))
    if nights > 14:
        print("You cannot book this many nights.")
    else:
      numbPoints = (nights * 25000) 
      if int(memberRecord[5]) < numbPoints:
          print("You don't have enough points to complete this transaction.")
      else:
          memberRecord[5] = int(memberRecord[5]) - numbPoints
          print('New points balance:', memberRecord[5]) 

    return_to_menu()
##endfunction##
                      

def display_scheme_status(): 
##Displays scheme status.##
    print("\n____________Cygnet Hotel Group Loyalty Scheme___________\n")
    print("\n6. Display scheme status")
    print('_' * 33,'\n')

    totalSilver = 0
    totalGold = 0
    totalPlatinum = 0
    highestPointsBalance = 0
    memberHPB = ''
    loyaltyScheme.sort()
    print('{0:12s}\t{1:14s}\t{2:12s}\t{3:15s}\t{4:10s}\t{5:12s}'.format('MemberID', 'Surname', 'Joined','Status',  "Nights", 'Points'))
    for record in loyaltyScheme:
        if record[3] == 'Silver':
                totalSilver += 1
        elif record[3] == 'Gold':
                totalGold += 1
        else:
                totalPlatinum += 1
        if record[5] > highestPointsBalance:
                highestPointsBalance = record[5]
                memberHPB = record[0]
        print('{0:12s}\t{1:14s}\t{2:12s}\t{3:15s}\t{4:<10d}\t{5:<12d}'.format(record[0], record[1], record[2], record[3], record[4], record[5]))
    print('\nNumber of members in each membership category:')
    print('Silver:', totalSilver)
    print('Gold:', totalGold)
    print('Platinum:', totalPlatinum)
    print('\nThe member with the highest points balance is:', memberHPB)

    return_to_menu()
##endfunction##


def quit_program():
##Saves file and exits the program.##
    updatedFile = open("latestSchemeData.txt", "w")
    #Converts each record to CSV string and writes to file.
    for record in loyaltyScheme:
            str_data = ','.join(str(item) for item in record)
            str_data = str_data + "\n"
            updatedFile.write(str_data)
    updatedFile.close() 
    print("Goodbye")
##endfunction##                      

###MAIN PROGRAM###
import datetime
nextNumber = 800 #Keeps track of the next number to be used for a new member ID. Is incremented by 1 each time the function add_new_member() is executed.
loyaltyScheme = get_data()
menu()


