package edu.northwestern.bioinformatics.studycalendar.restlets;

import edu.northwestern.bioinformatics.studycalendar.StudyCalendarValidationException;
import edu.northwestern.bioinformatics.studycalendar.dao.ActivityDao;
import edu.northwestern.bioinformatics.studycalendar.dao.PopulationDao;
import edu.northwestern.bioinformatics.studycalendar.domain.Activity;
import edu.northwestern.bioinformatics.studycalendar.domain.PlannedActivity;
import edu.northwestern.bioinformatics.studycalendar.domain.PlannedActivityLabel;
import edu.northwestern.bioinformatics.studycalendar.domain.Population;
import edu.northwestern.bioinformatics.studycalendar.domain.Study;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.restlet.data.Status;
import org.restlet.resource.Representation;
import org.restlet.resource.ResourceException;

import java.util.LinkedList;
import java.util.List;

/**
 * @author Rhett Sutphin
 */
public class PlannedActivityForm extends ValidatingForm {
    private Study study;
    private ActivityDao activityDao;
    private PopulationDao populationDao;

    public PlannedActivityForm(Representation entity, Study study, ActivityDao activityDao, PopulationDao populationDao) {
        super(entity);
        this.study = study;
        this.activityDao = activityDao;
        this.populationDao = populationDao;

        validatePresenceOf(FormParameters.DAY);
        validateIntegralityOf(FormParameters.DAY);
        validatePresenceOf(FormParameters.ACTIVITY_CODE);
        validatePresenceOf(FormParameters.ACTIVITY_SOURCE);
    }

    public PlannedActivity createDescribedPlannedActivity() throws ResourceException {
        throwForValidationFailureIfNecessary();
        Integer day = FormParameters.DAY.extractFirstAsIntegerFrom(this);
        Activity activity = findDescribedActivity();
        Population population = findDescribedPopulation();

        PlannedActivity newPlannedActivity = new PlannedActivity();
        newPlannedActivity.setDay(day);
        newPlannedActivity.setActivity(activity);
        newPlannedActivity.setPopulation(population);
        newPlannedActivity.setCondition(
            StringEscapeUtils.unescapeHtml(FormParameters.CONDITION.extractFirstFrom(this)));
        newPlannedActivity.setDetails(
            StringEscapeUtils.unescapeHtml(FormParameters.DETAILS.extractFirstFrom(this)));
        addDescribedLabels(newPlannedActivity);

        return newPlannedActivity;
    }

    private Activity findDescribedActivity() throws ResourceException {
        String activitySource = FormParameters.ACTIVITY_SOURCE.extractFirstFrom(this);
        String activityCode = FormParameters.ACTIVITY_CODE.extractFirstFrom(this);

        Activity activity = activityDao.getByCodeAndSourceName(activityCode, activitySource);
        if (activity == null) {
            throw new ResourceException(
                Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY, "Activity not found");
        }
        return activity;
    }

    private Population findDescribedPopulation() throws ResourceException {
        Population population = null;
        String populationAbbrev = FormParameters.POPULATION.extractFirstFrom(this);
        if (populationAbbrev != null) {
            population = populationDao.getByAbbreviation(study, populationAbbrev);
            if (population == null) {
                throw new ResourceException(
                    Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY, "Population not found");
            }
        }
        return population;
    }

    private void addDescribedLabels(PlannedActivity target) {
        for (String serializedPaLabel : this.getValuesArray(FormParameters.LABEL.attributeName())) {
            if (!StringUtils.isBlank(serializedPaLabel)) {
                addDescribedLabels(target, serializedPaLabel);
            }
        }
    }

    private void addDescribedLabels(PlannedActivity target, String serialized) {
        String labelText;
        List<Integer> reps = new LinkedList<Integer>();
        if (serialized.indexOf(';') >= 0) {
            String[] parts = serialized.split(";");
            labelText = parts[0];
            if (parts.length > 1 && !StringUtils.isBlank(parts[1])) {
                for (String n : parts[1].trim().split("\\s+")) {
                    try {
                        int i = Integer.parseInt(n);
                        if (i < 0) {
                            throw new StudyCalendarValidationException("The label '" + serialized + "' is invalid.  All rep numbers must be nonnegative integers.");
                        }
                        reps.add(i);
                    } catch (NumberFormatException nfe) {
                        throw new StudyCalendarValidationException("The label '" + serialized + "' is invalid.  All rep numbers must be nonnegative integers.", nfe);
                    }
                }
            } else {
                reps.add(null);
            }
        } else {
            labelText = serialized;
            reps.add(null);
        }
        for (Integer rep : reps) {
            PlannedActivityLabel newLabel = new PlannedActivityLabel();
            newLabel.setRepetitionNumber(rep);
            newLabel.setLabel(labelText);
            target.addPlannedActivityLabel(newLabel);
        }
    }
}

@@ -871,16 +871,73 @@
 ception;
+%0Aimport org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;
 %0A%0Aimport
@@ -981,16 +981,65 @@
 il.List;
+%0Aimport java.util.Set;%0Aimport java.util.Iterator;
 %0A%0A/**%0A *
@@ -1181,24 +1181,24 @@
 ctivityDao;%0A
-
     private 
@@ -1221,24 +1221,92 @@
 pulationDao;
+%0A    private final Logger log = LoggerFactory.getLogger(getClass());
 %0A%0A    public
@@ -3432,32 +3432,525 @@
 brev != null) %7B%0A
+            if (study.isInAmendmentDevelopment() %7C%7C study.isInDevelopment())%7B%0A                Set%3CPopulation%3E populations = study.getChildren();%0A                for (Iterator%3CPopulation%3E popIterator = populations.iterator(); popIterator.hasNext();) %7B%0A                    population = popIterator.next();%0A                    if (population.getAbbreviation().equals(populationAbbrev)) %7B%0A                        return population;%0A                    %7D%0A                %7D%0A            %7D else %7B%0A    
             popu
@@ -4016,16 +4016,30 @@
 bbrev);%0A
+            %7D%0A
         

Fix for #577 - fixing the problem with adding a newly created population to the activity for amended templates