package ui.controller;

import api.CpsAlgorithm;
import classes.*;

import com.google.gson.JsonParseException;

import interfaces.CategoryListener;

import org.apache.commons.compress.archivers.ArchiveException;

import ui.model.Model;
import ui.model.Model.FairnessModel;
import ui.view.CreateTemplatePopUp;
import ui.view.FlexiblePane;
import ui.view.GUI;
import ui.view.MyCanvas;
import ui.view.Outliner;
import ui.view.StatisticGraphPanel;

import java.awt.*;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.stream.Collectors;

import javax.swing.JFrame;

/**
 * The Class represents the controller in the model, controller view Pattern.
 *
 * @author Gruppe14
 */
public class Control {

    private final MultiPurposeController multiPurposeController;
    private final CategoryController categoryController;
    private final ObjectController objectController;
    private final CanvasController canvasController;
    private final GlobalController globalController;
    private final SaveController saveController;
    private final LoadController loadController;
    private final AutoSaveController autoSaveController;
    private final StatsController statsController;
    private final NodeController nodeController;
    private final ClipboardController clipboardController;
    private final HolonCanvasController holonCanvasController;
    private Model model;
    private GUI gui;
    private SimulationManager simulationManager;
    private String autosaveDir = "";
    private String categoryDir = "";
    private String otherDir = "";
    private String dimensionsFileName = "dimensions";
    private int rand;

    /**
     * Constructor.
     *
     * @param model the Model
     */
    public Control(Model model) {
        this.model = model;

        this.multiPurposeController = new MultiPurposeController(model);
        this.categoryController = new CategoryController(model, multiPurposeController);
        this.objectController = new ObjectController(model, multiPurposeController);
        this.canvasController = new CanvasController(model, multiPurposeController);
        this.globalController = new GlobalController(model);
        this.saveController = new SaveController(model);
        this.nodeController = new NodeController(model, canvasController, multiPurposeController);
        this.loadController = new LoadController(model, categoryController, canvasController, objectController,
                nodeController, multiPurposeController);
        this.simulationManager = new SimulationManager(model);
        this.autoSaveController = new AutoSaveController(model);
        this.statsController = new StatsController(model);
        this.clipboardController = new ClipboardController(model, saveController, loadController, canvasController,
                objectController, nodeController, multiPurposeController);
        this.holonCanvasController = new HolonCanvasController(model);

        autosaveDir = System.getProperty("user.home") + "/.config/HolonGUI/Autosave/";
        categoryDir = System.getProperty("user.home") + "/.config/HolonGUI/Category/";
        otherDir = System.getProperty("user.home") + "/.config/HolonGUI/Other/";
        File autoSave = new File(autosaveDir);
        File category = new File(categoryDir);
        File other = new File(otherDir);
        // deleteDirectory(dest);
        autoSave.mkdirs();
        category.mkdirs();
        other.mkdirs();
        createAutoRandom();
        try {
            autoSave();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Generate random number, so that every instance of the program has unique
     * save files
     */
    private void createAutoRandom() {
        rand = (int) (Math.random() * 1000);
        while (new File(autosaveDir + rand + (autoSaveController.getAutoSaveNr())).exists()) {
            rand = (int) Math.random() * 1000;
        }
    }

    /**
     * Delete a Directory.
     *
     * @param path to delete
     */
    public void deleteDirectory(File path) {
        if (path.exists()) {
            File[] files = path.listFiles();
            for (File file : files) {
                if (file.isDirectory()) {
                    deleteDirectory(file);
                } else {
                    if (file.getName().contains("" + rand))
                        file.delete();
                }
            }
            // path.delete();
        }
    }

	/* Operations for searching */

    /**
     * Search for Object by ID.
     *
     * @param id the id of the Object
     * @return the CpsObject
     */
    public AbstractCanvasObject searchByID(int id) {
        return multiPurposeController.searchByID(id);
    }

    /**
     * Search for Object by ID in upperNode
     *
     * @param id the id of the Object
     * @return the CpsObject
     */
    public AbstractCanvasObject searchByIDUpperNode(int id, GroupNode upperNode) {
        return multiPurposeController.searchByIDUpperNode(id, upperNode);
    }

    public AbstractCanvasObject searchTracked(int id) {
        return multiPurposeController.searchByID(id);
    }

    /**
     * Search for Object in a Category.
     *
     * @param category name of the Category
     * @param object   Name of the Object
     * @return The Object
     */
    public AbstractCanvasObject searchCategoryObject(String category, String object) {
        return multiPurposeController.searchCatObj(multiPurposeController.searchCat(category), object);
    }

    /**
     * search for category.
     *
     * @param cat name of the Category
     * @return the Category
     */
    public Category searchCategory(String cat) {
        return multiPurposeController.searchCat(cat);
    }

	/* Operations for Categories and Objects */

    /**
     * init default category and objects.
     *
     * @throws IOException
     */
    public void resetCategorys() throws IOException {
        categoryController.initCategories();
        objectController.initHolonElements();
        saveCategory();
    }

    /**
     * Adds New Category into Model.
     *
     * @param cat name of the new Category
     * @throws IOException
     */
    public void addCategory(String cat) throws IOException {
        categoryController.addNewCategory(cat);
        saveCategory();
    }

    /**
     * Gives all Category as String
     * @return a array of strings from all Categorys
     */
    public String[] getCategoriesStrings()
    {
		return ((ArrayList<String>) categoryController.getCategories().stream().map(c -> c.getName()).collect(Collectors.toList())).toArray(new String[categoryController.getCategories().size()]);
    }
    /**
     * Add new Holon Object to a Category.
     *
     * @param cat Category
     * @param obj New Object Name
     * @param ele Array of Elements
     * @param img the image Path
     * @throws IOException
     */
    public void addObject(Category cat, String obj, ArrayList<HolonElement> ele, String img) throws IOException {
        categoryController.addNewHolonObject(cat, obj, ele, img);
        saveCategory();
    }


    /**
     * Add new Holon Switch to a Category.
     *
     * @param cat Category
     * @param obj New Object Name
     * @throws IOException
     */
    public void addSwitch(Category cat, String obj) throws IOException {
        categoryController.addNewHolonSwitch(cat, obj, "/Images/switch-on.png");
        saveCategory();
    }
    
    /**
     * Add new HolonBattery to a Category
     * @param cat
     * @param obj
     * @throws IOException
     */
    public void addBattery(Category cat, String obj) throws IOException {
        categoryController.addNewHolonBattery(cat, obj, "/Images/battery.png");
        saveCategory();
    }
    //TODO make good
    public void addBattery(Category cat, HolonBattery holonbat) throws IOException {
        categoryController.addNewHolonBattery(cat, holonbat, "/Images/battery.png");
        saveCategory();
    }
    
    /**
     * delete a given Category.
     *
     * @param cat the Category
     * @throws IOException
     */
    public void deleteCategory(String cat) throws IOException {
        categoryController.deleteCategory(cat);
        saveCategory();
    }

    /**
     * Delete an Object from a Category.
     *
     * @param cat the Category
     * @param obj the Object
     * @throws IOException
     */
    public void delObjectCategory(String cat, String obj) throws IOException {
        categoryController.deleteObject(cat, obj);
        saveCategory();
    }

    /**
     * deletes a selectedObject.
     *
     * @param obj Cpsobject
     */
    public void deleteSelectedObject(AbstractCanvasObject obj) {
        objectController.deleteSelectedObject(obj);
    }

    /**
     * add an Object to selectedObject.
     *
     * @param obj AbstractCpsobject
     */
    public void addSelectedObject(AbstractCanvasObject obj) {
        objectController.addSelectedObject(obj);
    }

	/* Operations for Canvas */

    /**
     * Add a new Object.
     *
     * @param object the Object
     */
    public void addObjectCanvas(AbstractCanvasObject object) {
        canvasController.addNewObject(object);
        calculateStateAndVisualForTimeStep(model.getCurIteration());
        if (!(object instanceof Node)) {
            try {
                autoSave();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Deletes an CpsObject on the Canvas and its connections.
     *
     * @param obj  AbstractCpsObject
     * @param save
     */
    public void delCanvasObject(AbstractCanvasObject obj, boolean save) {
        canvasController.deleteObjectOnCanvas(obj);
        if (obj instanceof GroupNode) {
        	canvasController.bfsNodeCleaner((GroupNode) obj);        	
        }
        calculateStateAndVisualForCurrentTimeStep();
        if (save)
            try {
                autoSave();
            } catch (IOException e) {
                e.printStackTrace();
            }
    }

    /**
     * Replaces {@code toBeReplaced} by {@code by} on the canvas
     * @param toBeReplaced the object that will be replaced
     * @param by the object that will replace it
     */
    public void replaceCanvasObject(AbstractCanvasObject toBeReplaced, AbstractCanvasObject by) {
    	canvasController.replaceObjectOnCanvas(toBeReplaced, by);
    	try {
            autoSave();
        } catch (IOException e) {
        	System.out.println("Error by Replacing "+toBeReplaced.toString() + " by " + by.toString());
            e.printStackTrace();
        }
    }
    
    /**
     * Add an edge to the Canvas.
     *
     * @param edge the edge
     */
    public void addEdgeOnCanvas(Edge edge) {
        canvasController.addEdgeOnCanvas(edge);
        try {
            autoSave();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Removes an Edge from the Canvas.
     *
     * @param edge the edge to remove
     */
    public void removeEdgesOnCanvas(Edge edge) {
        canvasController.removeEdgesOnCanvas(edge);
        try {
            autoSave();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Set the selected Edge.
     *
     * @param edge that is selected
     */
    public void setSelecteEdge(Edge edge) {
        model.setSelectedEdge(edge);
    }

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

	

	/* Operations for Objects and Elements */

    /**
     * Add a new Element into a Object on the Canvas.
     *
     * @param objectId  the Object ID
     * @param ele       the Name of the Element
     * @param amount    the Amount
     * @param energy    the Energy
     * @param elementId the Element ID
     */
    public void addElementCanvasObject(int objectId, String ele, int amount, float energy, int elementId) {
        objectController.addNewElementIntoCanvasObject(objectId, ele, amount, energy, elementId);
        try {
            autoSave();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Add a new Element into a Object in Category.
     *
     * @param catName the Category
     * @param objName the Object
     * @param eleName the Element Name
     * @param amount  the amount
     * @param energy  the Energy
     */
    public void addElementCategoryObject(String catName, String objName, String eleName, int amount, float energy) {
        objectController.addNewElementIntoCategoryObject(catName, objName, eleName, amount, energy);
    }

    /**
     * deletes a Element from a given Canvas Object.
     *
     * @param id        the ID
     * @param elementid the Element ID
     */
    public void deleteElementCanvas(int id, int elementid) {
        objectController.deleteElementInCanvas(id, elementid);
        try {
            autoSave();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

	/* Global Operations */

    /**
     * Add a SubNetColor.
     *
     * @param c the Color
     */
    public void addSubNetColor(Color c) {
        globalController.addSubNetColor(c);
    }

    /**
     * Returns SCALE.
     *
     * @return SCALE
     */
    public int getScale() {
        return globalController.getScale();
    }

    /**
     * Changes the value of SCALE and SCALEDIV2.
     *
     * @param s Scale
     */
    public void setScale(int s) {
        globalController.setScale(s);
    }

    /**
     * Returns SCALE Divided by 2.
     *
     * @return SCALE Divided by 2
     */
    public int getScaleDiv2() {
        return globalController.getScaleDiv2();
    }

    /**
     * sets the current Iteration.
     *
     * @param curit the current Iteration
     */
    public void setCurIteration(int curit) {
        globalController.setCurIteration(curit);
        //getGui().getTimePanel().getTimeSlider().setValue(curit);
    }

    /**
     * Writes the current State of the Modelling into a JSON File which can be
     * loaded.
     *
     * @param path the Path
     * @throws IOException exception
     */
    public void saveFile(String path) throws IOException, ArchiveException {
        saveController.writeSave(path);
    }

    /**
     * Reads the the Save File and load the state into the Model.
     *
     * @param path the Path
     * @throws IOException      exception
     * @throws ArchiveException
     */
    public void loadFile(String path) throws IOException, ArchiveException {
        loadController.readSave(path);
        saveCategory();
        autoSave();
    }

    /**
     * Reads the Json File from Autosave
     *
     * @param path
     * @throws IOException
     */
    public void loadAutoSave(String path) throws IOException {
        loadController.readJson(path);
    }

    public ArrayList<Integer> loadSavedWindowDimensionsIfExistent() {
        try {
            return loadController.readWindowDimensions(otherDir + dimensionsFileName);
        } catch (Exception e) {
            return new ArrayList<>();
        }
    }

    /**
     * Init the CategoryListener.
     *
     * @param catLis the CategoryListener
     */
    public void initListener(CategoryListener catLis) {
        categoryController.addCategoryListener(catLis);
    }

    /**
     * calculates the flow of the edges and the supply for objects for the
     * current Timestep.
     */
    public void calculateStateAndVisualForCurrentTimeStep() {
    	calculateStateAndVisualForTimeStep(model.getCurIteration());
    }

    public void calculateStateOnlyForCurrentTimeStep() {
    	simulationManager.calculateStateForTimeStep(model.getCurIteration(), false);
    }
    /**
     * calculates the flow of the edges and the supply for objects.
     *
     * @param x current Iteration
     */
    public void calculateStateAndVisualForTimeStep(int x) {
        simulationManager.calculateStateForTimeStep(x, true);
        updateOutliner();
        updateFlexWindow();
        this.updateCanvas();
    }

    /**
     * resets the whole State of the simulation including a reset of all Edges
     * to the default "is working" state
     */
    public void resetSimulation() {
      setIsSimRunning(false);
      simulationManager.resetFlexManager();
    }


    /**
     * make an autosave.
     *
     * @throws IOException Exception
     */
    public void autoSave() throws IOException {
        autoSaveController.increaseAutoSaveNr();
        saveController.writeAutosave(autosaveDir + rand + autoSaveController.getAutoSaveNr());
        if (autoSaveController.allowed()) {
            new File(autosaveDir + rand + (autoSaveController.getAutoSaveNr() - globalController.getNumbersOfSaves()))
                    .delete();
        }
    }

    /**
     * find all old auto save files (with a file-name, that does not contain the current rand)
     *
     * @return a list of files, that are not from the current run
     */
    public ArrayList<File> filterOldAutoSaveFiles() {
        File[] files = new File(autosaveDir).listFiles();
        ArrayList<File> oldAutoSaves = new ArrayList<>();

        for (File file : files) {
            if (!file.getName().contains(String.valueOf(rand)))
                oldAutoSaves.add(file);
        }

        return oldAutoSaves;
    }

    /**
     * deletes the old autosave files
     */
    public void deleteObsoleteAutoSaveFiles() {
        for (File file : filterOldAutoSaveFiles()) {
            file.delete();
        }
    }

    public void saveCategory() throws IOException {
        saveController.writeCategory(categoryDir + "Category.json");
    }

    public void savePosAndSizeOfWindow(int x, int y, int width, int height) throws IOException, ArchiveException {
        saveController.writeWindowStatus(otherDir + dimensionsFileName, x, y, width, height);
    }

    /**
     * Returns the undo save.
     *
     * @return the undo save
     */
    public String getUndoSave() {
        autoSaveController.decreaseAutoSaveNr();
        if (!new File(autosaveDir + rand + (autoSaveController.getAutoSaveNr())).exists()) {
            autoSaveController.increaseAutoSaveNr();
        }
        return autosaveDir + rand + (autoSaveController.getAutoSaveNr());
    }

    /**
     * Returns the redo save.
     *
     * @return the redo save
     */
    public String getRedoSave() {
        autoSaveController.increaseAutoSaveNr();
        if (!new File(autosaveDir + rand + (autoSaveController.getAutoSaveNr())).exists()) {
            autoSaveController.decreaseAutoSaveNr();

            // if it still does not exist, try old autosaves
            if (!new File(autosaveDir + rand + (autoSaveController.getAutoSaveNr())).exists()) {
                ArrayList<File> oldAutoSaves = filterOldAutoSaveFiles();
                if (oldAutoSaves.size() > 0) {
                    return autosaveDir + oldAutoSaves.get(oldAutoSaves.size() - 1).getName();
                }
            }
        }
        return autosaveDir + rand + (autoSaveController.getAutoSaveNr());
    }

    /**
     * Getter for Model.
     *
     * @return the Model
     */
    public Model getModel() {
        return model;
    }

    /**
     * get the Simulation Manager.
     *
     * @return the Simulation Manager
     */
    public SimulationManager getSimManager() {
        return simulationManager;
    }

  
    /**
     * Set the timerSpeed.
     *
     * @param t interval in ms
     */
    public void setTimerSpeed(int t) {
        globalController.setTimerSpeed(t);
    }

    /**
     * Set the Canvas X Size.
     *
     * @param canvasX the cANVAS_X to set
     */
    public void setCanvasX(int canvasX) {
        globalController.setCanvasX(canvasX);
        try {
            autoSave();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Set the Canvas Y Size.
     *
     * @param canvasY the cANVAS_Y to set
     */
    public void setCanvasY(int canvasY) {
        globalController.setCanvasY(canvasY);
        try {
            autoSave();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void setMaxCapacity(float cap) {
        globalController.setMaxCapacity(cap);
    }

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

    /**
     * Run the Algorithm.
     */
    public void runAlgorithm(Model model, Control controller) {
        if (model.getAlgorithm() != null) {
            ((CpsAlgorithm) model.getAlgorithm()).runAlgorithm(model, controller);
        }
    }

    // ========================= MANAGING TRACKED OBJECTS ====================

    public ArrayList<AbstractCanvasObject> getTrackingObj() {
        return statsController.getTrackingObj();
    }

    public void setTrackingObj(ArrayList<AbstractCanvasObject> objArr) {
        statsController.setTrackingObj(objArr);
    }

    public void addTrackingObj(AbstractCanvasObject obj) {
        statsController.addTrackingObj(obj);
        try {
            autoSave();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void removeTrackingObj(AbstractCanvasObject obj) {
        statsController.removeTrackingObj(obj);
        try {
            autoSave();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // ========================== MANAGING TRACKED OBJECTS END ================

    /**
     * Controlling Nodes of Nodes
     */

    public void addUpperNode(String nodeName, GroupNode upperNode, ArrayList<AbstractCanvasObject> toGroup) {
        nodeController.doUpperNode(nodeName, upperNode, toGroup);
        try {
            autoSave();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void ungroupGroupNode(GroupNode node, GroupNode upperNode) {
        nodeController.undoUpperNode(node, upperNode);
        try {
            autoSave();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void addObjUpperNode(AbstractCanvasObject object, GroupNode upperNode) {
    	nodeController.addObjectInUpperNode(object, upperNode, true);
        try {
            autoSave();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void delObjUpperNode(AbstractCanvasObject object, GroupNode upperNode) {
    	nodeController.deleteObjectInUpperNode(object, upperNode);
        if (object instanceof GroupNode)
            canvasController.bfsNodeCleaner((GroupNode) object);
        try {
            autoSave();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * Replaces {@code toBePlaced} by {@code by} in {@code upperNode}
     * @param toBeReplaced
     * @param by
     * @param upperNode
     */
	public void replaceObjUpperNode(AbstractCanvasObject toBeReplaced,
			AbstractCanvasObject by, GroupNode upperNode) {
		nodeController.replaceObjectInUpperNode(toBeReplaced, by, upperNode);
		try {
            autoSave();
        } catch (IOException e) {
        	System.out.println("Error by Replacing "+toBeReplaced.toString() 
        			+ " by " + by.toString() + " in UpperNode " + upperNode.toString());
            e.printStackTrace();
        }
	}



  

    /**
     * Get the number of HolonObjects in the given List
     *
     * @param list
     */
    public int getNumberHolonObjects(ArrayList<AbstractCanvasObject> list) {
        return objectController.getNumberHolonObjects(list);
    }
    
    /**
     * Get the number of HolonObjects in the given List
     *
     * @param list
     */
    public ArrayList<HolonObject> getAllHolonObjects(ArrayList<AbstractCanvasObject> list) {
        return objectController.getAllHolonObjects(list);
    }


    /**
     * Returns HolonBodySCALE.
     *
     * @return SCALE
     */
    public int getHolonBodyScale() {
        return globalController.getHolonBodyScale();
    }

    /**
     * Changes the value of HolonBodySCALE
     *
     * @param s HolonBodyScale
     */
    public void setHolonBodyScale(int s) {
        globalController.setHolonBodyScale(s);
    }

    /**
     * Sets the ID of the selected HolonBody
     *
     * @param i ID of the selected HolonBody
     */
    public void addSelectedHolonBody(int i) {
        objectController.addSelectedHolonBody(i);
    }

    /**
     * Copy all Selected Objects.
     */
    public void copy(GroupNode upperNode) {
        clipboardController.copy(upperNode);
    }

    public void paste(GroupNode upperNode, Point point)
            throws JsonParseException, UnsupportedFlavorException, IOException {
        clipboardController.paste(upperNode, point);
        try {
            autoSave();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void cut(GroupNode upperNode) {
        clipboardController.cut(upperNode);
        try {
            autoSave();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * creates a new Template for the given cps Object
     * @param cps Object, which should become a template
     * @param parentFrame 
     */
    public void createTemplate(HolonObject cps, JFrame parentFrame) {
        CreateTemplatePopUp t = new CreateTemplatePopUp(cps,model,parentFrame,this);
        t.setVisible(true);
    }

    public void getObjectsInDepth() {
        clipboardController.getObjectsInDepth();
    }

    public float getTotalProduction(ArrayList<AbstractCanvasObject> arrayList) {
        return holonCanvasController.getTotalProduction(arrayList);
    }

    public float getTotalConsumption(ArrayList<AbstractCanvasObject> arrayList) {
        return holonCanvasController.getTotalConsumption(arrayList);
    }

    public int getTotalElements(ArrayList<AbstractCanvasObject> arrayList) {
        return holonCanvasController.getTotalElements(arrayList);
    }

    public int getTotalProducers(ArrayList<AbstractCanvasObject> arrayList) {
        return holonCanvasController.getTotalProducers(arrayList);
    }

    public int getActiveElements(ArrayList<AbstractCanvasObject> arrayList) {
        return holonCanvasController.getActiveElements(arrayList);
    }

    /**
     * Set the Background Image;
     *
     * @param imagePath Image Path
     * @param mode      Image Mode
     * @param width     Image custom width
     * @param height    Image custom height
     */
    public void setBackgroundImage(String imagePath, int mode, int width, int height) {
        canvasController.setBackgroundImage(imagePath, mode, width, height);
    }

    public void setFlexiblePane(FlexiblePane fp) {
        simulationManager.setFlexiblePane(fp);
    }

    public Hashtable<String, StatisticGraphPanel> getGraphTable() {
        return model.getGraphTable();
    }

    public void setGraphTable(Hashtable<String, StatisticGraphPanel> gT) {
        model.setGraphTable(gT);
    }

    /**
     * Sets if the Simulation is running
     */
    public void setIsSimRunning(boolean isRunning) {
        globalController.setIsSimRunning(isRunning);
    }


    /**
     * Sets show
     * @param showSupplyBars wether the bars should be shown
     */
	public void setShowSupplyBars(boolean showSupplyBars) {
		globalController.setShowSupplyBars(showSupplyBars);
	}
	
	/**
     * Sets fairness Model
     * @param fairnessModel that should be used. 
     */
	public void setFairnessModel(FairnessModel fairnessModel) {
		globalController.setFairnessModel(fairnessModel);
	}
	
	public void updateOutliner() {
		gui.updateOutliners(simulationManager.getActualDecorState());
	}
	
	public void updateFlexWindow() {
		gui.updateFlexWindows();
	}
	
	
	public void updateCanvas() {
		gui.repaintCanvas();
		gui.triggerUpdateController(null);
	}
	public GUI getGui() {
		return gui;
	}

	public void guiDisable(boolean state) {
		gui.guiDisable(state);
	}
	
	public void setGui(GUI gui) {
		this.gui = gui;
	}
	
}
