/*
 * File: AdvRoom.java
 * ------------------
 * This file defines a class that models a single room in the
 * Adventure game.
 */

import acm.util.*; 
import java.io.*;
import java.util.*;

/* Class: AdvRoom */
/**
 * This class defines a single room in the Adventure game.  A room is
 * characterized by the following properties:
 *
 * <ul>
 * <li>A room number, which must be greater than zero
 * <li>Its name, which is a one-line string identifying the room
 * <li>Its description, which is a multiline array describing the room
 * <li>A list of objects contained in the room
 * <li>A flag indicating whether the room has been visited
 * <li>A motion table specifying the exits and where they lead
 * </li>
 *
 * The external format of the room data file is described in the
 * assignment handout.  The comments on the methods exported by
 * this class show how to use the initialized data structure.
 */

public class AdvRoom {

/* Method: getRoomNumber() */
/**
 * Returns the room number.
 *
 * @usage int roomNumber = room.getRoomNumber();
 * @return The room number
 */
	public int getRoomNumber() {
		return roomNumber;
	}

/* Method: getName() */
/**
 * Returns the room name, which is its one-line description.
 *
 * @usage String name = room.getName();
 * @return The room name
 */
	public String getName() {
		return shortDescription;
	}


/* Method: getDescription() */
/**
 * Returns an array of strings that correspond to the long description
 * of the room.
 *
 * @usage String[] description = room.getDescription();
 * @return An array of strings giving the long description of the room
 */
	public String[] getDescription() {
		return longDescriptionArray; 
	}


	/* Method: addObject(obj) */
	/**
	 * Adds an object to the list of objects in the room.
	 *
	 * @usage room.addObject(obj);
	 * @param The AdvObject to be added
	 */
		public void addObject(AdvObject obj) {
			objects.add(obj);
		}

	/* Method: removeObject(obj) */
	/**
	 * Removes an object from the list of objects in the room.
	 *
	 * @usage room.removeObject(obj);
	 * @param The AdvObject to be removed
	 */
		public void removeObject(AdvObject obj) {
			objects.remove(obj);
		}

	/* Method: containsObject(obj) */
	/**
	 * Checks whether the specified object is in the room.
	 *
	 * @usage if (room.containsObject(obj)) . . .
	 * @param The AdvObject being tested
	 * @return true if the object is in the room, and false otherwise
	 */
		public boolean containsObject(AdvObject obj) {
			if (objects.contains(obj)) {
				return true;
			} else {
				return false;
			}
		}

	/* Method: getObjectCount() */
	/**
	 * Returns the number of objects in the room.
	 *
	 * @usage int nObjects = room.getObjectCount();
	 * @return The number of objects in the room
	 */
		public int getObjectCount() {
			return objects.size();
		}

	/* Method: getObject(index) */
	/**
	 * Returns the specified element from the list of objects in the room.
	 *
	 * @usage AdvObject obj = room.getObject(index);
	 * @return The AdvObject at the specified index position
	 */
		public AdvObject getObject(int index) {
			return (AdvObject) objects.get(index);
		}

/* Method: setVisited(flag) */
/**
 * Sets the flag indicating that this room has been visited according
 * to the value of the parameter.  Calling setVisited(true) means
 * that the room has been visited; calling setVisited(false) restores
 * its initial unvisited state.
 *
 * @usage room.setVisited(flag);
 * @param flag The new state of the "visited" flag
 */
	public void setVisited(boolean flag) {
		visitedFlag = flag;
	}
	
/* Method: hasBeenVisited() */
/**
 * Returns true if the room has previously been visited.
 *
 * @usage if (room.hasBeenVisited()) . . .
 * @return true if the room has been visited; false otherwise
 */
	public boolean hasBeenVisited() {
		return visitedFlag;
	}


/* Method: getMotionTable() */
/**
 * Returns the motion table associated with this room, which is an
 * array of directions, room numbers, and enabling objects stored
 * in a AdvMotionTableEntry.
 *
 * @usage AdvMotionTableEntry[] motionTable = room.getMotionTable();
 * @return The array of motion table entries associated with this room
 */
	public AdvMotionTableEntry[] getMotionTable() {
		return MotionTables;
	}

/* Method: readFromFile(rd) */
/**
 * Reads the data for this room from the BufferedReader rd, which
 * must have been opened by the caller.  This method returns true
 * if the room initialization is successful; if there are no more
 * rooms to read, readFromFile returns false without initializing
 * the current room. 
 *
 * @usage boolean ok = room.readFromFile(rd);
 * @param rd A bufferedReader open on the rooms data file
 * @return true if a room is successfully read; false at end of file
 */
	public boolean readFromFile(BufferedReader rd) {
		try { 
			String line; 
			while (true) { 
				line = rd.readLine(); 
				if (line == null) return false; 
				if (line.length() > 0) break; 
			} 
			roomNumber = Integer.parseInt(line); 
			shortDescription = "";
			while (true) {
				line = rd.readLine();
				if (line == null) return false; 
				if (line.length() > 0) break; 
			}
			shortDescription += line; 
			ArrayList longDescription = new ArrayList(); 
			while (true) { 
				line = rd.readLine(); 
				if (line.equals(MARKER)) break; 
				longDescription.add(line); 
			}
			transferToArray(longDescription);
			while(true){
				line = rd.readLine();
				if (line == null) break; 
				if (line.length() == 0) break;
				readExits(line);
			}
			MotionTables = new AdvMotionTableEntry[MotionArrayList.size()];
			for (int i = 0; i < MotionArrayList.size(); i++){
				MotionTables[i] = (AdvMotionTableEntry) MotionArrayList.get(i);
			}
			return true; 
		} catch (IOException ex) { 
			throw new ErrorException(ex); 
		} catch (NumberFormatException ex) { 
			throw new ErrorException("Illegal question number"); 
		} 
	}
// Seperates the direction of travel, the number of the destination room, and the
// key item (if any), and adds them to the MotionArrayList as a AdvMotionTableEntry.
	private void readExits(String line) {
		int space = line.indexOf(" ");
		String direction = line.substring(0, space);
		int slash = line.indexOf("/");
		int destinationRoom;
		String key = null;
		if (slash == -1) {
			destinationRoom = Integer.parseInt(line.substring(space).trim());
		} else {
			destinationRoom = Integer.parseInt(line.substring(space, slash).trim());
			key = line.substring(slash+1);
		}
		singleTable = new AdvMotionTableEntry(direction, destinationRoom, key);
		MotionArrayList.add(singleTable);
	}
// Turns an array into an ArrayList
	private void transferToArray(ArrayList longdescript) {
		longDescriptionArray = new String[longdescript.size()];
		for(int i = 0; i < longdescript.size(); i++){
			longDescriptionArray[i] = (String) longdescript.get(i);
		}
	}


/* Private instance variables */
	private String MARKER = "-----"; 
	private boolean visitedFlag;
	private int roomNumber;
	private ArrayList objects = new ArrayList();
	private AdvMotionTableEntry singleTable;
	private ArrayList MotionArrayList = new ArrayList();
	private AdvMotionTableEntry[] MotionTables;
	private String[] longDescriptionArray;
	private BufferedReader rd;
	private String shortDescription;
}


