import java.util.Scanner;


/*Since Inventory is a real-world entity, here (unlike on the exam) it makes
 sense to make it instantiable, and instantiate it in the main method. */
public class Inventory {
 
    private static Scanner in = new Scanner(System.in);
  
    private SaleItem [] itemsInStore;
    private ShippedItem [] itemsShipped;
    private int numItemsShipped, numItemsInStore;
    public Inventory() {
	numItemsShipped = numItemsInStore = 0;
    }

    public void addItems(int numFurniture, int numClothing) {

	itemsInStore = new SaleItem[numFurniture+numClothing];
	
	//"randomly" distribute clothing and furniture to simulate real conditions
	//i.e., various objects arrive on a daily basis
	//Yes, this is a slightly esoteric loop..
	for(int f=0, c=0; (f+c) < (numFurniture + numClothing) ; ) {

	    if( (f+c)%3 ==0 ) {
		itemsInStore[f+c] = new Clothing(f+c, 15.0, 3);
		++c; //added clothing
	    }
	    else {
		itemsInStore[f+c] = new Furniture(f+c, 100.0, 40, 2, 4);
		++f;
	    }
	}//for

	numItemsInStore = numFurniture+numClothing;
	itemsShipped = new ShippedItem[numItemsInStore]; //maximum
    }


    //helper method: gets the sum of all items currently sold
    //illustrates polymorphism (getPrice() method) 
    public double getInventoryWorth() {
	double result = 0;
	for(int i=0; i<itemsInStore.length; ++i) {
	    result += itemsInStore[i].getPrice();
	}
	return result;
    }

    /*helper method: checked which items in itemsSold have been shipped
    //Recall: only Furniture can be shipped, and only some of the furniture has been sold
    //[see Furniture.java].  However, this method is general for any shipped item


    //Postcondition: method copies the references (shallow copy) to itemsShipped.
    // i.e., itemsShipped holds (references to) all items that have been sold and shipped.
    */

    //illustrates instanceof and casting. 
    public void updateShippedItems() {
	numItemsShipped = 0;

	for(int i=0; i<itemsInStore.length; ++i) {
	    //check if we've been purchased and that we MIGHT be shipped
	    if(itemsInStore[i] instanceof ShippedItem && itemsInStore[i].purchased() ) {

		//cast to check if we've actually been shipped
		ShippedItem tempItem = (ShippedItem)itemsInStore[i]; //safe operation here
		//now (ONLY after casting) we can check if it's been sold
		//Note: how can this design be improved?
		if(tempItem.shipped()) {
		    //Question: why is the line below safe (won't produce ArrayOutOfBounds).
		    itemsShipped[numItemsShipped] = tempItem; 
		    numItemsShipped++;
		}
	    }
	}
    }

    //Illustrates instanceof/casting to retrieve a single furniture object
    //and manipulate it
    public void purchaseFurniture() {
	Furniture pof = null;  //pof = "piece of furniture"
	//iterate until an unpurchased pof is found
	for(int i=0; i<itemsInStore.length && pof == null; ++i) {
	    if (itemsInStore[i] instanceof Furniture && !itemsInStore[i].purchased() ) {
		pof = (Furniture)itemsInStore[i];
	    }
	}//for
	
	//purchase it
	pof.purchase();
    }


    //prints shipped items
    public void printShippedItems() {
	for(int i=0; i<numItemsShipped; ++i) {
	    System.out.println("Items was shipped, distance = " + itemsShipped[i].getDistance());
	}
    }

    //prints shipped items
    public void printItemsInStore() {
	for(int i=0; i<numItemsInStore; ++i) {
	    System.out.println("Items sold at price = " + itemsInStore[i].getPrice());
	}
    }

    //many abused this on the exam--this is the correct way to re-prompt for an int
    public static int getInt() {
	int retVal;
	String consumer;
	while(!in.hasNextInt()) {
	    consumer = in.nextLine();
	    System.out.println("Must enter an integer: ");
	}
	retVal = in.nextInt();
	return retVal;
    }


    public static void main(String [] args) {
	//0. get the inventory: in this simplified version, user just inputs two numbers, one
	//   for # of furniture items, and the other for # of clothing items.
	
	int numFurniture = 0, numClothing = 0;
	System.out.print("Enter number of furniture items: ");
	numFurniture = getInt();
	System.out.print("Enter number of clothing items: ");
	numClothing = getInt();
		
	//create an inventory, and input all objects
	Inventory myInventory = new Inventory();
	myInventory.addItems(numFurniture, numClothing);
	myInventory.printItemsInStore();


	//Now for the relevant parts...

	//purchase a furniture item that will be shipped to one's home
	myInventory.purchaseFurniture();
	
	
	//2. get the total worth of all items currently sold
	double totalWorth = myInventory.getInventoryWorth();
	System.out.println("Total Inventory Worth: " + totalWorth);
	
	
	//3. get all shipped items
	myInventory.updateShippedItems();
	myInventory.printShippedItems();

	//Note: the ONLY place we had to deal with Furniture and Clothing types here was in the 
	//constructor.  All of the utility methods used Interface types and polymorphism.  

    }//main
}//Inventory
