package gov.va.vinci.dart;

import gov.va.vinci.dart.biz.Request;
import gov.va.vinci.dart.common.SingletonShim;
import gov.va.vinci.dart.common.json.ErrorView;
import gov.va.vinci.dart.common.test.BusinessIntegrationTest;
import gov.va.vinci.dart.json.CommentIdView;
import gov.va.vinci.dart.json.CommentListView;
import gov.va.vinci.dart.json.CommentView;
import gov.va.vinci.dart.json.CreateActivityView;
import gov.va.vinci.dart.json.NewActivityView;
import gov.va.vinci.dart.json.RequestIdView;
import gov.va.vinci.dart.json.SaveNewerCommentView;
import gov.va.vinci.dart.json.SaveReplyCommentView;
import gov.va.vinci.dart.service.DartObjectFactory;
import gov.va.vinci.dart.usr.CustomAuthentication;

import org.springframework.security.core.context.SecurityContextHolder;
import org.testng.Assert;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

public class TestCommunicationController extends BusinessIntegrationTest {

	@BeforeTest
	public void setup() {
		SingletonShim.getBean(DartObjectFactory.class);
		
		CustomAuthentication token = new CustomAuthentication("DNS", null, "password", "details", "principal");

		try {
			DartObjectFactory.getInstance().getUserManager().login(token);
			SecurityContextHolder.getContext().setAuthentication(token);
		} 
		catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Test
	public void testOne() throws Exception {

		CreateActivityView req = new CreateActivityView ();
		
		ActivityController ac = SingletonShim.getBean(ActivityController.class);
		req.setType(Request.DATA_ACCESS);
		req.setOfficialName("official name");
		
		// now see if we can create it correctly
		Object obj = ac.createActivity(req);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof NewActivityView);
		
		NewActivityView nav = (NewActivityView)obj;
		Assert.assertTrue(nav.getActivityId() > 0);
		Assert.assertTrue(nav.getRequestId() > 0);
		
		// now we have a request to work with

		CommunicationController cc = SingletonShim.getBean(CommunicationController.class);
		
		// try an illegal argument
		obj = cc.listCommentsByRequest(null);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof ErrorView);
		Assert.assertNotEquals(((ErrorView)obj).getMessage().get("text"), "OK");

		// try an illegal request id
		RequestIdView riv = new RequestIdView();
		riv.setRequestId(-1);

		obj = cc.listCommentsByRequest(riv);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof ErrorView);
		Assert.assertNotEquals(((ErrorView)obj).getMessage().get("text"), "OK");

		// try the new request with no comments
		riv.setRequestId(nav.getRequestId());
		obj = cc.listCommentsByRequest(riv);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof CommentListView);
		CommentListView clv = (CommentListView)obj;
		
		Assert.assertNotNull(clv.getComments());
		Assert.assertEquals(clv.getComments().size(), 0);

		// add a comment
		SaveNewerCommentView sncv = new SaveNewerCommentView();
		sncv.setRequestId(nav.getRequestId());
		sncv.setText("this is text");
		sncv.setTopic("topic");
		sncv.setUserId(1006);
		cc.saveNewComment(sncv);
		
		// did it save?
		riv.setRequestId(nav.getRequestId());
		obj = cc.listCommentsByRequest(riv);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof CommentListView);
		clv = (CommentListView)obj;
		
		Assert.assertNotNull(clv.getComments());
		Assert.assertEquals(clv.getComments().size(), 1);
		
		CommentView cv = clv.getComments().get(0);
		Assert.assertNotNull(cv);
		Assert.assertEquals(cv.getCommentText(), "this is text");
		Assert.assertEquals(cv.getShortText(), "this is text");
		Assert.assertEquals(cv.getRequestId(), nav.getRequestId());
		Assert.assertNotNull(cv.getReplies());
		Assert.assertEquals(cv.getReplies().size(), 0);
		
	}
	
	@Test
	public void testTwo() throws Exception {

		CreateActivityView req = new CreateActivityView ();
		
		ActivityController ac = SingletonShim.getBean(ActivityController.class);
		req.setType(Request.DATA_ACCESS);
		req.setOfficialName("official name");
		
		// now see if we can create it correctly
		Object obj = ac.createActivity(req);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof NewActivityView);
		
		NewActivityView nav = (NewActivityView)obj;
		Assert.assertTrue(nav.getActivityId() > 0);
		Assert.assertTrue(nav.getRequestId() > 0);
		
		// now we have a request to work with

		CommunicationController cc = SingletonShim.getBean(CommunicationController.class);
		
		// add a comment
		SaveNewerCommentView sncv = new SaveNewerCommentView();
		sncv.setRequestId(nav.getRequestId());
		sncv.setText("this is text");
		sncv.setTopic("topic");
		sncv.setUserId(1006);
		cc.saveNewComment(sncv);

		RequestIdView riv = new RequestIdView();
		riv.setRequestId(nav.getRequestId());
		obj = cc.listCommentsByRequest(riv);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof CommentListView);
		CommentListView clv = (CommentListView)obj;
		
		CommentView cv = clv.getComments().get(0);

		CommentIdView civ = new CommentIdView();
		civ.setCommentId(cv.getCommentId());
		
		obj = cc.getComment(civ);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof CommentView);
		
		cv = (CommentView)obj;
		Assert.assertEquals(cv.getCommentId(), civ.getCommentId());
		Assert.assertEquals(cv.getCommentText(), "this is text");
		
		// does getComment fail correctly?

		obj = cc.getComment(null);  // can't pass it a null
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof ErrorView);
		Assert.assertNotEquals(((ErrorView)obj).getMessage().get("text"), "OK");

		civ.setCommentId(-1);  // can't pass it an invalid comment id
		obj = cc.getComment(civ);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof ErrorView);
		Assert.assertNotEquals(((ErrorView)obj).getMessage().get("text"), "OK");

	}

	@Test
	public void testThree() throws Exception {

		CreateActivityView req = new CreateActivityView ();
		
		ActivityController ac = SingletonShim.getBean(ActivityController.class);
		req.setType(Request.DATA_ACCESS);
		req.setOfficialName("official name");
		
		// now see if we can create it correctly
		Object obj = ac.createActivity(req);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof NewActivityView);
		
		NewActivityView nav = (NewActivityView)obj;
		Assert.assertTrue(nav.getActivityId() > 0);
		Assert.assertTrue(nav.getRequestId() > 0);
		
		// now we have a request to work with

		CommunicationController cc = SingletonShim.getBean(CommunicationController.class);
		
		// add a comment
		SaveNewerCommentView sncv = new SaveNewerCommentView();
		sncv.setRequestId(nav.getRequestId());
		sncv.setText("this is text");
		sncv.setTopic("topic");
		sncv.setUserId(1006);
		cc.saveNewComment(sncv);

		// get the list of requests comments and find the one just saved as a way to get its comment id
		RequestIdView riv = new RequestIdView();
		riv.setRequestId(nav.getRequestId());
		obj = cc.listCommentsByRequest(riv);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof CommentListView);
		CommentListView clv = (CommentListView)obj;
		
		CommentView cv = clv.getComments().get(0);
		int commentId = cv.getCommentId();
		
		// does saveReplyComment fail correctly?
		obj = cc.saveReplyComment(null);  // can't pass a null
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof ErrorView);
		Assert.assertNotEquals(((ErrorView)obj).getMessage().get("text"), "OK");

		SaveReplyCommentView srcv = new SaveReplyCommentView();
		srcv.setCommentId(-1);
		
		obj = cc.saveReplyComment(srcv);  // can't pass an invalid comment id
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof ErrorView);
		Assert.assertNotEquals(((ErrorView)obj).getMessage().get("text"), "OK");
		
		srcv.setCommentId(commentId);
		srcv.setText("reply text");
		srcv.setUserId(1006);
		
		obj = cc.saveReplyComment(srcv);  // this should work
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof ErrorView);
		Assert.assertEquals(((ErrorView)obj).getMessage().get("text"), "OK");

		// look for the reply in the request comment list
		obj = cc.listCommentsByRequest(riv);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof CommentListView);
		clv = (CommentListView)obj;
		Assert.assertNotNull(clv.getComments());
		Assert.assertEquals(clv.getComments().size(), 1);  // only 1. the child comment is embedded in the result tree

		cv = clv.getComments().get(0);
		Assert.assertNotNull(cv);
		Assert.assertNotNull(cv.getReplies());
		Assert.assertEquals(cv.getReplies().size(), 1);
		
		CommentView cv2 = cv.getReplies().get(0);
		Assert.assertNotNull(cv2);
		Assert.assertEquals(cv2.getParentId(), cv.getCommentId());
	
		// create a reply to that reply

		srcv.setCommentId(cv2.getCommentId());
		srcv.setText("reply to reply text");
		srcv.setUserId(1006);
		
		obj = cc.saveReplyComment(srcv);  // this should work
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof ErrorView);
		Assert.assertEquals(((ErrorView)obj).getMessage().get("text"), "OK");

		// look for the reply in the request comment list
		obj = cc.listCommentsByRequest(riv);
		Assert.assertNotNull(obj);
		Assert.assertTrue(obj instanceof CommentListView);
		clv = (CommentListView)obj;
		Assert.assertNotNull(clv.getComments());
		Assert.assertEquals(clv.getComments().size(), 1);  // only 1. the child comment is embedded in the result tree

		cv = clv.getComments().get(0);
		Assert.assertNotNull(cv);
		Assert.assertNotNull(cv.getReplies());
		Assert.assertEquals(cv.getReplies().size(), 1);

		cv2 = cv.getReplies().get(0);
		Assert.assertNotNull(cv2);
		Assert.assertEquals(cv2.getParentId(), cv.getCommentId());

		CommentView cv3 = cv.getReplies().get(0);
		Assert.assertNotNull(cv3);
		Assert.assertEquals(cv3.getParentId(), cv.getCommentId());
		Assert.assertEquals(cv3, cv2);

		Assert.assertEquals(cv3.getShortText(), "reply text");

		Assert.assertNotNull(cv3.getReplies());
		Assert.assertEquals(cv3.getReplies().size(), 1);
		CommentView cv4 = cv3.getReplies().get(0);
		Assert.assertEquals(cv4.getParentId(), cv3.getCommentId());

		Assert.assertEquals(cv4.getShortText(), "reply to reply text");
	}
}
