package ui.controller;

import classes.*;
import ui.model.Model;

import java.util.ArrayList;

/**
 * Controller for Objects.
 *
 * @author Gruppe14
 */
public class ObjectController {

    private Model model;
    private MultiPurposeController mpC;

    /**
     * Constructor.
     *
     * @param model Model
     * @param mp    MultiPurposeController
     */
    public ObjectController(Model model, MultiPurposeController mp) {
        this.model = model;
        this.mpC = mp;
        initHolonElements();
    }

    /**
     * init default Power supply of the Power Plant.
     */
    public void initHolonElements() {
        addNewElementIntoCategoryObject("Energy", "Power Plant", "Power", 1, 10000);
        addNewElementIntoCategoryObject("Building", "House", "TV", 2, -250);
        addNewElementIntoCategoryObject("Building", "House", "Fridge", 1, -500);
        addNewElementIntoCategoryObject("Building", "House", "Radio", 1, -100);
        addNewElementIntoCategoryObject("Building", "House", "PC", 3, -250);
        addNewElementIntoCategoryObject("Building", "House", "Light", 5, -50);
        addNewElementIntoCategoryObject("Building", "House", "Solar Panels", 1, 300);
    }

    /**
     * Adds Element into a Object.
     *
     * @param object  the Object
     * @param element the Element
     */
    public void addElement(HolonObject object, HolonElement element) {
        object.getElements().add(element);
    }

    /**
     * Adds Element into a Object on the Canvas.
     *
     * @param object  the Object
     * @param element the Element
     */
    public void addElementIntoCanvasObject(HolonObject object, HolonElement element) {
        element.setSaving(null);
        addElement(object, element);
    }

    /**
     * Add a new Element into a Object on the Canvas.
     *
     * @param objectId  the Object ID
     * @param element   the Name of the Element
     * @param amount    the Amount
     * @param energy    the Energy
     * @param elementId the Element ID
     */
    public void addNewElementIntoCanvasObject(int objectId, String element, int amount, float energy, int elementId) {
        HolonElement ele = new HolonElement(element, amount, energy, elementId);
        if (mpC.searchByID(objectId) == null) {
            addElementIntoCanvasObject((HolonObject) model.getSelectedCpsObjects().get(0), ele);
        } else {
            addElementIntoCanvasObject((HolonObject) mpC.searchByID(objectId), ele);
        }
    }

    /**
     * Add Element into a Object in Category.
     *
     * @param category the Category
     * @param object   the Object
     * @param element  the Element
     */
    public void addElementIntoCategoryObject(String category, String object, HolonElement element) {
        element.setSaving(new Pair<>(category, object));
        addElement((HolonObject) mpC.searchCatObj(mpC.searchCat(category), object), element);
    }

    /**
     * Add a new Element into a Object in Category.
     *
     * @param category the Category
     * @param object   the Object
     * @param element  the Element Name
     * @param energy   the Energy
     * @param amount   the amount
     */
    public void addNewElementIntoCategoryObject(String category, String object, String element, int amount,
                                                float energy) {

        HolonElement ele = new HolonElement(element, amount, energy);
        addElementIntoCategoryObject(category, object, ele);
    }

    /**
     * deletes a Element from a given Object.
     *
     * @param obj the Oject
     * @param ele the Element
     */
    public void deleteElement(HolonObject obj, HolonElement ele) {
        obj.getElements().remove(ele);
    }

    /**
     * deletes a selectedObject.
     *
     * @param obj Cpsobject
     */
    public void deleteSelectedObject(AbstractCpsObject obj) {
        model.getSelectedCpsObjects().remove(obj);
    }

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

    /**
     * deletes a Element from a given Canvas Object.
     *
     * @param id    the ID
     * @param eleid the Element ID
     */
    public void deleteElementInCanvas(int id, int eleid) {
        HolonObject object = (HolonObject) mpC.searchByID(id);
        if (object == null) {
            object = (HolonObject) model.getSelectedCpsObjects().get(0);
        }
        HolonElement element = mpC.searchEleById(object, eleid);
        deleteElement(object, element);
    }

    /**
     * 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) {
        model.setSelectedObjectID(id);
    }

    /**
     * Get the number of HolonObjects in the given List
     *
     * @param list
     */
    public int getNumberHolonObjects(ArrayList<AbstractCpsObject> list) {
        int val = 0;

        for (AbstractCpsObject obj : list) {
            if (obj instanceof HolonObject) {
                val++;
            } else if (obj instanceof CpsUpperNode) {
                val += getNumberHolonObjects(((CpsUpperNode) obj).getNodes());
            }
        }
        return val;
    }

    /**
     * Get the number of HolonObjects with the given state in the given List
     *
     * @param list
     * @param state
     */
    public int getNumberStateObjects(ArrayList<AbstractCpsObject> list, int state) {
        int val = 0;

        for (AbstractCpsObject obj : list) {
            if (obj instanceof HolonObject) {
                if (((HolonObject) obj).getState() == state || (state == 2 && ((HolonObject) obj).getState() == 3)) {
                    val++;
                }
            } else if (obj instanceof CpsUpperNode) {
                val += getNumberStateObjects(((CpsUpperNode) obj).getNodes(), state);
            }
        }
        return val;
    }

    /**
     * add the ID of a HolonBody.
     *
     * @param i int
     */
    public void addSelectedHolonBody(int i) {
        model.setSelectedHolonBody(i);
    }
}
