package tests;

import classes.AbstractCpsObject;
import classes.CpsEdge;
import classes.HolonObject;
import classes.HolonSwitch;
import classes.IdCounter;
import ui.controller.CanvasController;
import ui.controller.CategoryController;
import ui.controller.MultiPurposeController;
import ui.model.Model;

import org.junit.Test;
import org.junit.Before;
import static org.junit.Assert.assertTrue;

import java.awt.Point;
/**
 * Tests for the CanvasController.
 * 
 * @author Gruppe14
 */
public class PraktikumHolonsTestCanvasController {

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

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

	/**
	 * Tests adding objects.
	 */
	@Test
	public void testAddingObjects() {
		// just adding a few things
		assertTrue("Number of Objects does not Match", model.getObjectsOnCanvas().size() == 0);
		controller.addNewObject(new HolonObject(mp.searchCatObj(mp.searchCat("Energy"), "Power Plant")));
		assertTrue("ID of the Object does not Match", mp.searchByID(1).getName().equals("Power Plant"));
		assertTrue("Type of the Object does not Match", mp.searchByID(1) instanceof HolonObject);
		assertTrue("Number of Objects does not Match", model.getObjectsOnCanvas().size() == 1);
		controller.addNewObject(new HolonObject(mp.searchCatObj(mp.searchCat("Energy"), "Power Plant")));
		assertTrue("ID of the Object does not Match", mp.searchByID(2).getName().equals("Power Plant"));
		assertTrue("Type of the Object does not Match", mp.searchByID(2) instanceof HolonObject);
		assertTrue("Number of Objects does not Match", model.getObjectsOnCanvas().size() == 2);
		controller.addNewObject(new HolonObject(mp.searchCatObj(mp.searchCat("Energy"), "Power Plant")));
		assertTrue("ID of the Object does not Match", mp.searchByID(3).getName().equals("Power Plant"));
		assertTrue("Type of the Object does not Match", mp.searchByID(3) instanceof HolonObject);
		assertTrue("Number of Objects does not Match", model.getObjectsOnCanvas().size() == 3);
		controller.addNewObject(new HolonObject(mp.searchCatObj(mp.searchCat("Energy"), "Power Plant")));
		assertTrue("Number of Objects does not Match", model.getObjectsOnCanvas().size() == 4);
		controller.addNewObject(new HolonObject(mp.searchCatObj(mp.searchCat("Energy"), "Power Plant")));
		assertTrue("Number of Objects does not Match", model.getObjectsOnCanvas().size() == 5);
		controller.addNewObject(new HolonObject(mp.searchCatObj(mp.searchCat("Building"), "House")));
		assertTrue("ID of the Object does not Match", mp.searchByID(6).getName().equals("House"));
		assertTrue("Type of the Object does not Match", mp.searchByID(6) instanceof HolonObject);
		assertTrue("Number of Objects does not Match", model.getObjectsOnCanvas().size() == 6);
		controller.addNewObject(new HolonObject(mp.searchCatObj(mp.searchCat("Building"), "House")));
		assertTrue("Number of Objects does not Match", model.getObjectsOnCanvas().size() == 7);
		controller.addNewObject(new HolonObject(mp.searchCatObj(mp.searchCat("Building"), "House")));
		assertTrue("Number of Objects does not Match", model.getObjectsOnCanvas().size() == 8);
		controller.addNewObject(new HolonSwitch(mp.searchCatObj(mp.searchCat("Component"), "Switch")));
		assertTrue("ID of the Object does not Match", mp.searchByID(9).getName().equals("Switch"));
		assertTrue("Type of the Object does not Match", mp.searchByID(9) instanceof HolonSwitch);
		assertTrue("Number of Objects does not Match", model.getObjectsOnCanvas().size() == 9);
		controller.addNewObject(new HolonSwitch(mp.searchCatObj(mp.searchCat("Component"), "Switch")));
		assertTrue("Number of Objects does not Match", model.getObjectsOnCanvas().size() == 10);
	}
	
	/**
	 * Tests deleting Objects.
	 */
	@Test(expected = NullPointerException.class)
	public void testDeletingObject() {
		// Adding Objects on Canvas.. without Coordinates
		controller.addNewObject(new HolonObject(mp.searchCatObj(mp.searchCat("Energy"), "Power Plant")));
		controller.addNewObject(new HolonObject(mp.searchCatObj(mp.searchCat("Energy"), "Power Plant")));
		controller.addNewObject(new HolonObject(mp.searchCatObj(mp.searchCat("Building"), "House")));
		controller.addNewObject(new HolonObject(mp.searchCatObj(mp.searchCat("Energy"), "Power Plant")));
		controller.addNewObject(new HolonObject(mp.searchCatObj(mp.searchCat("Energy"), "Power Plant")));
		controller.addNewObject(new HolonObject(mp.searchCatObj(mp.searchCat("Building"), "House")));
		controller.addNewObject(new HolonSwitch(mp.searchCatObj(mp.searchCat("Component"), "Switch")));
		controller.addNewObject(new HolonObject(mp.searchCatObj(mp.searchCat("Energy"), "Power Plant")));
		controller.addNewObject(new HolonObject(mp.searchCatObj(mp.searchCat("Building"), "House")));
		controller.addNewObject(new HolonSwitch(mp.searchCatObj(mp.searchCat("Component"), "Switch")));

		controller.deleteObjectOnCanvas(mp.searchByID(4));
		assertTrue("Object:4 was not deleted", mp.searchByID(4) == null);
		assertTrue("Number of Objects does not Match", model.getObjectsOnCanvas().size() == 9);
		controller.deleteObjectOnCanvas(mp.searchByID(5));
		assertTrue("Object:4 was not deleted", mp.searchByID(5) == null);
		assertTrue("Number of Objects does not Match", model.getObjectsOnCanvas().size() == 8);
		controller.deleteObjectOnCanvas(mp.searchByID(6));
		assertTrue("Object:4 was not deleted", mp.searchByID(6) == null);
		assertTrue("Number of Objects does not Match", model.getObjectsOnCanvas().size() == 7);

		// deleting Non-Existant Object -> NullPointerexception
		controller.deleteObjectOnCanvas(mp.searchByID(4));
	}

	/**
	 * Tests adding and deleting Edges.
	 */
	@Test
	public void testAddingAndDeletingEdges() {
		HolonObject a = new HolonObject("A");
		controller.addNewObject(new HolonObject(a));
		int n = 0;

		// creates vertices A - Z
		for (int i = 2; i < 27; i++) {
			// adds Object on canvas
			HolonObject temp = new HolonObject(adapter.generate(i));
			controller.addNewObject(new HolonObject(temp));
			// connect current vertice with all other vertices
			for (AbstractCpsObject cps : model.getObjectsOnCanvas()) {
				if (!cps.equals(mp.searchByID(i)))
					controller.addEdgeOnCanvas(new CpsEdge(mp.searchByID(i), cps));
			}

			// test how many connections current vertice got
			assertTrue("Number of Connections does not Match", mp.searchByID(i).getConnectedTo().size() == i - 1);
			// actually just means if its a
			// complete graph -> all vertices connected all other vertices
			n = model.getObjectsOnCanvas().size();
			assertTrue("Number of Edges does not Match", model.getEdgesOnCanvas().size() == (n * (n - 1)) / 2);
		}
		// same as above
		n = model.getObjectsOnCanvas().size();
		assertTrue("Number of Edges does not Match", model.getEdgesOnCanvas().size() == (n * (n - 1)) / 2);

		// here starts the deleting
		controller.removeEdgesOnCanvas(mp.searchEdge(13, 14));
		assertTrue("Number of Connection of Vertice M does not Match",
				mp.searchByID(13).getConnections().size() == model.getObjectsOnCanvas().size() - 2);
		assertTrue("Edge-M-N was not deleted", mp.searchEdge(13, 14) == null);

		controller.deleteObjectOnCanvas(mp.searchByID(13));
		assertTrue("Object:13 was not deleted", mp.searchByID(13) == null);
		assertTrue("Edge-A-M was not deleted", mp.searchEdge(1, 13) == null);
		assertTrue("Edge-B-M was not deleted", mp.searchEdge(2, 13) == null);
		assertTrue("Edge-C-M was not deleted", mp.searchEdge(3, 13) == null);
		assertTrue("Edge-D-M was not deleted", mp.searchEdge(4, 13) == null);
		assertTrue("Edge-E-M was not deleted", mp.searchEdge(5, 13) == null);
		assertTrue("Edge-F-M was not deleted", mp.searchEdge(6, 13) == null);
		assertTrue("Edge-M-O was not deleted", mp.searchEdge(13, 16) == null);
		assertTrue("Edge-M-P was not deleted", mp.searchEdge(13, 17) == null);
		assertTrue("Edge-M-Q was not deleted", mp.searchEdge(13, 18) == null);
		assertTrue("Edge-M-R was not deleted", mp.searchEdge(13, 19) == null);
		assertTrue("Edge-M-S was not deleted", mp.searchEdge(13, 20) == null);
	}
	
	/**
	 * Test copying, cutting and pasting Objects.
	 */
	@Test
	public void testCutCopyPasteObjects() {
		HolonObject a = new HolonObject("A");
		HolonObject b = new HolonObject("B"); 
		HolonObject c = new HolonObject("C"); 
		
		a = new HolonObject(a);
		a.setPosition(1, 1);
		b = new HolonObject(b);
		b.setPosition(2, 2);
		c = new HolonObject(c);
		c.setPosition(3, 3);
		CpsEdge edge1 = new CpsEdge(a, b);
		CpsEdge edge2 = new CpsEdge(b, c);
		CpsEdge edge3 = new CpsEdge(c, a);
		controller.addNewObject(a);
		controller.addEdgeOnCanvas(edge1);
		controller.addEdgeOnCanvas(edge2);
		controller.addEdgeOnCanvas(edge3);

		
		assertTrue("Clipboard not empty", model.getClipboradObjects().isEmpty());
		model.getSelectedCpsObjects().add(a);
		model.getSelectedCpsObjects().add(b);
		model.getSelectedCpsObjects().add(c);
		controller.copyObjects();
		assertTrue("Clipboard empty", !model.getClipboradObjects().isEmpty());
	
		assertTrue("Clipboard empty", !model.getClipboradObjects().isEmpty());
		
		controller.pasteObjects(new Point(1, 1));
		
		controller.addNewObject(a);
		controller.addNewObject(b);
		controller.addNewObject(c);
		controller.cutObjects();
		
	}
}
