package com.constellio.app.modules.es.ui.components;
import static com.constellio.app.ui.i18n.i18n.$;
import java.util.List;
import org.joda.time.DateTimeConstants;
import com.constellio.app.modules.es.model.connectors.structures.TraversalSchedule;
import com.constellio.app.ui.entities.MetadataVO;
import com.constellio.app.ui.entities.RecordVO;
import com.constellio.app.ui.framework.buttons.AddButton;
import com.constellio.app.ui.framework.buttons.IconButton;
import com.vaadin.data.Property;
import com.vaadin.data.Validator.InvalidValueException;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.data.util.NestedMethodProperty;
import com.vaadin.data.util.converter.Converter.ConversionException;
import com.vaadin.server.Resource;
import com.vaadin.server.ThemeResource;
import com.vaadin.ui.AbstractSelect.ItemCaptionMode;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomField;
import com.vaadin.ui.Table;
import com.vaadin.ui.Table.ColumnGenerator;
import com.vaadin.ui.VerticalLayout;
public class TraversalSchedulesComponent extends CustomField<List<TraversalSchedule>> {
public static final String WEEK_DAY_FIELD = "weekDay";
public static final String START_TIME_FIELD = "startTime";
public static final String END_TIME_FIELD = "endTime";
public static final String DELETE_BUTTON = "delete";
private Table table;
private AddButton addButton;
private VerticalLayout layout;
private RecordVO connectorInstance;
private MetadataVO metadataVO;
private final BeanItemContainer<TraversalSchedule> container;
public TraversalSchedulesComponent(RecordVO connectorInstance, final MetadataVO metadataVO) {
super();
this.connectorInstance = connectorInstance;
this.metadataVO = metadataVO;
layout = new VerticalLayout();
layout.setSpacing(true);
table = new Table();
table.setWidth("100%");
table.setPageLength(0);
container = new BeanItemContainer<>(TraversalSchedule.class);
table.setContainerDataSource(container);
List<TraversalSchedule> traversalSchedules = getTraversalSchedules();
if (traversalSchedules.isEmpty()) {
traversalSchedules.add(new TraversalSchedule());
}
table.addItems(traversalSchedules);
table.addGeneratedColumn(WEEK_DAY_FIELD, new WeekDayFieldGenerator());
table.setColumnHeader(WEEK_DAY_FIELD, $("TraversalSchedule.weekDay"));
table.addGeneratedColumn(START_TIME_FIELD, new TimeFieldGenerator());
table.setColumnHeader(START_TIME_FIELD, $("TraversalSchedule.startTime"));
table.addGeneratedColumn(END_TIME_FIELD, new TimeFieldGenerator());
table.setColumnHeader(END_TIME_FIELD, $("TraversalSchedule.endTime"));
table.addGeneratedColumn(DELETE_BUTTON, new DeleteButtonGenerator());
table.setColumnHeader(DELETE_BUTTON, "");
table.addValueChangeListener(new ValueChangeListener() {
@SuppressWarnings("unchecked")
@Override
public void valueChange(Property.ValueChangeEvent event) {
List<TraversalSchedule> newValue = (List<TraversalSchedule>) table.getItemIds();
TraversalSchedulesComponent.this.connectorInstance.set(metadataVO, newValue);
}
});
table.setVisibleColumns(WEEK_DAY_FIELD, START_TIME_FIELD, END_TIME_FIELD, DELETE_BUTTON);
addButton = new AddButton($("add")) {
@Override
protected void buttonClick(ClickEvent event) {
TraversalSchedule newTraversalSchedule = new TraversalSchedule();
List<TraversalSchedule> traversalSchedules = getTraversalSchedules();
int indexOfNewCopy;
if (traversalSchedules.size() > 1) {
indexOfNewCopy = traversalSchedules.size();
} else {
indexOfNewCopy = 1;
}
traversalSchedules.add(indexOfNewCopy, newTraversalSchedule);
addItems();
}
};
layout.addComponents(addButton, table);
layout.setComponentAlignment(addButton, Alignment.TOP_RIGHT);
}
private void addItems() {
table.removeAllItems();
List<TraversalSchedule> traversalSchedules = getTraversalSchedules();
for (TraversalSchedule traversalSchedule : traversalSchedules) {
addItem(traversalSchedule);
}
}
private void removeItem(TraversalSchedule traversalSchedule) {
List<TraversalSchedule> traversalSchedules = getTraversalSchedules();
traversalSchedules.remove(traversalSchedule);
setValue(traversalSchedules);
}
private void addItem(TraversalSchedule traversalSchedule) {
table.addItem(traversalSchedule);
}
public List<TraversalSchedule> getTraversalSchedules() {
return connectorInstance.getList(metadataVO);
}
@Override
public List<TraversalSchedule> getValue() {
return connectorInstance.get(metadataVO);
}
@Override
public void setValue(List<TraversalSchedule> newFieldValue)
throws ReadOnlyException, ConversionException {
connectorInstance.set(metadataVO, newFieldValue);
addItems();
}
@Override
protected Component initContent() {
return layout;
}
@SuppressWarnings("unchecked")
@Override
public Class getType() {
return List.class;
}
public static class WeekDayFieldGenerator implements ColumnGenerator {
@Override
public Component generateCell(Table source, Object itemId, Object columnId) {
Component component = buildOperatorField((TraversalSchedule) itemId);
// source.getContainerProperty(itemId, columnId).setValue(component);
return component;
}
private Component buildOperatorField(final TraversalSchedule traversalSchedule) {
ComboBox comboBox = new ComboBox();
comboBox.setPropertyDataSource(new NestedMethodProperty<Integer>(traversalSchedule, WEEK_DAY_FIELD));
comboBox.addItem(DateTimeConstants.MONDAY);
comboBox.setItemCaption(DateTimeConstants.MONDAY, $("TraversalSchedule.monday"));
comboBox.addItem(DateTimeConstants.TUESDAY);
comboBox.setItemCaption(DateTimeConstants.TUESDAY, $("TraversalSchedule.tuesday"));
comboBox.addItem(DateTimeConstants.WEDNESDAY);
comboBox.setItemCaption(DateTimeConstants.WEDNESDAY, $("TraversalSchedule.wednesday"));
comboBox.addItem(DateTimeConstants.THURSDAY);
comboBox.setItemCaption(DateTimeConstants.THURSDAY, $("TraversalSchedule.thursday"));
comboBox.addItem(DateTimeConstants.FRIDAY);
comboBox.setItemCaption(DateTimeConstants.FRIDAY, $("TraversalSchedule.friday"));
comboBox.addItem(DateTimeConstants.SATURDAY);
comboBox.setItemCaption(DateTimeConstants.SATURDAY, $("TraversalSchedule.saturday"));
comboBox.addItem(DateTimeConstants.SUNDAY);
comboBox.setItemCaption(DateTimeConstants.SUNDAY, $("TraversalSchedule.sunday"));
comboBox.setItemCaptionMode(ItemCaptionMode.EXPLICIT);
comboBox.setNullSelectionAllowed(false);
// comboBox.setWidth("100px");
return comboBox;
}
}
public static class TimeFieldGenerator implements ColumnGenerator {
@Override
public Component generateCell(Table source, Object itemId, Object columnId) {
return buildOperatorField((TraversalSchedule) itemId, (String) columnId);
}
private Component buildOperatorField(final TraversalSchedule traversalSchedule, String columnId) {
ComboBox comboBox = new ComboBox();
for (int h = 0; h < 24; h++) {
comboBox.addItem(h + ":00");
comboBox.addItem(h + ":30");
}
if (START_TIME_FIELD.equals(columnId)) {
comboBox.setPropertyDataSource(new NestedMethodProperty<String>(traversalSchedule, START_TIME_FIELD));
} else if (END_TIME_FIELD.equals(columnId)) {
comboBox.setPropertyDataSource(new NestedMethodProperty<String>(traversalSchedule, END_TIME_FIELD));
}
return comboBox;
}
}
public class DeleteButtonGenerator implements ColumnGenerator {
public final Resource ICON_RESOURCE = new ThemeResource("images/commun/supprimer.gif");
@Override
public Object generateCell(final Table source, final Object itemId, Object columnId) {
Button delete = new IconButton(ICON_RESOURCE, $("delete"), true) {
@Override
protected void buttonClick(ClickEvent event) {
removeItem((TraversalSchedule) itemId);
}
};
delete.setEnabled(source.size() > 1);
return delete;
}
}
@Override
protected void validate(List<TraversalSchedule> fieldValue)
throws InvalidValueException {
super.validate(fieldValue);
for (TraversalSchedule traversalSchedule : fieldValue) {
if (!traversalSchedule.isEmpty()) {
if (!traversalSchedule.hasValuesInAllFields()) {
throw new InvalidValueException($("TraversalSchedule.mustHaveValuesInAllFields"));
} else if (!startTimeBeforeEndTime(traversalSchedule)) {
throw new InvalidValueException($("TraversalSchedule.startTimeAfterEndTime"));
}
}
}
}
private boolean startTimeBeforeEndTime(TraversalSchedule traversalSchedule) {
int startTime = toInt(traversalSchedule.getStartTime());
int endTime = toInt(traversalSchedule.getEndTime());
if (startTime == 0 && endTime == 0) {
return true;
}
return startTime < endTime;
}
private int toInt(String time) {
String normalizedTime = time.replace(":", "");
return Integer.parseInt(normalizedTime);
}
}