"""Simulate a snack vending machine"""
# MCS 260 Fall 2020 Project 2 Solution
# Emily Dumas

# Note: This solution was designed to use things we learned 
# in lecture before or very shortly after the project was
# assigned.  With the benefit of more recent material, some
# things could be done in slightly more efficient ways.

import sys

coin_values = { 
    "quarter": 25,
    "dime": 10,
    "nickel": 5
}

def dispense_change(cents):
    """print lines to simulate return of `cents` cents"""
    while cents >= 25:
        print("RETURN: quarter")
        cents = cents - 25
    while cents >= 10:
        print("RETURN: dime")
        cents = cents - 10
    while cents >= 5:
        print("RETURN: nickel")
        cents = cents - 5
    # We are told the prices will be multiples of 5 cents
    # and so cents should equal 0 now.

def show_inventory(inventory):
    """Display the `inventory` (list of dicts) in the format required by 
    the project description
    """
    for idx,itemdata in enumerate(inventory):
        print(idx,itemdata["name"],
              "${:.2f} ({} available)".format(itemdata["price"]/100,
                                              itemdata["stock"]))
        # Note: Could also handle this as a single format string
        # instead of multiple arguments to print()

def vend(inventory):
    """Run the vending machine simulator with a given `inventory`."""    

    # Determine the maximum price of an item
    maxprice=0
    for d in inventory:
        if d["price"] > maxprice:
            maxprice = d["price"]
    
    # Command loop
    credit=0
    while True:
        print("CREDIT: ${:.2f}".format(credit/100))
        cmd = input(">")

        if cmd in ["quarter","dime","nickel"]:
            # Coin inserted
            if credit >= maxprice:
                print("RETURN:",cmd)
            else:
                credit = credit + coin_values[cmd]
        elif cmd in ["0", "1","2","3","4","5"]:
            # Snack purchase request
            i = int(cmd)  # 0-based index
            if inventory[i]["stock"] == 0:
                print("MSG: Out of stock")
            elif credit < inventory[i]["price"]:
                print("MSG: Insufficient credit")
            else:
                inventory[i]["stock"] = inventory[i]["stock"] - 1
                print("VEND:",inventory[i]["name"])
                dispense_change(credit - inventory[i]["price"])
                credit = 0
        elif cmd == "inventory":
            # Request to display inventory
            show_inventory(inventory)
        elif cmd == "return":
            # Return current credit
            dispense_change(credit)
            credit = 0
        elif cmd[:7] == "restock":
            # Restock an item; takes parameters `index` and `amount`

            # NOTE: we don't check that "restock" is immediately
            # followed by a space, so commands like "restocking 2 3"
            # will also work.  If proper error handling were expected,
            # we would want to revise this.
            fields = cmd.split()
            idx = int(fields[1])
            amt = int(fields[2])
            inventory[idx]["stock"] = inventory[idx]["stock"] + amt
        elif cmd == "exit":
            # exit the simulation
            return
        else:
            # Unknown command

            # NOTE: There was no requirement to handle this situation
            # in the project description.
            print("Unknown command: {}".format(cmd))

def read_inventory(fn):
    """Load inventory data from text file `fn`, in the format of 6 
    lines of comma-separated values
        stock,price,name
    Return a list of dicts with keys "stock", "price", "name".
    """
    L = []
    f = open(fn,"r")
    for line in f:
        fields = line.strip().split(',') # Split along commas to get string "fields"
        d = dict() # will store data on this item
        d["stock"] = int(fields[0])  # Field 0 is an int, the initial stock
        d["price"] = int(fields[1])  # Field 1 is an int, the price in cents
        d["name"] = fields[2]        # Field 2 is a string, the name
        L.append(d)
    return L

# The inventory filename is given as the first command line argument
# after the script name Read the inventory from this file and immediately
# start the simulation.

vend(read_inventory(sys.argv[1]))
