package classes;

import java.awt.Color;
import java.util.ArrayList;

/**
 * The abstract class "CpsObject" represents any possible object in the system
 * (except Edges). The representation of any object contains following
 * variables: see description of variables
 * 
 * @author Gruppe14
 *
 */
public abstract class AbstractCpsObject {
	/* Type of the Object. */
	String objName;
	/* Name given by the user. */
	String name;
	/* ID of the Obj. */
	int id;
	/* Path of the image for the Obj. */
	String image;
	/* Array of neighbors */
	ArrayList<CpsEdge> connections;
	/* Position with a X and Y value */
	Position position;
	/*
	 * Energy input and output of each object in the grid Where the Object is
	 * Stored
	 */
	String sav;
	/* borderColor the user sets */
	Color borderColor = Color.WHITE;
	/* a Tag that can be used */
	ArrayList<Integer> tags;
	/* a Tag that can be used */
	ArrayList<Integer> pseudoTags;
	
	/**
	 * Constructor for a CpsObejct with an unique ID.
	 * 
	 * @param objName
	 *            of the Object
	 */
	public AbstractCpsObject(String objName) {
		setObjName(objName);
		setName(objName);
		setImage("/Images/Dummy_House.png");
		tags = new ArrayList<Integer>();
		pseudoTags = new ArrayList<Integer>();
	}

	/**
	 * Constructor for a new CpsObject with an unique ID (This constructor
	 * correspond to the interaction between the Categories and Canvas)-->
	 * actually the "new" Object is a copy.
	 * 
	 * @param obj
	 *            Object to be copied
	 */
	public AbstractCpsObject(AbstractCpsObject obj) {
		setObjName(obj.getObjName());
		setName(obj.getObjName());
		setConnections(new ArrayList<CpsEdge>());
		setPosition(new Position());
		setID(IdCounter.nextId());
		setImage(obj.getImage());
	}

	/**
	 * Getter for the type of the Object.
	 * 
	 * @return String
	 */
	public String getObjName() {
		return objName;
	}

	/**
	 * Set the type of Object.
	 * 
	 * @param objName
	 *            String
	 */
	public void setObjName(String objName) {
		this.objName = objName;
	}

	/**
	 * Getter for the user-defined name (no unique).
	 * 
	 * @return String
	 */
	public String getName() {
		return name;
	}

	/**
	 * Set the name.
	 * 
	 * @param name
	 *            String
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * Getter of the unique ID.
	 * 
	 * @return int
	 */
	public int getID() {
		return id;
	}

	/**
	 * Set the ID to a new one.
	 * 
	 * @param id
	 *            the iD to set
	 */
	public void setID(int id) {
		this.id = id;
	}

	/**
	 * Get the path of the image for the selected Object.
	 * 
	 * @return String
	 */
	public String getImage() {
		return image;
	}

	/**
	 * Set the path of the image.
	 * 
	 * @param image
	 *            the Image to set
	 */
	public void setImage(String image) {
		this.image = image;
	}

	/**
	 * List of all existing connections.
	 * 
	 * @return the connections ArrayList
	 */
	public ArrayList<CpsEdge> getConnections() {
		return connections;
	}

	/**
	 * Set a new ArrayList of connections (Update).
	 * 
	 * @param arrayList
	 *            the connections to set
	 */
	public void setConnections(ArrayList<CpsEdge> arrayList) {
		this.connections = arrayList;
	}

	/**
	 * List of all existing connections.
	 * 
	 * @return the connections ArrayList
	 */
	public ArrayList<CpsEdge> getConnectedTo() {
		return connections;
	}

	/**
	 * Add a new connection to the selected Object.
	 * 
	 * @param toConnect
	 *            Edge
	 */
	public void addConnection(CpsEdge toConnect) {
		connections.add(toConnect);
	}

	/**
	 * Set the position of the Object in the canvas.
	 * 
	 * @param pos
	 *            Coordinates
	 */
	public void setPosition(Position pos) {
		this.position = pos;
	}

	/**
	 * Set the position of the Object in the canvas.
	 * 
	 * @param x
	 *            X-Coord
	 * @param y
	 *            Y-Coord
	 */
	public void setPosition(int x, int y) {
		setPosition(new Position(x, y));
	}

	/**
	 * Get the actual position of the Object.
	 * 
	 * @return Position Position of this Object
	 */
	public Position getPosition() {
		return position;
	}

	/**
	 * For save purpose.
	 * 
	 * @return the stored
	 */
	public String getSav() {
		return sav;
	}

	/**
	 * For save purpose.
	 * 
	 * @param sav
	 *            the stored to set
	 */
	public void setSav(String sav) {
		this.sav = sav;
	}

	/**
	 * Get the color of the border.
	 * 
	 * @return the BorderColor
	 */
	public Color getBorderColor() {
		return borderColor;
	}

	/**
	 * Set the Border Color of this CpsObject.
	 * 
	 * @param c
	 *          the BorderColor
	 */
	public void setBorderColor(Color c) {
		this.borderColor = c;
	}

	/**
	 * For internal purpose (energy flow).
	 * 
	 * @param tag
	 *            for internal purpose
	 */
	public void addTag(int tag) {
		if(!(tags.contains(tag))){
			this.tags.add(tag);
		}
	}
	
	public void addAllTags(ArrayList<Integer> tags){
		for(Integer tag: tags){
			addTag(tag);
		}
	}

	/**
	 * Get the actual tags.
	 * 
	 * @return ArrayList
	 */
	public ArrayList<Integer> getTag() {
		return tags;
	}

	/**
	 * Rest the tags to Null.
	 */
	public void resetTags() {
		this.tags = new ArrayList<Integer>();
		this.pseudoTags = new ArrayList<Integer>();
	}

	/**
	 * For internal purpose (energy flow).
	 * 
	 * @param tags
	 *            for internal purpose
	 */
	public void setTags(ArrayList<Integer> tags) {
		this.tags = tags;
	}

	/**
	 * For internal purpose (energy flow).
	 * 
	 * @param tags
	 *            for internal purpose
	 */
	public void setPseudoTags(ArrayList<Integer> tags) {
		this.pseudoTags= tags;
	}
	
	/**
	 * Get the pseudo tags.
	 * 
	 * @return ArrayList
	 */
	public ArrayList<Integer> getPseudoTags() {
		return this.pseudoTags;
	}
	
	/**
	 * add a pseudo tag.
	 * 
	 * @return ArrayList
	 */
	public void addPseudoTag(int tag) {
		if(!pseudoTags.contains(tag)){
			pseudoTags.add(tag);
		}
	}
	
	/**
	 * adds all given pseudotags to the tags
	 * @param pseudoTags
	 */
	public void addAllPseudoTags(ArrayList<Integer> pseudoTags){
		for(Integer tag: pseudoTags){
			addPseudoTag(tag);
		}
	}
	
	/**
	 * adds All pseudoTags to tags without duplicates
	 */
	public void recalculateTags(){
		for(Integer tag: pseudoTags){
			if(!tags.contains(tag)){
				tags.add(tag);
			}
		}
	}
	
}
