package edu.northwestern.bioinformatics.studycalendar.web.template;

import edu.northwestern.bioinformatics.studycalendar.domain.*;
import edu.northwestern.bioinformatics.studycalendar.domain.delta.PropertyChange;
import static edu.northwestern.bioinformatics.studycalendar.domain.Fixtures.createNamedInstance;
import edu.northwestern.bioinformatics.studycalendar.dao.PeriodDao;
import edu.northwestern.bioinformatics.studycalendar.dao.PlannedActivityDao;
import edu.northwestern.bioinformatics.studycalendar.service.AmendmentService;
import static org.easymock.EasyMock.expect;

import java.util.List;
import java.util.ArrayList;
import java.util.Map;

public class UpdatePeriodCommandTest  extends EditCommandTestCase {
    private UpdatePeriodCommand command = new UpdatePeriodCommand();
    private Period period;
    private PeriodDao periodDao;
    private PlannedActivityDao plannedActivityDao;
    public int PERIOD_ID = 10;
    public AmendmentService amendmentService;
    public Activity activity;
    public String periodDetails;

    public String detailsToChange;
    public String eventDetails;
    public String eventConditionalDetails;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        periodDao = registerMockFor(PeriodDao.class);
        plannedActivityDao = registerMockFor(PlannedActivityDao.class);
        amendmentService = registerMockFor(AmendmentService.class);

        activity = createNamedInstance("Three", Activity.class);
        activity.setId(3);
        periodDetails = "DETAILS";

        detailsToChange = "New event details";
        eventDetails = "Event details";
        eventConditionalDetails = "Event conditional details";        

        period = new Period();
        period.setName("period");
        period.setStartDay(13);
        period.getDuration().setQuantity(7);
        period.getDuration().setUnit(Duration.Unit.day);
        period.setId(PERIOD_ID);

        command.setPeriodDao(periodDao);
        command.setPlannedActivityDao(plannedActivityDao);
        command.setAmendmentService(amendmentService);
    }

    public void testPerformEditOnDetails() throws Exception {
        command.setId(period.getId());
        PlannedActivity eventOne = createPlannedActivity(1, 25);
        eventOne.setId(21);
        eventOne.setDetails(eventDetails);
        period.addPlannedActivity(eventOne);

        List<Integer> ids = new ArrayList<Integer>();
        ids.add(eventOne.getId());
        command.setEventIds(ids);
        command.setDetails(detailsToChange);
        command.setColumnNumber(-1);
        
        expect(periodDao.getById(PERIOD_ID)).andReturn(period).anyTimes();
        expect(plannedActivityDao.getById(21)).andReturn(eventOne);

        amendmentService.updateDevelopmentAmendment(eventOne,
            PropertyChange.create("details", eventDetails, detailsToChange));

        replayMocks();
        command.performEdit();
        verifyMocks();
        
        assertEquals(1, period.getPlannedActivities().size());
        assertEquals("Details should not be updated in place", eventDetails, command.getPeriod().getPlannedActivities().get(0).getDetails());
    }

    public void testPerformEditOnConditionalDetails() throws Exception {
        command.setId(period.getId());
        PlannedActivity eventOne = createPlannedActivity(1, 25);
        eventOne.setId(21);
        eventOne.setCondition(eventConditionalDetails);
        period.addPlannedActivity(eventOne);

        List<Integer> ids = new ArrayList<Integer>();
        ids.add(eventOne.getId());
        command.setEventIds(ids);
        command.setConditionalDetails(detailsToChange);
        command.setConditionalUpdated(true);
        command.setColumnNumber(0);

        expect(periodDao.getById(PERIOD_ID)).andReturn(period).anyTimes();
        expect(plannedActivityDao.getById(21)).andReturn(eventOne);

        amendmentService.updateDevelopmentAmendment(eventOne,
            PropertyChange.create("condition", eventConditionalDetails, detailsToChange));

        replayMocks();
        command.performEdit();
        verifyMocks();

        assertEquals(1, period.getPlannedActivities().size());
        assertEquals("Details should not be updated in place", eventConditionalDetails, command.getPeriod().getPlannedActivities().get(0).getCondition());
    }

    public void testGetLocalModelWithDetails() throws Exception {
        PlannedActivity eventTwo = createPlannedActivity(2, 26);
        eventTwo.setId(22);
        command.setDetails(eventDetails);
        period.addPlannedActivity(eventTwo);
        expect(periodDao.getById(PERIOD_ID)).andReturn(period).anyTimes();
        command.setId(period.getId());
        command.setColumnNumber(-1);
        command.setRowNumber(3);

        replayMocks();

        Map<String, Object> map = command.getLocalModel();
        verifyMocks();

        assertNotNull("Map is null", map);
        assertEquals("Map's details is wrong", eventDetails, map.get("details"));
        assertEquals("Map's column number is wrong", -1, map.get("columnNumber"));
        assertEquals("Map's row number is wrong", 3, map.get("rowNumber"));
     }

    public void testGetLocalModelWithConditionalDetails() throws Exception {
        PlannedActivity eventTwo = createPlannedActivity(2, 26);
        eventTwo.setId(22);
        command.setConditionalDetails(eventConditionalDetails);
        command.setConditionalUpdated(true);
        period.addPlannedActivity(eventTwo);
        expect(periodDao.getById(PERIOD_ID)).andReturn(period).anyTimes();
        command.setId(period.getId());
        command.setColumnNumber(1);
        command.setRowNumber(3);

        replayMocks();

        Map<String, Object> map = command.getLocalModel();
        verifyMocks();
        System.out.println("map " + map);
        assertNotNull("Map is null", map);
        assertEquals("Map's details is wrong", eventConditionalDetails, map.get("conditionalDetails"));
        assertEquals("Map's column number is wrong", 1, map.get("columnNumber"));
        assertEquals("Map's row number is wrong", 3, map.get("rowNumber"));
     }

    private PlannedActivity createPlannedActivity(int day, Integer id) {
        return createPlannedActivity(day, null, id, null);
    }

    private PlannedActivity createPlannedActivity(
        int day, String details, Integer id, String conditionalDetails
    ) {
        PlannedActivity evt = Fixtures.createPlannedActivity(activity.getName(), day);
        evt.setId(id);
        evt.setActivity(activity);
        evt.setDetails(details);
        evt.setCondition(conditionalDetails);
        return evt;
    }

}


@@ -715,16 +715,62 @@
 tCase %7B%0A
+    private static final int PERIOD_ID = 10;%0A%0A
     priv
@@ -950,44 +950,14 @@
    p
-ublic int PERIOD_ID = 10;%0A    public
+rivate
  Ame
@@ -993,21 +993,22 @@
 e;%0A    p
-ublic
+rivate
  Activit
@@ -1023,52 +1023,20 @@
 ty;%0A
+%0A
     p
-ublic String periodDetails;%0A%0A    public
+rivate
  Str
@@ -1057,29 +1057,30 @@
 hange;%0A    p
-ublic
+rivate
  String even
@@ -1094,21 +1094,22 @@
 s;%0A    p
-ublic
+rivate
  String 
@@ -1237,32 +1237,35 @@
 odDao = register
+Dao
 MockFor(PeriodDa
@@ -1303,32 +1303,35 @@
 tyDao = register
+Dao
 MockFor(PlannedA
@@ -1513,43 +1513,8 @@
 (3);
-%0A        periodDetails = %22DETAILS%22;
 %0A%0A  

Change mock registration in an effort to avoid OOME on hudson; misc style cleanup