package classes;

import java.util.ArrayList;

/**
 * The class "CpsEdge" represents the connections on the GUI. Each connection
 * contains a max. capacity, a flow, a status (isWorking), tags (for internal
 * use of electricity flow), source and destination
 * 
 * @author Gruppe14
 *
 */
public class CpsEdge {

	// Max. capacity of the Edge, if flow is greater than the status --> is
	// Working would be false
	float maxCapacity;
	// Current flow of electricity (through the edge)
	float flow;
	/*
	 * Represents the actual status of the Edge (true = flows electricity; false
	 * = no flow of electricity) State represents the real status of the edge If
	 * it breaks --> stay ruin no matter the actual scenario The only way to
	 * repair it is through manual change (setStateEdge)
	 */
	boolean isWorking;
	// for internal use --> flow of electricity (simulation state)
	ArrayList<Integer> tags;
	// for internal use --> flow of electricity (simulation state)
	ArrayList<Integer> pseudoTags;
	// Source
	AbstractCpsObject a;
	// Destination
	AbstractCpsObject b;

	/**
	 * Constructor without max. capacity (by default as 100)
	 * 
	 * @param a
	 *            Source
	 * @param b
	 *            Destination
	 */
	public CpsEdge(AbstractCpsObject a, AbstractCpsObject b) {
		setA(a);
		setB(b);
		this.a.addConnection(this);
		this.b.addConnection(this);
		this.maxCapacity = 100;
		flow = 0;
		isWorking = true;
		pseudoTags = new ArrayList<Integer>();
	}

	/**
	 * Constructor with a user-defined max. capacity
	 * 
	 * @param a
	 *            Source
	 * @param b
	 *            Destination
	 * @param maxCap
	 *            Maximum Capacity
	 */
	public CpsEdge(AbstractCpsObject a, AbstractCpsObject b, float maxCap) {
		setA(a);
		setB(b);
		this.a.addConnection(this);
		this.b.addConnection(this);
		this.maxCapacity = maxCap;
		flow = 0;
		isWorking = true;
		pseudoTags = new ArrayList<Integer>();
	}

	/**
	 * Getter for the max. capacity
	 * 
	 * @return the capacity
	 */
	public float getCapacity() {
		return maxCapacity;
	}

	/**
	 * Setter for the max. capacity
	 * 
	 * @param cap
	 *            the Capacity to set
	 */
	public void setCapacity(float cap) {
		this.maxCapacity = cap;
	}

	/**
	 * Getter fot the current flow.
	 * 
	 * @return the flow
	 */
	public float getFlow() {
		return flow;
	}

	/**
	 * Set the flow into a new one.
	 * 
	 * @param flow
	 *            the flow to set
	 */
	public void setFlow(float flow) {
		this.flow = flow;
		/**
		 * if (flow <= maxCapacity || flow == -1) { isWorking = true; } else {
		 * isWorking = false; state = false;
		 **/
	}

	/**
	 * Calculates the state of the edge (see description of isWorking).
	 * 
	 * @param simMode
	 *            Simulation Mode
	 */

	public void calculateState(boolean simMode) {
		if (flow > maxCapacity && maxCapacity != -1) {
			isWorking = false;
		} else {
			if (!simMode && (flow <= maxCapacity || maxCapacity == -1)) {
				isWorking = true;
			}
		}
	}

	/**
	 * Getter for the Source.
	 * 
	 * @return the a
	 */
	public AbstractCpsObject getA() {
		return a;
	}

	/**
	 * Set the Source to a new one.
	 * 
	 * @param a
	 *            the a to set
	 */
	public void setA(AbstractCpsObject a) {
		this.a = a;
	}

	/**
	 * Getter for the destination.
	 * 
	 * @return the b
	 */
	public AbstractCpsObject getB() {
		return b;
	}

	/**
	 * Set the Destination to a new one.
	 * 
	 * @param b
	 *            the b to set
	 */
	public void setB(AbstractCpsObject b) {
		this.b = b;
	}

	/**
	 * Set the state manually to a new one.
	 * 
	 * @param state
	 *            the state
	 */
	public void setState(boolean state) {
		isWorking = state;
	}

	/**
	 * Getter for the status.
	 * 
	 * @return the state
	 */
	public boolean getState() {
		return isWorking;
	}

	/**
	 * set the tags into a new set of tags.
	 * 
	 * @param tags
	 *            tags for this edge
	 */
	public void setTags(ArrayList<Integer> tags) {
		this.tags = tags;
	}

	/**
	 * Getter for the ArrayList of tags.
	 * 
	 * @return tags tags for this edge
	 */
	public ArrayList<Integer> getTags() {
		return tags;
	}

	/**
	 * Add a new tag to the ArrayList.
	 * 
	 * @param tag tag for the ArrayList
	 */
	public void addTag(int tag) {
		if(!tags.contains(tag)){
			tags.add(tag);
		}
	}
	
	/**
	 * checks wether tags contains all given tags
	 * @param toCheck 
	 * 				tags that are checked
	 * @return
	 * 		true if all are contained in tags, false otherwise
	 */
	public boolean containsTags(ArrayList<Integer> list, ArrayList<Integer> toCheck){
		if(toCheck.size() == 0){
			return true;
		}else{
			for(Integer i: toCheck){
				if(!(list.contains(i))){
					return false;
				}
			}
			return true;
		}
	}
	
	public void addPseudoTag(int tag){
		if(!pseudoTags.contains(tag)){
			pseudoTags.add(tag);
		}
	}
	
	public void setPseudoTag(ArrayList<Integer> list){
		pseudoTags = list;
	}
	
	public ArrayList<Integer> getPseudoTags(){
		return pseudoTags;
	}
	
	public void recalculateTags(){
		for(Integer i: pseudoTags){
			if(!tags.contains(i)){
				tags.add(i);
			}
		}
	}

}