package net.rrm.ehour.ui.manage.assignment.form;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import net.rrm.ehour.customer.service.CustomerService;
import net.rrm.ehour.domain.Customer;
import net.rrm.ehour.domain.Project;
import net.rrm.ehour.project.service.ProjectService;
import net.rrm.ehour.report.criteria.Sort;
import net.rrm.ehour.sort.CustomerComparator;
import net.rrm.ehour.sort.ProjectComparator;
import net.rrm.ehour.ui.common.component.*;
import net.rrm.ehour.ui.common.event.AjaxEvent;
import net.rrm.ehour.ui.common.event.AjaxEventType;
import net.rrm.ehour.ui.common.event.EventPublisher;
import net.rrm.ehour.ui.common.panel.AbstractBasePanel;
import net.rrm.ehour.ui.manage.assignment.AssignmentAdminBackingBean;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.markup.html.form.AbstractChoice;
import org.apache.wicket.markup.html.form.ChoiceRenderer;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class AssignmentProjectSelectionPanel extends AbstractBasePanel<AssignmentAdminBackingBean> {
private static final long serialVersionUID = 5513770467507708949L;
private AjaxFormComponentFeedbackIndicator projectValidationErrorIndicator;
public enum EntrySelectorAjaxEventType implements AjaxEventType {
PROJECT_CHANGE
}
@SpringBean
private CustomerService customerService;
@SpringBean
private ProjectService projectService;
public AssignmentProjectSelectionPanel(String id, IModel<AssignmentAdminBackingBean> model) {
super(id, model);
addCustomerAndProjectChoices();
}
@SuppressWarnings("serial")
private void addCustomerAndProjectChoices() {
List<Customer> customers = getCustomers();
// customer
final DropDownChoice<Customer> customerChoice = createCustomerDropdown(customers);
// project model
final IModel<List<Project>> projectChoices = new AbstractReadOnlyModel<List<Project>>() {
@SuppressWarnings("unchecked")
@Override
public List<Project> getObject() {
// need to re-get it, project set is lazy
Customer selectedCustomer = getPanelModelObject().getCustomer();
Customer customer;
List<Project> projects;
if (selectedCustomer != null) {
customer = customerService.getCustomer(selectedCustomer.getCustomerId());
if (customer == null || customer.getProjects() == null || customer.getProjects().isEmpty()) {
projects = Lists.newArrayList();
} else {
projects = Lists.newArrayList(customer.getActiveProjects());
}
} else {
projects = projectService.getActiveProjects();
}
Collections.sort(projects, new ProjectComparator(Sort.PARENT_CODE_FIRST));
return projects;
}
};
final AbstractChoice<?, Project> projectChoice = createProjectChoice(projectChoices);
add(projectChoice);
projectValidationErrorIndicator = new AjaxFormComponentFeedbackIndicator("projectValidationError", projectChoice);
projectValidationErrorIndicator.setOutputMarkupId(true);
add(projectValidationErrorIndicator);
// make project update automatically when customers changed
customerChoice.add(new AjaxFormComponentUpdatingBehavior("change") {
@Override
protected void onUpdate(AjaxRequestTarget target) {
final AbstractChoice<?, Project> updatedProjectChoice = createProjectChoice(projectChoices);
AssignmentProjectSelectionPanel.this.addOrReplace(updatedProjectChoice);
target.add(updatedProjectChoice);
projectValidationErrorIndicator.setIndicatorFor(updatedProjectChoice);
}
});
}
private AbstractChoice<?, Project> createProjectChoice(IModel<List<Project>> projectChoices) {
final AbstractChoice<?, Project> projectChoice = createProjectChoiceDropDown("projectAssignment.project", projectChoices, new ProjectRenderer(createProjectToCustomerMap(projectChoices)));
projectChoice.setRequired(true);
projectChoice.setOutputMarkupId(true);
projectChoice.setLabel(new ResourceModel("admin.assignment.project"));
projectChoice.add(new ValidatingFormComponentAjaxBehavior());
projectChoice.add(new AjaxFormComponentUpdatingBehavior("change") {
@Override
protected void onUpdate(AjaxRequestTarget target) {
AjaxEvent ajaxEvent = new AjaxEvent(EntrySelectorAjaxEventType.PROJECT_CHANGE);
EventPublisher.publishAjaxEvent(AssignmentProjectSelectionPanel.this, ajaxEvent);
}
});
projectChoice.add(new ValidatingFormComponentAjaxBehavior());
return projectChoice;
}
private List<Customer> getCustomers() {
List<Customer> customers = customerService.getActiveCustomers();
List<Customer> customersWithActiveProjects = Lists.newArrayList();
for (Customer customer : customers) {
if (!customer.getActiveProjects().isEmpty()) {
customersWithActiveProjects.add(customer);
}
}
Collections.sort(customersWithActiveProjects, new CustomerComparator());
return customersWithActiveProjects;
}
private AbstractChoice<?, Project> createProjectChoiceDropDown(String id, IModel<List<Project>> projectChoices, OptGroupRendererMap<Project> renderer) {
if (getPanelModelObject().isNewAssignment()) {
PropertyModel<Collection<Project>> selectedProjects = new PropertyModel<>(getDefaultModel(), "selectedProjects");
return new GroupableListMultipleChoice<>(id, selectedProjects, projectChoices, renderer);
} else {
IModel<Project> projectModel;
projectModel = new PropertyModel<>(getDefaultModel(), "projectAssignment.project");
GroupableDropDownChoice<Project> choice = new GroupableDropDownChoice<>(id, projectModel, projectChoices, renderer);
choice.add(DynamicAttributeModifier.remove("style"));
return choice;
}
}
private DropDownChoice<Customer> createCustomerDropdown(List<Customer> customers) {
DropDownChoice<Customer> customerChoice = new DropDownChoice<>("customer", customers, new ChoiceRenderer<Customer>("fullName"));
customerChoice.setLabel(new ResourceModel("admin.assignment.customer"));
customerChoice.setOutputMarkupId(true);
customerChoice.setNullValid(true);
add(customerChoice);
return customerChoice;
}
private Map<Project, String> createProjectToCustomerMap(IModel<List<Project>> projectChoices) {
List<Project> projects = projectChoices.getObject();
Map<Project, String> projectToCustomerMap = Maps.newHashMap();
for (Project project : projects) {
projectToCustomerMap.put(project, project.getCustomer().getFullName());
}
return projectToCustomerMap;
}
static class ProjectRenderer extends OptGroupRendererMap<Project> {
public ProjectRenderer(Map<Project, String> projectToCustomerMap) {
super(projectToCustomerMap);
}
@Override
public Object getDisplayValue(Project project) {
return project.getFullName();
}
@Override
public String getIdValue(Project project, int index) {
return Integer.toString(project.getProjectId());
}
}
}