package com.metservice.kanban.web;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;
import com.metservice.kanban.EstimatesDao;
import com.metservice.kanban.KanbanService;
import com.metservice.kanban.model.EstimatesProject;
import com.metservice.kanban.model.KanbanProject;
import com.metservice.kanban.model.WorkItem;
//TODO This class needs unit tests.
@Controller
@RequestMapping("{projectName}")
public class EstimatesController {
private static final Logger LOGGER = LoggerFactory.getLogger(EstimatesController.class);
private static final String ESTIMATES_PROJECT_ATTR = "estimatesproject";
private static final String KANBAN_PROJECT_ATTR = "project";
private static final String ESTIMATES_JSP = "estimates.jsp";
private static final String ESTIMATES_FEATURE_JSP = "petfeature.jsp";
@Autowired
EstimatesDao estimatesDao;
@Autowired
KanbanService kanbanService;
@ModelAttribute(ESTIMATES_PROJECT_ATTR)
public synchronized EstimatesProject populateEstimatesProject(@PathVariable("projectName") String projectName) throws IOException {
EstimatesProject project = estimatesDao.loadProject(projectName);
return project;
}
@ModelAttribute(KANBAN_PROJECT_ATTR)
public synchronized KanbanProject populateProject(@PathVariable("projectName") String projectName)
throws IOException {
return kanbanService.getKanbanProject(projectName);
}
@ModelAttribute("projectName")
public String populateProjectName(@PathVariable("projectName") String bprojectName) {
return bprojectName;
}
@RequestMapping("estimates")
public ModelAndView showProject(@ModelAttribute(ESTIMATES_PROJECT_ATTR) EstimatesProject estimatesProject) {
Map<String, Object> model = new HashMap<String, Object>();
return new ModelAndView(ESTIMATES_JSP, model);
}
@ModelAttribute("service")
public synchronized KanbanService populateService()
throws IOException {
return kanbanService;
}
@RequestMapping("pet-set-project-property")
public RedirectView setBudget(String name, int value,
@ModelAttribute(ESTIMATES_PROJECT_ATTR) EstimatesProject project)
throws IOException {
if ("budget".equals(name)) {
project.setBudget(value);
} else if ("estimatedCostPerPoint".equals(name)) {
project.setEstimatedCostPerPoint(value);
} else {
throw new IllegalArgumentException("name = " + name);
}
estimatesDao.storeProjectEstimates(project);
return new RedirectView("estimates");
}
@RequestMapping("pet-edit-feature")
public ModelAndView editFeature(int id, @ModelAttribute(ESTIMATES_PROJECT_ATTR) EstimatesProject project) {
Map<String, Object> model = new HashMap<String, Object>();
model.put("pageTitle", "Edit feature");
model.put("feature", project.getFeature(id));
return new ModelAndView(ESTIMATES_FEATURE_JSP, model);
}
@RequestMapping("pet-save-feature")
public RedirectView saveFeature(int id, int averageCaseEstimate, int worstCaseEstimate,
@ModelAttribute(ESTIMATES_PROJECT_ATTR) EstimatesProject project)
throws IOException {
Assert.isTrue(id != 0);
// get WI for feature
WorkItem workItem = project.getKanbanProject().getWorkItemById(id);
// update WI from feature
workItem.setAverageCaseEstimate(averageCaseEstimate);
workItem.setWorstCaseEstimate(worstCaseEstimate);
estimatesDao.storeUpdatedFeatures(project);
return new RedirectView("estimates");
}
@RequestMapping("pet-set-feature-included-in-estimates")
public RedirectView excludeFeature(int id, boolean value,
@ModelAttribute(ESTIMATES_PROJECT_ATTR) EstimatesProject project)
throws IOException {
boolean includedInEstimates = value;
WorkItem feature = project.getKanbanProject().getWorkItemById(id);
feature.setMustHave(includedInEstimates);
estimatesDao.storeUpdatedFeatures(project);
return new RedirectView("estimates");
}
@RequestMapping("pet-move-feature")
public RedirectView moveFeature(int id, int targetId, String direction,
@ModelAttribute(ESTIMATES_PROJECT_ATTR) EstimatesProject project)
throws IOException {
boolean after = "down".equals(direction);
project.getKanbanProject().move(id, targetId, after);
project.getKanbanProject().save();
return new RedirectView("estimates");
}
@RequestMapping(value = "estimates-cost-daily-save", produces = "application/json", consumes = "application/json")
@ResponseBody
public JsonStatus saveDailyCosts(@ModelAttribute(ESTIMATES_PROJECT_ATTR) EstimatesProject project,
@RequestBody Data[] data) throws IOException {
Map<LocalDate, Integer> dailyCosts = new TreeMap<LocalDate, Integer>();
for (Data d : data) {
if (StringUtils.isNotEmpty(d.cost) && StringUtils.isNotEmpty(d.date)) {
try {
LocalDate date = LocalDate.parse(d.date);
Integer cost = Integer.parseInt(d.cost);
dailyCosts.put(date, cost);
} catch (Exception e) {
LOGGER.warn("Error parsing data for daily costs date = {}, cost = {}, skipping this value", d.date,
d.cost);
LOGGER.warn("Got exception", e);
}
}
}
project.setDayCosts(dailyCosts);
estimatesDao.storeProjectEstimates(project);
return JsonStatus.createOkStatus();
}
public static class Data {
public String date;
public String cost;
public Data(String date, String cost) {
this.date = date;
this.cost = cost;
}
public Data() {
}
}
}