//****************************************************************************
// CLASS NAME:	Place.java
//
// AUTHOR:	Rick Brink
//		rick@mail.csh.rit.edu
//		http://www.csh.rit.edu/~rick
//
// VERSION:	1.0
//
// HISTORY:	4/16/96		Initial Version
//
// COPYRIGHT INFORMATION:
//
// This program and the Java source is in the public domain.
// Permission to use, copy, modify, and distribute this software
// and its documentation for NON-COMMERCIAL purposes and
// without fee is hereby granted.
//
//    Copyright 1996
//
//    Rick Brink
//    1266 Brighton-Henrietta Townline Rd.
//    Rochester, NY 14623
//
// DISCLAIMER:
//
// The author claims no responsibility for any damage, direct or indirect,
// to any harware or software as a result of using this program.
//****************************************************************************

import java.io.PrintStream;
import java.util.StringTokenizer;
import java.util.Vector;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Font;

/**
  * A class representing a Place in a Petri Net diagram.
  *
  * @see PetriComponent
  * @see java.awt.Font
  * @see java.awt.Graphics
  * @see java.awt.Color
  * @see java.io.PrintStream
  * @see java.util.StringTokenizer
  * @see java.util.Vector
  *
  * @version 1.0 July 3, 1996
  *
  * @author  Rick Brink
**/
class Place extends PetriComponent {

    /** Unique numeric label for each Place object **/
    private protected int label_ = 0;

    /** Pointer to a Token which may be contained by this Place **/
    protected Token token_;

    /** Indicates if token_ is a valid Token object **/
    protected boolean tokenInitialized_ = false;

    /**
      * Construct a new Place, with coordinates of
      * (x,y) which are the absolute coordinates divided by
      * gridStep_.  Also note, all coordinates represent the
      * upper left hand corner of a grid square.  A unique
      * numeric identifier should also be passed into the constructor.
    **/
    public Place (int x, int y, int label) {
        xCoordinate_ = x;
        yCoordinate_ = y;
        label_ = label;
    }

    /**
      * Construct a new Place without specifying any parameters.
    **/
    public Place () {
    }

    /**
      * Create a copy of the current Place Object
    **/
    public Object clone() {
        Place p = new Place(xCoordinate_, yCoordinate_, label_);
        p.tokenInitialized_ = tokenInitialized_;
        p.token_ = token_;
        return p;
    }

    /**
      * Set the unique numeric label for this Place
    **/
    public void setLabel(int label) {
        label_ = label;
    }

    /**
      * Get numeric label for this Place
    **/
    public int getLabel() {
        return(label_);;
    }

    /**
      * Initializes the token_ object that this Place holds a pointer
      * to.
    **/
    public void setToken (Token token) {
        token_ = token;
        if (token != null) {
            tokenInitialized_ = true;
        }
        else {
            tokenInitialized_ = false;
        }
    }

    /**
      * Returns the number of Tokens the token_ object of this
      * Place currently represents, else 0 if the token_ Object
      * of this Place is not yet initialized.
    **/
    public int getNumTokens() {
        if (tokenInitialized_) {
            return (token_.getTokensRepresented());
        }
        else {
            return (0);
        }
    }

    /**
      * Add to the number of Tokens that this Place currently
      * holds.  If it currently holds none, a new Token object is
      * created with numTokens as the number of tokens the Token
      * object represents, and this is added to tokenVector.
      * Note also that this method can be used to
      * delete from the number of Token by sending a negative value
      * in for numTokens.  If this is the case, and all Tokens are
      * removed, then the Token object is removed from tokenVector.
    **/
    public void addTokens(int numTokens, Vector tokenVector,
                          int maxCapacity) {
        if (tokenInitialized_) {
            int numTokens__ = token_.getTokensRepresented() + numTokens;
            numTokens__ = Math.min(maxCapacity, numTokens__);
            token_.setTokensRepresented(numTokens__);

            // if numTokens is actually a negative number, as in
            // reverse steps, we could be removing all the tokens
            // in this place, so set the appropriate values and
            // remove the Token from tokenVector
            if (numTokens__ == 0) {
                tokenInitialized_ = false;
                for (int i__ = 0; i__ < tokenVector.size(); i__++) {
                    Token token__ = (Token)tokenVector.elementAt(i__);
                    if ((token__.getXCoordinate() == xCoordinate_) &&
                       (token__.getYCoordinate() == yCoordinate_)) {
                        tokenVector.removeElementAt(i__);
                        token_ = null;
                    }
                }
            }
        }
        else {
            numTokens = Math.min(maxCapacity, numTokens);
            Token newToken__ = new Token(xCoordinate_, yCoordinate_,
                numTokens);
            token_ = newToken__;
            tokenInitialized_ = true;
            tokenVector.addElement(newToken__);
        }
    }

    /**
      * Draw the Place to the screen.
    **/
    public void draw(Graphics g, int gridStep, Color placeColor,
                     boolean displayLabel) {
        g.setColor(placeColor);
        g.drawOval(xCoordinate_ * gridStep, yCoordinate_ * gridStep,
                   gridStep,gridStep);
        if (selected_) {
            int x__ = xCoordinate_ * gridStep;
            int y__ = yCoordinate_ * gridStep;
            g.setColor(Color.green);
            g.fillRect(x__ - 2, y__ - 2, SELECT_SIZE, SELECT_SIZE);
            g.fillRect(x__ + gridStep - 2, y__ - 2, SELECT_SIZE, SELECT_SIZE);
            g.fillRect(x__ - 2, y__ + gridStep - 2, SELECT_SIZE, SELECT_SIZE);
            g.fillRect(x__ + gridStep - 2, y__ + gridStep - 2, SELECT_SIZE, SELECT_SIZE);
        }
        if (displayLabel) {
            g.setColor(Color.red);
            Font labelFont__ = new Font("Dialog", Font.PLAIN, 12);
            g.setFont(labelFont__);
            g.drawString("P" + label_, xCoordinate_ * gridStep,
                         yCoordinate_ * gridStep);
        }

    }

    /**
      * Save the necessary Place information to a PrintStream
    **/
    public void saveToFile(PrintStream printStream) {
        printStream.println("Place: " + xCoordinate_ + "," +
                            yCoordinate_ + "," + label_);
    }

    /**
      * Given a StringTokenizer, set the Place values.  Useful
      * for restoring a Place from a file.
    **/
    public void loadFromFile(StringTokenizer tokenizer) {
        xCoordinate_ = Integer.parseInt(tokenizer.nextToken());
        yCoordinate_ = Integer.parseInt(tokenizer.nextToken());
        label_ = Integer.parseInt(tokenizer.nextToken());
        return;
    }

}