package tests;

import static org.junit.Assert.assertTrue;

import org.junit.Before;
import org.junit.Test;

import classes.AbstractCpsObject;
import classes.HolonObject;
import ui.controller.CanvasController;
import ui.controller.CategoryController;
import ui.controller.MultiPurposeController;
import ui.controller.ObjectController;
import ui.model.Model;

/**
 * Tests for the ObjectController.
 * 
 * @author Gruppe14
 */
public class PraktikumHolonsTestObjectController {

	protected PraktikumHolonsAdapter adapter;
	protected Model model;
	protected MultiPurposeController mp;
	protected CategoryController cg;
	protected CanvasController cvs;
	protected ObjectController controller;

	/**
	 * Setup for the Tests.
	 */
	@Before
	public void setUp() {
		adapter = new PraktikumHolonsAdapter();
		model = new Model();
		mp = new MultiPurposeController(model);
		cg = new CategoryController(model, mp);
		cvs = new CanvasController(model, mp);
		controller = new ObjectController(model, mp);
	}

	/**
	 * Tests for the Initial HolonElements.
	 */
	@Test
	public void testInitialHolonElements() {
		assertTrue("Number of Elements does not Match",
				((HolonObject) mp.searchCatObj(mp.searchCat("Energy"), "Power Plant")).getElements().size() == 1);
		assertTrue("Element does not Match",
				mp.searchEle((HolonObject) mp.searchCatObj(mp.searchCat("Energy"), "Power Plant"), "Power").getEleName()
						.equals("Power"));
		assertTrue("Element does not Match",
				mp.searchEle((HolonObject) mp.searchCatObj(mp.searchCat("Energy"), "Power Plant"), "Power").getEleName()
						.equals("Power"));
		assertTrue("Total Energy does not Match",
				mp.searchEle((HolonObject) mp.searchCatObj(mp.searchCat("Building"), "House"), "PC")
						.getTotalEnergy() == -750);
		assertTrue("Non-Existant Element is Found",
				mp.searchEle((HolonObject) mp.searchCatObj(mp.searchCat("Building"), "House"), "") == null);
	}

	/**
	 * Tests for adding and Deleting in Categories.
	 */
	@Test
	public void testAddingAndDeletingInCategory() {
		controller.addNewElementIntoCategoryObject("Building", "House", "A", 1, -10);
		for (int i = 2; i < 27; i++) {
			controller.addNewElementIntoCategoryObject("Building", "House", adapter.generate(i), i, -10);
			// n(n+1) / 2
			assertTrue("Total Energy does not match", ((HolonObject) mp.searchCatObj(mp.searchCat("Building"), "House"))
					.getCurrentEnergy() == -1800 + ((i * (i + 1)) / 2) * -10);
			assertTrue("Number of Elements does not Match",
					((HolonObject) mp.searchCatObj(mp.searchCat("Building"), "House")).getElements().size() == 6 + i);
		}

		controller.deleteElementInCategory("Building", "House", "B");
		controller.deleteElementInCategory("Building", "House", "D");
		controller.deleteElementInCategory("Building", "House", "F");
		controller.deleteElementInCategory("Building", "House", "G");
		controller.deleteElementInCategory("Building", "House", "H");
		controller.deleteElementInCategory("Building", "House", "I");
		controller.deleteElementInCategory("Building", "House", "Z");
		controller.deleteElementInCategory("Building", "House", "TV");
		assertTrue("Element:B was Found",
				mp.searchEle((HolonObject) mp.searchCatObj(mp.searchCat("Building"), "House"), "B") == null);
		assertTrue("Element:D was Found",
				mp.searchEle((HolonObject) mp.searchCatObj(mp.searchCat("Building"), "House"), "D") == null);
		assertTrue("Element:F was Found",
				mp.searchEle((HolonObject) mp.searchCatObj(mp.searchCat("Building"), "House"), "F") == null);
		assertTrue("Element:G was Found",
				mp.searchEle((HolonObject) mp.searchCatObj(mp.searchCat("Building"), "House"), "G") == null);
		assertTrue("Element:H was Found",
				mp.searchEle((HolonObject) mp.searchCatObj(mp.searchCat("Building"), "House"), "H") == null);
		assertTrue("Element:I was Found",
				mp.searchEle((HolonObject) mp.searchCatObj(mp.searchCat("Building"), "House"), "I") == null);
		assertTrue("Element:Z was Found",
				mp.searchEle((HolonObject) mp.searchCatObj(mp.searchCat("Building"), "House"), "Z") == null);
		assertTrue("Element:TV was Found",
				mp.searchEle((HolonObject) mp.searchCatObj(mp.searchCat("Building"), "House"), "TV") == null);
	}

	/**
	 * Tests for Adding and Deleting Objects on the Canvas.
	 */
	@Test
	public void testAddingAndDeletingInCanvas() {
		for (int i = 0; i < 100; i++) {
			cvs.addNewObject(new HolonObject(mp.searchCatObj(mp.searchCat("Building"), "House")));
		}
		for (AbstractCpsObject cps : model.getObjectsOnCanvas()) {
			for (int i = 0; i < 27; i++) {
				controller.addNewElementIntoCanvasObject(cps.getID(), adapter.generate(i), 1, -100);
				assertTrue("Element:" + adapter.generate(i) + " was not Created",
						mp.searchEle((HolonObject) mp.searchByID(cps.getID()), adapter.generate(i)) != null);
			}
			assertTrue("Element:B was not Found", mp.searchEle((HolonObject) mp.searchByID(cps.getID()), "B") != null);
			assertTrue("Element:D was not Found", mp.searchEle((HolonObject) mp.searchByID(cps.getID()), "D") != null);
			assertTrue("Element:F was not Found", mp.searchEle((HolonObject) mp.searchByID(cps.getID()), "F") != null);
			assertTrue("Element:G was not Found", mp.searchEle((HolonObject) mp.searchByID(cps.getID()), "G") != null);
			assertTrue("Element:H was not Found", mp.searchEle((HolonObject) mp.searchByID(cps.getID()), "H") != null);
			assertTrue("Element:I was not Found", mp.searchEle((HolonObject) mp.searchByID(cps.getID()), "I") != null);
			assertTrue("Element:B was not Found", mp.searchEle((HolonObject) mp.searchByID(cps.getID()), "B") != null);
		}

		for (AbstractCpsObject cps : model.getObjectsOnCanvas()) {
			int size = model.getSelectedCpsObjects().size();
			controller.addSelectedObject(cps);
			assertTrue("Size does not Match", model.getSelectedCpsObjects().size() == size + 1);
		}
		for (AbstractCpsObject cps : model.getObjectsOnCanvas()) {
			System.out.println(model.getSelectedCpsObjects().size());
			int size = model.getSelectedCpsObjects().size();
			controller.deleteSelectedObject(cps);
			assertTrue("Size does not Match", model.getSelectedCpsObjects().size() == size - 1);
			assertTrue("Object was not unselected", !model.getSelectedCpsObjects().contains(cps));

		}
	}

}
