/* $This file is distributed under the terms of the license in /doc/license.txt$ */

package edu.cornell.mannlib.vitro.webapp.controller.freemarker;

import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.PolicyOption.POLICY_NEUTRAL;

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

import com.fasterxml.jackson.databind.JsonNode;

import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup;
import stubs.edu.cornell.mannlib.vitro.webapp.dao.VClassGroupDaoStub;
import stubs.edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactoryStub;
import stubs.edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccessFactoryStub;
import stubs.javax.servlet.http.HttpServletRequestStub;

import java.util.Collections;

/**
 * Not a well-formed set of unit tests. But it's a pretty good exercise of the
 * different possibilities in the output stage.
 * 
 * Test plan:
 * 
 * <pre>
 * No data - roots is null -- NONSENSICAL
 * No data - roots is empty
 * 
 * name
 * no name
 * 
 * displayRank
 * no displayRank
 * 
 * no child classes
 * child classes
 * 
 * child class has name
 * child class has no name
 * 
 * child class has shortDef
 * child class has no shortDef
 * 
 * G1 no name, displayRank, no classes
 * G2 name, no displayRank, classes
 * G2C1 no name, no shortDef
 * G2C2 name, shortdef 
 * 
 * Try once with no data
 * Try with all data
 * </pre>
 */

public class ListClassGroupsControllerTest extends ListControllerTestBase {
	private static final String LINK_FORMAT_GROUP = "<a href='./editForm?uri=%s&amp;controller=Classgroup'>%s</a>";
	private static final String LINK_FORMAT_CLASS = "<a href='vclassEdit?uri=%s'>%s</a>";
	private static final String GROUP1 = "http://ont1/group1";
	private static final String GROUP2 = "http://ont1/group2";
	private static final String CLASS1 = "http://ont1/class1";
	private static final String CLASS2 = "http://ont1/class2";
	private static final String CLASS2_NAME = "The Second Class";
	private static final String CLASS2_SHORT_DEF = "A Marvelous Class";
	private static final int GROUP1_RANK = 5;
	private static final String GROUP2_NAME = "The Second Group";

	private static final JsonNode JSON_EMPTY_RESPONSE = arrayOf();

	private static final JsonNode JSON_FULL_RESPONSE = arrayOf(
			groupListNode(LINK_FORMAT_GROUP, GROUP1, "(unnamed group)",
					"" + GROUP1_RANK),
			groupListNode(LINK_FORMAT_GROUP, GROUP2, GROUP2_NAME, "",
					groupMemberNode("", "", "", ""),
					groupMemberNode(LINK_FORMAT_CLASS, CLASS2, CLASS2_NAME,
							CLASS2_SHORT_DEF)));

	private ListClassGroupsController controller;
	private HttpServletRequestStub req;
	private ModelAccessFactoryStub modelsFactory;
	private WebappDaoFactoryStub wadf;
	private VClassGroupDaoStub vcgDao;

	@Before
	public void setup() {
		controller = new ListClassGroupsController();

		req = new HttpServletRequestStub();

		vcgDao = new VClassGroupDaoStub();

		wadf = new WebappDaoFactoryStub();
		wadf.setVClassGroupDao(vcgDao);

		modelsFactory = new ModelAccessFactoryStub();
		modelsFactory.get(req).setWebappDaoFactory(wadf, POLICY_NEUTRAL);
	}

	// ----------------------------------------------------------------------
	// The tests
	// ----------------------------------------------------------------------

	@Test
	public void noData() throws Exception {
		assertMatchingJson(controller, req, JSON_EMPTY_RESPONSE);
	}

	@Test
	public void basicJsonTest() throws Exception {
		populate();

		/*
		 * The controller attempts to handle the case of a class with no name,
		 * but instead it returns invalid json.
		 */
		String rawResponse = getJsonFromController(controller, req);
		String kluged = rawResponse.replace("[\"\"", "[ {\"name\": \"\"");
		assertKlugedJson(JSON_FULL_RESPONSE, kluged);

		// assertMatchingJson(controller, req, JSON_FULL_RESPONSE);
	}

	// ----------------------------------------------------------------------
	// Helper methods
	// ----------------------------------------------------------------------

	private void populate() {
		vcgDao.setGroups(vClassGroup(GROUP1, null, GROUP1_RANK),
				vClassGroup(GROUP2, GROUP2_NAME, -1, vclass(CLASS1, null, null),
						vclass(CLASS2, CLASS2_NAME, CLASS2_SHORT_DEF)));

	}

	private VClassGroup vClassGroup(String uri, String name, int rank,
			VClass... vClasses) {
		VClassGroup group = new VClassGroup(uri, name, rank);
		Collections.addAll(group, vClasses);
		return group;
	}

	private VClass vclass(String uri, String name, String shortDef) {
		VClass vc = new VClass(uri);
		vc.setName(name);
		vc.setShortDef(shortDef);
		return vc;
	}

}
