package classes;

import java.awt.Point;
import java.util.LinkedList;

import com.google.gson.annotations.Expose;

/**
 * The class HolonSwitch represents a Switch, which can be turned on and off.
 * 
 * @author Gruppe14
 *
 */
public class HolonSwitch extends AbstractCpsObject implements IGraphedElement {

	/**
	 * The class HolonSwitch represents an Object in the system, that has the
	 * capacity of manipulate the electricity flow. The switch can be manage
	 * automatically through a graph or direct manually.
	 * 
	 * @author Gruppe14
	 *
	 */
	/*
	 * manual state True, if this wire is working (capable of carrying
	 * electricity), else false
	 */
	@Expose
	boolean manualActive;

	/*
	 * active state True, if this wire is working (capable of carrying
	 * electricity), else false
	 */
	@Expose
	boolean autoActive;

	/*
	 * true if switch has to be used manually
	 */
	@Expose
	boolean manualMode;
	
	@Expose
	int localPeriod;

	/*
	 * Energy at each point of the graph with 50 predefined points. At the
	 * beginning, it starts with all values at energy
	 */
	boolean[] activeAt;
	// Points on the UnitGraph
	LinkedList<Point> graphPoints = new LinkedList<>();

	/**
	 * Create a new HolonSwitch with the default name ("Switch"), a default
	 * value of automatic handle and active status.
	 * 
	 * @param objName
	 *            String
	 */
	public HolonSwitch(String objName) {
		super(objName);
		activeAt=new boolean[100];
		setManualState(true);
		setAutoState(true);
		setActiveAt(true);
		setManualMode(false);
		setGraphPoints(new LinkedList<Point>());
	}

	/**
	 * Create a copy of an existing HolonSwitch.
	 * 
	 * @param obj
	 *            the Object to copy
	 */
	public HolonSwitch(AbstractCpsObject obj) {
		super(obj);
		super.setName(obj.getName());
		setManualState(((HolonSwitch) obj).getActiveManual());
		setAutoState(true);
		setLocalPeriod(((IGraphedElement)obj).getLocalPeriod());
		setActiveAt(true);
		for (int i = 0; i < activeAt.length; i++) {
			activeAt[i] = ((HolonSwitch) obj).getActiveAt()[i];
		}
		setGraphPoints(new LinkedList<Point>());
		for (Point p : ((HolonSwitch) obj).getGraphPoints()) {
			this.graphPoints.add(new Point((int) p.getX(), (int) p.getY()));
		}
		setManualMode(((HolonSwitch) obj).getManualMode());
	}

	/**
	 * Calculates the state of the Switch.
	 */
	public void switchState() {
		if (!manualMode) {
			setManualMode(true);
		}
		if (this.manualActive == true) {
			setImage("/Images/switch-off.png");
		} else {
			setImage("/Images/switch-on.png");
		}
		this.manualActive = !manualActive;

	}

	/**
	 * Getter for the status of the Switch at a given timestep.
	 * 
	 * @param timeStep
	 *            int
	 * @return state value
	 */
	public boolean getState(int timeStep) {
		if (manualMode) {
			return this.manualActive;
		} else {
			return getActiveAt()[timeStep];
		}
	}

	/**
	 * Overall status of the switch (manual or automatic mode).
	 * 
	 * @return boolean the State
	 */
	public boolean getState() {
		if (manualMode) {
			return this.manualActive;
		} else {
			return this.autoActive;
		}

	}

	/**
	 * Change the state of the Switch to manual.
	 * 
	 * @param state
	 *            the State
	 */
	public void setManualState(boolean state) {
		this.manualActive = state;
		setImage();
	}

	/**
	 * Set the state of the Switch to automatic.
	 * 
	 * @param state
	 *            the State
	 */
	public void setAutoState(boolean state) {
		this.autoActive = state;
		setImage();
	}

	/**
	 * Set Image of the Switch.
	 */
	private void setImage() {
		if (manualMode) {
			if (this.manualActive == false) {
				setImage("/Images/switch-off.png");
			} else {
				setImage("/Images/switch-on.png");
			}
		} else {
			if (this.autoActive == false) {
				setImage("/Images/switch-off.png");
			} else {
				setImage("/Images/switch-on.png");
			}
		}
	}

	/**
	 * For automatic use only (throught the graph).
	 * 
	 * @return the Graph Points
	 */
	public LinkedList<Point> getGraphPoints() {
		return graphPoints;
	}

	/**
	 * Set the values of the switch in the graph (auto. mode only).
	 * 
	 * @param points
	 *            the Graph points
	 */
	public void setGraphPoints(LinkedList<Point> points) {
		this.graphPoints = points;
	}

	/**
	 * All values of the graph for the selected Switch (only auto-Mode) get the
	 * activeAt Array.
	 * 
	 * @return boolean[] the States of each Iteration
	 */
	public boolean[] getActiveAt() {
		return activeAt;
	}

	/**
	 * Returns the ManualState.
	 * 
	 * @return boolean Manual State
	 */
	public boolean getActiveManual() {
		return this.manualActive;
	}

	/**
	 * Set the value of the Switch.
	 * 
	 * @param active
	 *            the default value
	 */
	public void setActiveAt(boolean active) {
		activeAt = new boolean[100];
		for (int i = 0; i < activeAt.length; i++) {
			this.activeAt[i] = active;
		}
	}

	/**
	 * Set the overall value of the Switch (manual mode).
	 * 
	 * @param mode
	 *            the mode (boolean)
	 */
	public void setManualMode(boolean mode) {
		manualMode = mode;
	}

	/**
	 * Get manualmode state.
	 * 
	 * @return boolean manual mode state
	 */
	public boolean getManualMode() {
		return manualMode;
	}

	@Override
	public void setLocalPeriod(int period) {
		localPeriod=period;
		activeAt=new boolean[localPeriod];
	}

	@Override
	public int getLocalPeriod() {
		return localPeriod;
	}
}