/*
   Tamot --- Task Modelling Editor
   Copyright (C) 2000 Commonwealth Scientific and Industrial Research Organisation
   (CSIRO), Australia. All rights reserved. 

   The Software, owned by CSIRO Australia, has been developed by the CSIRO 
   Intelligent Interactive Technology group. 
   For more information, please see http://www.cmis.csiro.au/iit/.

   The Software is a beta-test version for internal research and evaluation purposes 
   by the Licensee. The Software is still at a development stage. 
   It has not undergone complete testing and may have inherent errors,
   bugs or deficiencies that can affect the operation of the Software. 

   We encourage your feedback and suggestions. Any bugs / suggestions found please email to
   Shijian.Lu@cmis.csiro.au and Thomas.Lo@cmis.csiro.au. 

   After you have signed the Beta-Test Software License Agreement with the CSIRO,
   CSIRO grants you a non-exclusive, non-transferable license to use it only for your 
   personal, non-commercial and lawful end use. Implied licenses are negated. 

   Warranty Disclaimer : 

   CSIRO supplies the Software on an "as is" basis and makes no warranties that use of
   the Software by the Licensee will not infringe any third party’s 
   Intellectual Property Rights nor that the Software will be of merchantable quality,
   or suitable for a particular purpose. CSIRO excludes all terms, conditions and
   warranties implied by custom, the general law or statute in relation to the
   Software.
*/

package taskModellingTool;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.io.*;
import java.awt.geom.Area;

public abstract class GenericComponent extends JComponent implements Externalizable{    

    // number of pixels per unit
    // it is used to change the scale
    // it is the same for all the tasks
    protected static final double u0=20;
    protected static double u=u0;
    
    public static final int undefined = -1;

    //Attribute - task name
    public String name;
    
    //Thomas ?V5
    public int ID = undefined;
    
    /**
     * Property - task selected or not
     */
    protected boolean selected = false;

    // Shift selected or not for multiple component selection in the same window
    protected boolean shiftSelected = false;
    
    //protected boolean tmpOnScreen = false;

    /**
     * Property - task area
     */
    protected Area area;
    
    // constants
    protected static final Boolean
        bT=new Boolean(true),
        bF=new Boolean(false);

    public static final String TAB = String.valueOf((char) 9);

    public int pngX1 = undefined;
    public int pngY1 = undefined;
    public int pngX2 = undefined;
    public int pngY2 = undefined;

    
    //protected Object [][] attributesToDisplay;
                
    public GenericComponent(String name){    		
    	setLayout(null);
    	setUI(new SpecialShapeComponentUI());
    	this.name=findName(name);   	    		
    	
    	//Thomas ?V5
    	//setID();
    }

    //Thomas ?V5
    public void setID() {
    	ID = Manager.currentUnusedID;
    	Manager.currentUnusedID = Manager.currentUnusedID+1;
    	
    	//System.out.println("*** Creating GenericComponent : name = "+name+"; ID = "+ID);
	}
    
    public GenericComponent(String name,int index){    		
    	setLayout(null);
    	setUI(new SpecialShapeComponentUI());
    	this.name=(index==-1)?(findName(name)):(findName(name,index));   	    		
    	
    	//Thomas ?V5
    	//setID();
    }
    
    // get an unused index of the task name, ss
    public static int getIndex(String ss) {
    	String s=ss;
    	int i=-1;
    	if (Manager.skeleton.isInTree(s)) {
    	    for (i=0;Manager.skeleton.isInTree(s+i);i++);
    	    s=s+i;
    	}
        return i;
    }    
   	
    // find an unique task name
    public static String findName(String ss) {
    	String s = ss;
    	int index = 0;
        
    	if (s.equals("Task")) {
            if (Manager.skeleton.isInTree(s+" "+index)) {
                int i;
                for (i=0;Manager.skeleton.isInTree(s+" "+i);i++);
                s=s+" "+i;
            }
            else
                s=s+" "+index;
    	} else {
            if (Manager.skeleton.isInTree(s)) {
                int i;
                for (i=0;Manager.skeleton.isInTree(s+i);i++);
                s=s+i;
            }
    	}
        
        return s;
    }    
    	
    // find an unique task name from the given index onwards
    public static String findName(String ss,int index) {
    	String s = ss;
        
    	if (s.equals("Task")) {
            if (Manager.skeleton.isInTree(s+" "+index)) {
                int i;
                for (i=index+1;Manager.skeleton.isInTree(s+" "+i);i++);
                s=s+" "+i;
            } 
            else
                s=s+" "+index;
    	} else {
            if (Manager.skeleton.isInTree(s+index)) {
                int i;
                for (i=index+1;Manager.skeleton.isInTree(s+i);i++);
                s=s+i;
            }
            else
                s=s+index;
		}
    
        return s;
    }    
    	
    
    //--------------------------- IO ------------------------------/
    //used in the object reconstruction
    public GenericComponent() {
    	setLayout(null);
    	setUI(new SpecialShapeComponentUI()); 
    	
    	//Thomas ?V5
    	//setID();
    }
    
    public void displayInfo() {
        /*System.out.println("displayInfo : name = "+name+", ID = "+ID+", selected = "+selected+
            ", tmpOnScreen = "+tmpOnScreen);*/
        System.out.println("displayInfo : name = "+name+", ID = "+ID+", selected = "+selected);
    }
    
    // save task name, dimension of object
    public void writeExternal(ObjectOutput out) throws IOException{
    	out.writeObject(name);
    	//out.writeObject(attributesToDisplay);
    	out.writeObject(getBounds());
    }
    
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException{
    	name=(String)in.readObject();
    	//attributesToDisplay=(Object [] [])in.readObject();
    	setBounds((Rectangle)in.readObject());    	
    }
    
    public String getTABs(int numOfTABs) {
        StringBuffer result = new StringBuffer();
        
        for (int i=0; i<numOfTABs; i++) {
            result.append(TAB);
        }
        
        return result.toString();
    }
    
    public abstract void writeASCII(PrintStream o);
    
    public abstract void readASCII(BufferedReader i);
    
        
    public void setArea(Area a){
    	area=a;
    }
    
    public Area getArea() {
    	return area;
    }
    
    public void setSelected(boolean b) {
    	selected=b;
    }
   
    public boolean isSelected() {
    	return selected;
    }
    
    public void setShiftSelected(boolean b) {
        shiftSelected = b;
    }
   
    public boolean isShiftSelected() {
        return shiftSelected;
    }
    
    public abstract Object [][] getAttributesToDisplay();
    
    public abstract void setAttributesToDisplay(Object [][] o);
    
    public abstract boolean [] getUserAttributes();
    
    public abstract void setUserAttributes(boolean[] o);
    
    public abstract Object [] getDialogsFields();
    
    public abstract void setDialogsFields(Object [] o);
    
    public abstract Object [] getCloneFields();
    
    public abstract void setCloneFields(Object [] o);
    
    public void paintComponent(Graphics g){
    	super.paintComponent(g);
    	Graphics2D g2 = (Graphics2D)g;
        if (DisplayManager.antiAliasing) g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        else g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
        
        if (DisplayManager.quality) g2.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
    	else g2.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_SPEED);
    	
        if (DisplayManager.dithering) g2.setRenderingHint(RenderingHints.KEY_DITHERING,RenderingHints.VALUE_DITHER_ENABLE);
        else g2.setRenderingHint(RenderingHints.KEY_DITHERING,RenderingHints.VALUE_DITHER_DISABLE);

    	drawComponent(g2);
        
        //tmpOnScreen = true;
    }


    /**
     * Part to implement
     */
    protected abstract void drawComponent(Graphics2D g2);
                
    
    /**
     * Returns true if the current component's interior has a not null intersection with gc's interior
     */
    public abstract boolean intersection(GenericComponent gc);
    
    public String getName(){
    	return name;
    }
    
    public void setName(String s){
    	name=s;
    }

}