/*
 * @(#) EventHandler.java  1.10 10/09/02
 *
 * Copyright ***,  All Rights Reserved.
 * 
 * This software is the proprietary information of ********  
 * Use is subject to license terms.
 * 
 */


// import java packages
//
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
import java.io.*;
import java.lang.*;
import javax.swing.border.*;

/**
 * This class is designed to handle all events of the Vertices
 */
public class Vertex extends JButton implements Serializable {

    //-----------------------------------------------------------------
    //
    // static data members
    //
    //-----------------------------------------------------------------

    //-----------------------------------------------------------------
    //
    // instance data members
    //
    //-----------------------------------------------------------------
    
    // symbols in this vertices
    //
    public String name_d = new String();
    public Vector<String> symbols_d = new Vector<String>();

    // symbols in this vertices
    //
    public Vector<GraphArc> out_arcs_d = new Vector<GraphArc>();
    public Vector<GraphArc> in_arcs_d = new Vector<GraphArc>();

    // the relevant information about the vertex
    //
    public String icon_name_d = null;
    public int type_d = CData.NONE_VERTEX;
    public ImageIcon icon_d = null;
    public Point location_d = new Point();
    
    // the parents and children of the vertex
    //
    public Vector<Vertex> children_d = null;
    public Vector<Vertex> parents_d = null;

    // the dimensions of the vertex
    //
    public int width_d = -1;
    public int height_d = -1;

    //-----------------------------------------------------------------
    //
    // static function members
    //
    //-----------------------------------------------------------------

    //-----------------------------------------------------------------
    //
    // instance function members
    //
    //-----------------------------------------------------------------

    /**
     * default class constructor, calls super or JButton constructor
     * 
     */
    public Vertex() {
	super();
    }

    /**
     * adds an incoming arc
     *
     * @param arc_a GraphArc object to be added 
     *
     * @return true
     */
    public boolean addIncomingArc(GraphArc arc_a) {
	in_arcs_d.add(arc_a);
	return true;
    }

    /**
     * removeIncomingArc
     * 
     * @param arc_a GraphArc object to be removed
     * @return true
     */
    public boolean removeIncomingArc(GraphArc arc_a) {
	in_arcs_d.remove(arc_a);
	return true;
    }

    /**
     * adds outgoing arc
     * 
     * @param arc_a GraphArc object to be added
     * @return true
     */
    public boolean addOutcomingArc(GraphArc arc_a) {
	out_arcs_d.add(arc_a);
	return true;
    }

    /**
     * removes outgoing arc
     * 
     * @param arc_a GraphArc object to be removed
     * @return none
     */
    public boolean removeOutcomingArc(GraphArc arc_a) {
	out_arcs_d.remove(arc_a);
	return true;
    }

    /**
     * check errors in the model
     * 
     * @param prefix_a prefix used for the CData error message variable
     * @param msg_a    message appended to the CD error message variable
     *
     * @return true if check is passed, false if otherwise
     */
    public boolean check(String prefix_a, String msg_a) {

	// print message
	//
	CData.error_message_d += prefix_a + msg_a + "\n";

	// no checking for start and term
	//
	if ( isStart() || isTerm()){
	    return true;
	}

	// checking the symbols
	//
	if (symbols_d.size() == 0) {
	    
	    CData.error_message_d += 
		prefix_a + CData.ERR_VERTEX_NO_SYMBOL + "\n";
	    CData.err_flag_d = true;
	    return false;
	}
	return true;
    }

    /**
     * initialize the vertex
     * 
      */
    public void init() {

	// invoke the parent constructor
	//
	if ( type_d == CData.START_VERTEX ){
	    icon_d  = new ImageIcon(CData.START_IMAGE);
	    setIcon(icon_d);
	}
	else if ( type_d == CData.TERM_VERTEX ){
	    icon_d  = new ImageIcon(CData.TERM_IMAGE);
	    setIcon(icon_d);
	}
	else if ( type_d == CData.NODE_VERTEX ){
	    icon_d  = new ImageIcon(CData.NODE_IMAGE);
	    setIcon(icon_d);
	}

	// set the vertex text
	//
	if (name_d.length() > 5) {
	    setText(name_d.substring(0, 5));
	}
	else {
	    setText(name_d);
	}
	
       	// set the font of the vertex
	//
	setFont(CData.ARIAL_FONT);

	// disable the focus from being painted
	//
	setFocusPainted(false);

	// disable the content area from being painted
	//
	setContentAreaFilled(false); 

	// disable the content area from being painted
	//
	setBorder((Border)null); 

	// set the horizontal text position
	//
	setHorizontalTextPosition(SwingConstants.CENTER);

	// init the vertex
	parents_d = new Vector<Vertex>(10, 10);
	children_d = new Vector<Vertex>(10, 10);
	
	// set the default dimensions of the vertex
	//
	setBackground(Color.white);
	setSize(CData.VERTEX_WIDTH, CData.VERTEX_HEIGHT);
	setPreferredSize(new Dimension(CData.VERTEX_WIDTH, 
				       CData.VERTEX_HEIGHT));
	setMinimumSize(new Dimension(CData.VERTEX_WIDTH, 
				     CData.VERTEX_HEIGHT));

	setVertexWidth(CData.VERTEX_WIDTH);
	setVertexHeight(CData.VERTEX_HEIGHT);

	// set the tool tip for the vertex
	//
	setToolTipText(name_d);

	// add the listener
	//
	addMouseListener(CData.event_handler_d);
	addMouseMotionListener(CData.event_handler_d);
    }

    /**
     * copy the vertex
     * 
     * @param vertex_a vertex to be copyied
     */
    public void copyVertex(Vertex vertex_a) {

	// symbols in this vertices
	//
	name_d = new String(vertex_a.name_d);

	// symbols_d = (Vector)vertex_a.symbols_d.clone();
	//
	symbols_d = vertex_a.symbols_d;

	// the relevant information about the vertex
	//
	icon_name_d = vertex_a.icon_name_d;
	type_d = vertex_a.type_d;
	icon_d = vertex_a.icon_d;
	location_d.x = vertex_a.location_d.x;
	location_d.y = vertex_a.location_d.y;
    
	// the parents and children of the vertex
	//
	children_d = vertex_a.children_d;
	parents_d = vertex_a.parents_d;;

	// the dimensions of the vertex
	//
	width_d = vertex_a.width_d;
	height_d = vertex_a.height_d;

    }

    /**
     * copy constructor
     * 
     * @param vertex_a the vertex to be initialized
     */
    public Vertex(Vertex vertex_a) {

	// invoke the parent constructor
	//
	super(vertex_a.icon_d);
	
	// symbols in this vertices
	//
	name_d = new String(vertex_a.name_d);
	
	// symbols_d = (Vector)vertex_a.symbols_d.clone();
	//
	symbols_d = vertex_a.symbols_d;

	// set the vertex text
	//
	if (name_d.length() > 5) {
	    setText(name_d.substring(0, 5));
	}
	else {
	    setText(name_d);
	}
	
	// the relevant information about the vertex
	//
	icon_name_d = vertex_a.icon_name_d;
	type_d = vertex_a.type_d;
	icon_d = vertex_a.icon_d;
	location_d = vertex_a.getLocation();
	setLocation(location_d);
    
	// the parents and children of the vertex
	//
	children_d = vertex_a.children_d;
	parents_d = vertex_a.parents_d;;

	// the dimensions of the vertex
	//
	width_d = vertex_a.width_d;
	height_d = vertex_a.height_d;

       	// set the font of the vertex
	//
	setFont(CData.ARIAL_FONT);

	// disable the focus from being painted
	//
	setFocusPainted(false);

	// disable the content area from being painted
	//
	setContentAreaFilled(false); 

	// disable the content area from being painted
	//
	setBorder((Border)null); 

	// set the horizontal text position
	//
	setHorizontalTextPosition(SwingConstants.CENTER);

	// set the default dimensions of the vertex
	//
	setBackground(Color.white);
	setSize(CData.VERTEX_WIDTH, CData.VERTEX_HEIGHT);
	setPreferredSize(new Dimension(CData.VERTEX_WIDTH, 
				       CData.VERTEX_HEIGHT));
	setMinimumSize(new Dimension(CData.VERTEX_WIDTH, 
				     CData.VERTEX_HEIGHT));

	setVertexWidth(CData.VERTEX_WIDTH);
	setVertexHeight(CData.VERTEX_HEIGHT);

	// set the tool tip for the vertex
	//
	setToolTipText(name_d);

	// add the listener
	//
	addMouseListener(CData.event_handler_d);
	addMouseMotionListener(CData.event_handler_d);

    }

    /**
     * constructor, calls super constructor
     * 
     * @param name_a name string passed to super constructor
     * @param icon_a icon associated with vertex
     * @param type_a integer associated with type
     */
    public Vertex(String name_a, ImageIcon icon_a, int type_a) {

	// invoke the parent constructor
	//
	super(icon_a);
	icon_d = icon_a;
	name_d = name_a;
	type_d = type_a;

	// set the vertex text
	//
	if (name_d.length() > 5) {
	    setText(name_d.substring(0, 5));
	}
	else {
	    setText(name_d);
	}
	
	// init the vertext
	parents_d = new Vector<Vertex>(10, 10);
	children_d = new Vector<Vertex>(10, 10);
	
       	// set the font of the vertex
	//
	setFont(CData.ARIAL_FONT);

	// disable the focus from being painted
	//
	setFocusPainted(false);

	// disable the content area from being painted
	//
	setContentAreaFilled(false); 

	// disable the content area from being painted
	//
	setBorder((Border)null); 

	// set the horizontal text position
	//
	setHorizontalTextPosition(SwingConstants.CENTER);

	// set the default dimensions of the vertex
	//
	setBackground(Color.white);
	setSize(CData.VERTEX_WIDTH, CData.VERTEX_HEIGHT);
	setPreferredSize(new Dimension(CData.VERTEX_WIDTH, 
				       CData.VERTEX_HEIGHT));
	setMinimumSize(new Dimension(CData.VERTEX_WIDTH, 
				     CData.VERTEX_HEIGHT));

	setVertexWidth(CData.VERTEX_WIDTH);
	setVertexHeight(CData.VERTEX_HEIGHT);

	// set the tool tip for the vertex
	//
	setToolTipText(name_d);

	// add the listener
	//
	addMouseListener(CData.event_handler_d);
	addMouseMotionListener(CData.event_handler_d);

    }

    /**
     * checks to see if this is the start vertex 
     * 
     * @return true if type_d is equal to the start vertex
     */
    public boolean isStart () {
	
	return (type_d == CData.START_VERTEX);
    }

    /**
     * checks to see if this is the term vertex 
     * 
     * @return true if type_d is equal to the term vertex
     */
    public boolean isTerm () {
	
	return (type_d == CData.TERM_VERTEX);
    }

    /**
     * checks to see if the point is in this vertex
     * 
     * @param point_a the point to be tested
     * @return true if the point is with the region of the vertex button
     */
    public boolean isSelected ( Point point_a) {
	
	if(point_a.x >= location_d.x 
	   && point_a.x <= location_d.x + width_d 
	   && point_a.y >= location_d.y
	   && point_a.y <= location_d.y + height_d) {
	    // the vertex is selected
	    //
	    return true;
	}
	return false;
    }

    // all get and set methods
    //

    /**
     * gets the vertex location
     * 
     * @return a point to the vertex location
     */
    public Point getVertexLocation() {

	// return the location
	//
	return location_d;
    }

    /**
     * set the vertex location
     * 
     * @param location_a point to set the vertex to
     */
    public void setVertexLocation(Point location_a) {

	// return the location
	//
	location_d.x = location_a.x;
	location_d.y = location_a.y;
    }

    /**
     * get the vertex width
     * 
     * @return the vertex width
     */
    public int getVertexWidth() {

	// return the width
	//
	return width_d;
    }

    /**
     * set the vertex width
     * 
     * @param width_a width to set
     */
    public void setVertexWidth(int width_a) {

	// return the width
	//
	width_d = width_a;
    }

    /**
     * get the vertex height
     * 
     * @return the vertex height
     */
    public int getVertexHeight() {

	// return the height
	//
	return height_d;
    }

    /**
     * set the vertex height
     * 
     * @param height_a height to set
     */
    public void setVertexHeight(int height_a) {

	// return the height
	//
	height_d = height_a;
    }

    /**
     * gets the children of this vertex
     * 
     * @return the vector of children
     */
    public Vector getChildren() {
	return children_d;
    }

    /**
     * get the number of arcs coming into the vertex
     * 
     * @return integer value 1
     */
    public int getInDegree() {
	return 1;
	//return parents_d.size();
    }

    /**
     * get the number of arcs outgoing the vertex
     * 
     * @return number of outgoing arcs
     */
    public int getOutDegree() {
	return children_d.size();
    }

    /**
     * store the vertex, set as the form of properties
     * 
     * @param prefix_a prefix to be used with tags
     */
    public void store(String prefix_a) {

	// get the io to set properties
	//
	Properties io = CData.io_d;
	
	// tags
	//
	String symbol_size_tag = prefix_a + CData.IO_VERTEX_SYMBOL_SIZE;
	String vertex_name_tag = prefix_a + CData.IO_VERTEX_NAME;
	String vertex_type_tag = prefix_a + CData.IO_VERTEX_TYPE;
	String vertex_width_tag = prefix_a + CData.IO_VERTEX_WIDTH;
	String vertex_height_tag = prefix_a + CData.IO_VERTEX_HEIGHT;
	String vertex_loc_x_tag = prefix_a + CData.IO_VERTEX_LOC_X;
	String vertex_loc_y_tag = prefix_a + CData.IO_VERTEX_LOC_Y;

	// values
	//
	String symbol_size = String.valueOf(symbols_d.size());
	String vertex_width = String.valueOf(width_d);
	String vertex_height = String.valueOf(height_d);
	String vertex_loc_x = String.valueOf(getLocation().x);
	String vertex_loc_y = String.valueOf(getLocation().y);
	String vertex_type = String.valueOf(type_d);

	// store all data members
	//
	io.setProperty(vertex_name_tag, name_d);
	io.setProperty(vertex_type_tag, vertex_type);
	io.setProperty(symbol_size_tag, symbol_size);
	io.setProperty(vertex_width_tag, vertex_width);
	io.setProperty(vertex_height_tag, vertex_height);
	io.setProperty(vertex_loc_x_tag, vertex_loc_x);
	io.setProperty(vertex_loc_y_tag, vertex_loc_y);
	
	// write all symbols
	//
	for (int i= 0; i < symbols_d.size(); i++) {
	    String curr_symbol = (String)symbols_d.get(i);
	    String prefix = prefix_a + CData.IO_VERTEX_SYMBOL
		+ String.valueOf(i);
	    io.setProperty(prefix, curr_symbol);
	}
    }

    /**
     * load the data for this vertex from a file
     * 
     * @param prefix_a prefix to be used with tags
     */
    public void load(String prefix_a) {

	// get the io to set properties
	//
	Properties io = CData.io_d;
	
	// tags
	//
	String symbol_size_tag = prefix_a + CData.IO_VERTEX_SYMBOL_SIZE;
	String vertex_name_tag = prefix_a + CData.IO_VERTEX_NAME;
	String vertex_type_tag = prefix_a + CData.IO_VERTEX_TYPE;
	String vertex_width_tag = prefix_a + CData.IO_VERTEX_WIDTH;
	String vertex_height_tag = prefix_a + CData.IO_VERTEX_HEIGHT;
	String vertex_loc_x_tag = prefix_a + CData.IO_VERTEX_LOC_X;
	String vertex_loc_y_tag = prefix_a + CData.IO_VERTEX_LOC_Y;

	// values
	//
	String symbol_size = io.getProperty(symbol_size_tag);
	String vertex_width = io.getProperty(vertex_width_tag);
	String vertex_height = io.getProperty(vertex_height_tag);
	String vertex_loc_x = io.getProperty(vertex_loc_x_tag);
	String vertex_loc_y = io.getProperty(vertex_loc_y_tag);
	String vertex_type = io.getProperty(vertex_type_tag);

	
	// set data members
	//
	name_d = io.getProperty(vertex_name_tag);
	int s_size = Integer.valueOf(symbol_size).intValue();
	width_d = Integer.valueOf(vertex_width).intValue();
	height_d = Integer.valueOf(vertex_height).intValue();
	//Point location = new Point();
	location_d.x = Integer.valueOf(vertex_loc_x).intValue();
	location_d.y = Integer.valueOf(vertex_loc_y).intValue();
	setLocation(location_d);
	type_d = Integer.valueOf(vertex_type).intValue();

	// write load symbols
	//
	for (int i= 0; i < s_size; i++) {
	    String prefix = prefix_a + CData.IO_VERTEX_SYMBOL
		+ String.valueOf(i);
	    String curr_symbol = io.getProperty(prefix);
	    symbols_d.add(curr_symbol);
	}

	// init the vertex
	//
	init();
    }
}

//
// end of file















