/*
* 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;
}