package ui.model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import classes.Category;
import classes.CpsEdge;
import classes.AbstractCpsObject;
import classes.HolonElement;
import interfaces.CategoryListener;
import interfaces.ObjectListener;
import ui.view.Console;

/**
 * The Class Model is the class where everything is saved. All changes made to
 * the Data is managed via a controller.
 * 
 * @author Gruppe14
 *
 */
public class Model {

	// Global Variables
	private int canvasX = 1000;
	private int canvasY = 1000;
	private static int sCALE = 50; // Picture Scale
	private static int sCALEdIV2 = sCALE / 2;
	private static final int ITERATIONS = 100;
	private int curIteration = 0;
	// ID of the Selected Object
	private AbstractCpsObject selectedCpsObject = null;
	private HolonElement selectedHolonElement;
	private CpsEdge selectedEdge;
	private ArrayList<AbstractCpsObject> selectedObjects = new ArrayList<AbstractCpsObject>();
	private ArrayList<AbstractCpsObject> clipboardObjects = new ArrayList<AbstractCpsObject>();
	private Console console;

	// Iteration Speed
	private int timerSpeed = 1000;

	// Simulation boolean
	private boolean isSimulation = false;

	private int selectedID = 0;
	// number of the current autosave
	private int autoSaveNr = -1;
	// number of max simultaneous autosaves
	private int numberOfSaves = 35;
	/*
	 * Array of all categories in the model. It is set by default with the
	 * categories ENERGY, BUILDINGS and COMPONENTS
	 */
	private ArrayList<Category> categories;

	/*
	 * Array of all CpsObjects in our canvas. It is set by default as an empty
	 * list.
	 */
	private ArrayList<AbstractCpsObject> objectsOnCanvas;

	private HashMap<String, Integer> cgIdx;
	private HashMap<Integer, Integer> cvsObjIdx;

	/*
	 * Array of all CpsObjects in our canvas. It is set by default as an empty
	 * list.
	 */
	private ArrayList<CpsEdge> edgesOnCanvas;

	/*
	 * Array for all Listeners
	 */
	private List<CategoryListener> categoryListeners;
	private List<ObjectListener> objectListeners;

	/*
	 * Object that runs the Algorithm
	 */
	private Object algorithm = null;
	
	/**
	 * Constructor for the model. It initializes the categories and
	 * objectsOnCanvas by default values. Listeners are also initialized by
	 * default values.
	 */
	public Model() {
		setCategories(new ArrayList<Category>());
		setObjectsOnCanvas(new ArrayList<AbstractCpsObject>());
		setEdgesOnCanvas(new ArrayList<CpsEdge>());
		setCategoryListeners(new LinkedList<CategoryListener>());
		setObjectListeners(new LinkedList<ObjectListener>());
		setCgIdx(new HashMap<String, Integer>());
		setCvsObjIdx(new HashMap<Integer, Integer>());
		setClipboradObjects(new ArrayList<AbstractCpsObject>());
	}

	/**
	 * Returns all Categories.
	 * 
	 * @return the categories
	 */
	public ArrayList<Category> getCategories() {
		return categories;
	}

	/**
	 * Sets all Categories.
	 * 
	 * @param categories
	 *            the categories to set
	 */
	public void setCategories(ArrayList<Category> categories) {
		this.categories = categories;
	}

	/**
	 * Transform the Arraylist of categories into a string of all objectName
	 * with a separation (',') between each name.
	 * 
	 * @return String of all names separeted by ','
	 */
	public String toStringCat() {
		String text = "";
		for (int i = 0; i < categories.size(); i++) {
			if (text == "") {
				text = categories.get(i).getName();
			} else {
				text = text + ", " + categories.get(i).getName();
			}
		}
		return text;
	}

	/**
	 * Returns all Objects on the Canvas.
	 * 
	 * @return the objectsOnCanvas
	 */
	public ArrayList<AbstractCpsObject> getObjectsOnCanvas() {
		return objectsOnCanvas;
	}

	/**
	 * Sets all Objects on the Canvas.
	 * 
	 * @param objectsOnCanvas
	 *            the objectsOnCanvas to set
	 */
	public void setObjectsOnCanvas(ArrayList<AbstractCpsObject> objectsOnCanvas) {
		this.objectsOnCanvas = objectsOnCanvas;
	}

	/**
	 * Get all Edges on the Canvas.
	 * 
	 * @return the objectsOnCanvas
	 */
	public ArrayList<CpsEdge> getEdgesOnCanvas() {
		return edgesOnCanvas;
	}

	/**
	 * Adds an Edge to The Canvas.
	 * 
	 * @param edge
	 *            the edgesOnCanvas to add
	 */
	public void addEdgeOnCanvas(CpsEdge edge) {
		this.edgesOnCanvas.add(edge);
	}

	/**
	 * Remove an edge from the Canvas.
	 * 
	 * @param edge
	 *            the edge to remove
	 */
	public void removeEdgesOnCanvas(CpsEdge edge) {
		this.edgesOnCanvas.remove(edge);
	}

	/**
	 * Sets the edges on the Canvas.
	 * 
	 * @param arrayList
	 *            the edgesOnCanvas to set
	 */
	public void setEdgesOnCanvas(ArrayList<CpsEdge> arrayList) {
		this.edgesOnCanvas = arrayList;
	}

	/**
	 * Returns the ObjectListener.
	 * 
	 * @return the objectListeners
	 */
	public List<ObjectListener> getObjectListeners() {
		return objectListeners;
	}

	/**
	 * Sets the ObjectListener.
	 * 
	 * @param linkedList
	 *            the objectListeners to set
	 */
	public void setObjectListeners(LinkedList<ObjectListener> linkedList) {
		this.objectListeners = linkedList;
	}

	/**
	 * Returns the CategorieListener.
	 * 
	 * @return the categoryListeners
	 */
	public List<CategoryListener> getCategoryListeners() {
		return categoryListeners;
	}

	/**
	 * Sets the CategorieListener.
	 * 
	 * @param linkedList
	 *            the categoryListeners to set
	 */
	public void setCategoryListeners(LinkedList<CategoryListener> linkedList) {
		this.categoryListeners = linkedList;
	}

	/**
	 * Set the ID of the selected Object 0 = no Object is selected.
	 * 
	 * @param id
	 *            the ID
	 * 
	 */
	public void setSelectedObjectID(int id) {
		this.selectedID = id;
	}

	/**
	 * Returns the ID of the selected Object 0 = no Object is selected.
	 * 
	 * @return ID
	 */
	public int getSelectedObjectID() {
		return selectedID;
	}

	/**
	 * Returns the Selected Cps Object.
	 * 
	 * @return selected Cps Object
	 */
	public AbstractCpsObject getSelectedCpsObject() {
		return selectedCpsObject;
	}

	/**
	 * Set the Selected Objecs.
	 * 
	 * @param selectedCpsObject
	 *            Objects that are selected
	 */
	public void setSelectedCpsObject(AbstractCpsObject selectedCpsObject) {
		this.selectedCpsObject = selectedCpsObject;
	}

	/**
	 * Returns all selected Objects on the Canvas.
	 * 
	 * @return The selected Objects
	 */
	public ArrayList<AbstractCpsObject> getSelectedCpsObjects() {
		return selectedObjects;
	}

	/**
	 * Returns the Selected Holon Element.
	 * 
	 * @return selected Holon Element
	 */
	public HolonElement getSelectedHolonElement() {
		return selectedHolonElement;
	}

	/**
	 * Sets the Selecte HolonElement.
	 * 
	 * @param selectedHolonElement
	 *            that is Selected
	 */
	public void setSelectedHolonElement(HolonElement selectedHolonElement) {
		this.selectedHolonElement = selectedHolonElement;
	}

	/**
	 * Returns the sCale (Scale for the Images).
	 * 
	 * @return sCALE
	 */
	public int getScale() {
		return sCALE;
	}

	/**
	 * Returns sCALEdIV2 (The Scale divided by 2).
	 * 
	 * @return sCALEdIV2
	 */
	public int getScaleDiv2() {
		return sCALEdIV2;
	}

	/**
	 * Sets the Image Scale.
	 * 
	 * @param scale
	 *            for the image
	 */
	public void setScale(int scale) {
		sCALE = scale;
		sCALEdIV2 = sCALE / 2;
	}

	/**
	 * Returns ITERATIONS.
	 * 
	 * @return ITERATIONS
	 */
	public int getIterations() {
		return ITERATIONS;
	}

	/**
	 * sets the current Iteration.
	 * 
	 * @param curIT
	 *            the current Iteration
	 */
	public void setCurIteration(int curIT) {
		this.curIteration = curIT;
	}

	/**
	 * Returns cURiTERATION.
	 * 
	 * @return cURiTERATION
	 */
	public int getCurIteration() {
		return curIteration;
	}

	/**
	 * Set the selected Edge.
	 * 
	 * @param edge
	 *            that is selected
	 * 
	 */
	public void setSelectedEdge(CpsEdge edge) {
		this.selectedEdge = edge;
	}

	/**
	 * Returns the selected Edge.
	 * 
	 * @return selectedEdge
	 */
	public CpsEdge getSelectedEdge() {
		return selectedEdge;
	}

	/**
	 * Returns the Categorie Index.
	 * 
	 * @return the cgIdx
	 */
	public HashMap<String, Integer> getCgIdx() {
		return cgIdx;
	}

	/**
	 * Sets the Categorie Index.
	 * 
	 * @param cgIdx
	 *            the cgIdx to set
	 */
	public void setCgIdx(HashMap<String, Integer> cgIdx) {
		this.cgIdx = cgIdx;
	}

	/**
	 * Returns the CanvasObject Index.
	 * 
	 * @return the cvsObjIdx
	 */
	public HashMap<Integer, Integer> getCvsObjIdx() {
		return cvsObjIdx;
	}

	/**
	 * Sets the CanvasObject Index.
	 * 
	 * @param cvsObjIdx
	 *            the cvsObjIdx to set
	 */
	public void setCvsObjIdx(HashMap<Integer, Integer> cvsObjIdx) {
		this.cvsObjIdx = cvsObjIdx;
	}

	/**
	 * Sets the auto save Number.
	 * 
	 * @param autoSaveNr
	 *            the auto save number
	 */
	public void setAutoSaveNr(int autoSaveNr) {
		this.autoSaveNr = autoSaveNr;
	}

	/**
	 * Returns the auto save Number.
	 * 
	 * @return the auto save Number
	 */
	public int getAutoSaveNr() {
		return autoSaveNr;
	}

	/**
	 * Returns the Number of Saves.
	 * 
	 * @return the numberOfSaves
	 */
	public int getNumberOfSaves() {
		return numberOfSaves;
	}

	/**
	 * Set the Number of Saves.
	 * 
	 * @param numberOfSaves
	 *            the numberOfSaves to set
	 */
	public void setNumberOfSaves(int numberOfSaves) {
		this.numberOfSaves = numberOfSaves;
	}

	/**
	 * Sets the ClipboardObjects.
	 * 
	 * @param c
	 *            Array of Objects
	 */
	public void setClipboradObjects(ArrayList<AbstractCpsObject> c) {
		this.clipboardObjects = c;
	}

	/**
	 * Returns all Objects in the Clipboard.
	 * 
	 * @return Objects in the Clipboard
	 */
	public ArrayList<AbstractCpsObject> getClipboradObjects() {
		return clipboardObjects;
	}

	/**
	 * Sets the console.
	 * 
	 * @param console
	 *            the console
	 */
	public void setConsole(Console console) {
		this.console = console;
	}

	/**
	 * Returns the Console.
	 * 
	 * @return console the console
	 */
	public Console getConsole() {
		return console;
	}

	/**
	 * Sets the Interval in ms between each Iteration.
	 * 
	 * @param t
	 *            speed for the Iterations
	 */
	public void setTimerSpeed(int t) {
		this.timerSpeed = t;
	}

	/**
	 * get the Interval in ms between each Iteration.
	 * 
	 * @return timerSpeed speed for the Iterations
	 */
	public int getTimerSpeed() {
		return this.timerSpeed;
	}

	/**
	 * Sets the Simulation state (true = simulation, false = modeling).
	 * 
	 * @param isSimulation
	 *            boolean for for isSimulation
	 */
	public void setIsSimulation(boolean isSimulation) {
		this.isSimulation = isSimulation;
	}

	/**
	 * Returns the Simulation state (true = simulation, false = modeling).
	 * 
	 * @return isSimulation boolean for for isSimulation
	 */
	public boolean getIsSimulation() {
		return this.isSimulation;
	}

	/**
	 * Get Canvas X Size.
	 * 
	 * @return the cANVAS_X
	 */
	public int getCanvasX() {
		return canvasX;
	}

	/**
	 * Set Canvas X Size.
	 * 
	 * @param canvasX the cANVAS_X to set
	 */
	public void setCanvasX(int canvasX) {
		this.canvasX = canvasX;
	}

	/**
	 * get Canvas Y size.
	 * 
	 * @return the cANVAS_Y
	 */
	public int getCanvasY() {
		return canvasY;
	}

	/**
	 * Set Canvas Y size.
	 * 
	 * @param canvasY the cANVAS_Y to set
	 */
	public void setCanvasY(int canvasY) {
		this.canvasY = canvasY;
	}
	
	/**
	 * get the Algorithm.
	 * 
	 * @return the Algorithm
	 */
	public Object getAlgorithm() {
		return algorithm;
	}

	/**
	 * Set the Algorithm.
	 * 
	 * @param obj the Algorithm
	 */
	public void setAlgorithm(Object obj) {
		this.algorithm = obj;
	}
}
