package tests;

import static org.junit.Assert.*;

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

import classes.HolonObject;
import ui.controller.CategoryController;
import ui.controller.MultiPurposeController;
import ui.model.Model;

/**
 * Tests for the CategoryController.
 * 
 * @author Gruppe14
 */
public class PraktikumHolonsTestCategoryController {

	protected PraktikumHolonsAdapter adapter;
	protected Model model;
	protected MultiPurposeController mp;
	protected CategoryController controller;

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

	/**
	 * tests for the Initial Categories.
	 */
	@Test
	public void testInitialCategories() {
		assertTrue("Number of Categories is not 3", model.getCategories().size() == 3);
		assertTrue("Second Category is not Building", model.getCategories().get(1).getName().equals("Building"));
		assertTrue("Category Building is Empty", !model.getCategories().get(1).getObjects().isEmpty());
		assertEquals("Object is not a Power Plant", mp.searchCat("Energy").getObjects().get(0).getObjName(),
				"Power Plant");
		assertFalse("A Switch should not be a Holon Object",
				mp.searchCatObj(mp.searchCat("Component"), "Switch") instanceof HolonObject);
	}

	/**
	 * Basic tests for adding new Categories.
	 */
	@Test
	public void testAddingCategoriesMinimal() {
		controller.addNewCategory("University");
		controller.addNewCategory("Hospital");
		assertTrue("Number of Categories is not 5", model.getCategories().size() == 5);
		controller.addNewCategory("Energy");
		assertTrue("Number of Categories is not 6", model.getCategories().size() == 6);
		assertTrue("Name of the Duplicate: Energy was not changed to Energy_0",
				model.getCategories().get(5).getName().equals("Energy_0"));
		controller.addNewCategory("Energy");
		assertTrue("Number of Categories is not 7", model.getCategories().size() == 7);
		assertTrue("Name of the Duplicate: Energy was not changed to Energy_1",
				model.getCategories().get(6).getName().equals("Energy_1"));
	}

	/**
	 * Basic tests for deleting Categories.
	 */
	@Test
	public void testDeletingCategoriesMinimal() {
		assertTrue("Number of Categories is not 3", model.getCategories().size() == 3);
		assertTrue("2nd Category does not Match", model.getCategories().get(1).getName().equals("Building"));
		controller.deleteCategory("Building");
		assertTrue("Number of Categories is not 2", model.getCategories().size() == 2);
		assertTrue("Former 2nd Category was not deleted", model.getCategories().get(1).getName().equals("Component"));
		controller.deleteCategory("Energy");
		assertTrue("Number of Categories is not 1", model.getCategories().size() == 1);
		assertTrue("1st Category was not Component", model.getCategories().get(0).getName().equals("Component"));
	}

	/**
	 * Extended tests for adding and deleting Categories.
	 */
	@Test
	public void testAddingAndDeletingCategoriesExtended() {
		for (int i = 1; i <= 50; i++) {
			controller.addNewCategory(adapter.generate(i));
			assertTrue("Catagory:" + adapter.generate(i) + " was not added", model.getCategories().size() == i + 3);
		}

		assertEquals("Category does not match", model.getCategories().get(29).getName(), "AA");
		controller.deleteCategory("AA");
		assertTrue("Catagory:AA was not deleted", model.getCategories().size() == 52);
		assertEquals("Category does not match", model.getCategories().get(29).getName(), "AB");
		assertEquals("Category does not match", model.getCategories().get(30).getName(), "AC");
		controller.deleteCategory("AB");
		assertTrue("Catagory:AB was not deleted", model.getCategories().size() == 51);
		assertEquals("Category does not match", model.getCategories().get(29).getName(), "AC");
		controller.deleteCategory("AD");
		assertTrue("Catagory:AD was not deleted", model.getCategories().size() == 50);
		assertEquals("Category does not match", model.getCategories().get(29).getName(), "AC");
		assertEquals("Category does not match", model.getCategories().get(30).getName(), "AE");
		controller.deleteCategory("Energy");
		assertTrue("Catagory:Energy was not deleted", model.getCategories().size() == 49);

		for (int i = 1; i <= 10; i++) {
			controller.deleteCategory(adapter.generate(i));
			assertTrue("Catagory was not deleted", model.getCategories().size() == 49 - i);
		}
		assertEquals("Category does not match", model.getCategories().get(3).getName(), "L");
	}

	/**
	 * Basic tests for adding and deleting Objects.
	 */
	@Test
	public void testAddingAndDeletingObjectsMinimal() {
		controller.addNewHolonObject(mp.searchCat("Energy"), "Power Plant", null, "");
		controller.addNewHolonObject(mp.searchCat("Energy"), "Power Plant", null, "");
		controller.addNewHolonObject(mp.searchCat("Energy"), "Solar Plant", null, "");

		assertTrue("Number of Objects in Energy is not 4", mp.searchCat("Energy").getObjects().size() == 4);
		assertTrue("Number of Object-Indices in Energy is not 4", mp.searchCat("Energy").getObjIdx().size() == 4);
		assertTrue("Object was not renamed to \"Power Plant_0\" ",
				mp.searchCat("Energy").getObjects().get(1).getObjName().equals("Power Plant_0"));
		assertTrue("Object was not renamed to \"Power Plant_1\" ",
				mp.searchCat("Energy").getObjects().get(2).getObjName().equals("Power Plant_1"));
		assertTrue("3th Object was not \"Power Plant_1\"",
				mp.searchCat("Energy").getObjects().get(2).getName().equals("Power Plant_1"));
		controller.deleteObject("Energy", "Power Plant_1");
		assertTrue("3th Object was not deleted",
				mp.searchCat("Energy").getObjects().get(2).getName().equals("Solar Plant"));
		assertTrue("Number of Objects in Energy is not 3", mp.searchCat("Energy").getObjects().size() == 3);
		controller.addNewHolonObject(mp.searchCat("Energy"), "Solar Plant", null, "");
		assertTrue("Object was not renamed to \"Solar Plant_0\" ",
				mp.searchCat("Energy").getObjects().get(3).getObjName().equals("Solar Plant_0"));
		assertTrue("Number of Objects in Energy is not 4", mp.searchCat("Energy").getObjects().size() == 4);
	}

	/**
	 * Extended tests for adding and deleting Objects.
	 */
	@Test
	public void testAddingAndDeletingObjectsExtended() {

		for (int i = 1; i <= 25; i++) {
			controller.addNewHolonObject(mp.searchCat("Energy"), adapter.generate(i), null, null);
			//creating duplicates
			controller.addNewHolonObject(mp.searchCat("Energy"), adapter.generate(i), null, null);

			assertTrue("Objects were not added", mp.searchCat("Energy").getObjects().size() == i * 2 + 1);

			assertTrue("Object was not renamed to \"" + adapter.generate(i) + "_0\"", mp.searchCat("Energy")
					.getObjects().get(i * 2).getObjName().equals(adapter.generate(i) + "_0"));
		}
		//deleting the duplicates
		controller.deleteObject("Energy", "E_0");
		assertTrue("Object was not deleted", mp.searchCatObj(mp.searchCat("Energy"), "E_0") == null);
		controller.deleteObject("Energy", "F_0");
		assertTrue("Object was not deleted", mp.searchCatObj(mp.searchCat("Energy"), "F_0") == null);
		controller.deleteObject("Energy", "G_0");
		assertTrue("Object was not deleted", mp.searchCatObj(mp.searchCat("Energy"), "G_0") == null);
		controller.deleteObject("Energy", "H_0");
		assertTrue("Object was not deleted", mp.searchCatObj(mp.searchCat("Energy"), "H_0") == null);
		assertTrue("Number of Objects does not match", mp.searchCat("Energy").getObjects().size() == 47);
	}
}
