package com.din.din.webapp.beans.interfaces;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.persistence.EntityManager;
import org.primefaces.event.CloseEvent;
import org.primefaces.event.DragDropEvent;
import org.primefaces.event.FlowEvent;
import com.din.din.model.dao.FoodItemDAO;
import com.din.din.model.dao.QuantityTypeDAO;
import com.din.din.model.dao.RecipeDAO;
import com.din.din.model.dao.RecipeItemDAO;
import com.din.din.model.entities.FoodItem;
import com.din.din.model.entities.KeyEntity;
import com.din.din.model.entities.Project;
import com.din.din.model.entities.QuantityType;
import com.din.din.model.entities.Recipe;
import com.din.din.model.entities.Recipe.TimeMeasurement;
import com.din.din.model.entities.RecipeItem;
import com.din.din.model.util.EntityCachingManager;
import com.din.din.model.util.EntityCachingManager.CacheLoader;
import com.din.din.model.webapp.Wizard;
import com.din.din.webapp.beans.interfaces.wrappers.FoodItemWrapper;
import com.din.din.webapp.beans.interfaces.wrappers.RecipeItemWrapper;
import com.din.din.webapp.beans.util.BeanUtil;
import com.google.appengine.api.datastore.Key;
public class RecipeWizard extends Wizard<Recipe> {
private Set<FoodItemWrapper> foodItemSet = new LinkedHashSet<FoodItemWrapper>();
private List<FoodItemWrapper> foodItemList = null;
private Project project;
private FoodItem selectedFoodItem = null;
public RecipeWizard(Project project, EntityCachingManager cache) {
super(cache);
this.project = project;
}
public void setEntity(Recipe recipe) {
super.setEntity(recipe);
if(recipe != null) {
EntityCachingManager cache = getCache();
final Project project = recipe.getProject();
// Load QuantityTypes if not already loaded
cache.get(QuantityType.class, true, new CacheLoader<QuantityType>() {
public List<QuantityType> onCacheLoad() {
return QuantityTypeDAO.getQuantityTypeByProject(project);
}
});
foodItemSet.clear();
if(recipe.getRecipeItems() != null) {
Map<Key, KeyEntity> foodItemMap = cache.get(FoodItem.class);
for(RecipeItem item : recipe.getRecipeItems()) {
if(foodItemMap.containsKey(item.getFoodItemKey())) {
FoodItem foodItem = (FoodItem)foodItemMap.get(item.getFoodItemKey());
FoodItemWrapper foodItemWrapper = new FoodItemWrapper(project, foodItem, item);
foodItemSet.add(foodItemWrapper);
}
}
}
}
}
public Recipe getRecipe() {
return getEntity();
}
public TimeMeasurement[] getTimeMeasurements() {
return TimeMeasurement.values();
}
public synchronized List<FoodItemWrapper> getFoodItemList() {
if(foodItemList == null) {
foodItemList = new ArrayList<FoodItemWrapper>(foodItemSet);
}
return foodItemList;
}
public FoodItem getSelectedFoodItem() {
return selectedFoodItem;
}
public void setSelectedFoodItem(FoodItem selectedFoodItem) {
this.selectedFoodItem = selectedFoodItem;
}
public FoodItemWrapper getSelectedFoodItemWrapper() {
return selectedFoodItem != null ? new FoodItemWrapper(project, selectedFoodItem) : null;
}
public void setSelectedFoodItemWrapper(FoodItemWrapper selectedFoodItem) {
setSelectedFoodItem(selectedFoodItem != null ? selectedFoodItem.getFoodItem() : null);
}
public synchronized void onFoodItemDrop(DragDropEvent ddEvent) {
if(selectedFoodItem != null) {
if(foodItemSet.add(new FoodItemWrapper(project, selectedFoodItem))) {
foodItemList = null;
}
selectedFoodItem = null;
}
}
public void onRemoveFoodItem(CloseEvent event) {
FacesContext context = FacesContext.getCurrentInstance();
FoodItem item = context.getApplication().evaluateExpressionGet(context, "#{foodItem}", FoodItem.class);
selectedFoodItem = item;
onRemoveFoodItem();
}
public void onRemoveFoodItem(ActionEvent event) {
onRemoveFoodItem();
}
public synchronized String onRemoveFoodItem() {
if(selectedFoodItem != null) {
if(foodItemSet.remove(new FoodItemWrapper(project, selectedFoodItem))) {
foodItemList = null;
}
}
return null;
}
@Override
public String onTransition(FlowEvent event) {
final String [] phases = {"summary", "ingredientList", "directions", "confirm"};
String nextStep = super.onTransition(event);
// Perform validation on foodItemSet to make sure we have all information in order to proceed
if(phases[1].equals(event.getOldStep()) && phases[2].equals(event.getNewStep())) {
if(!validateIngredientList()) {
nextStep = event.getOldStep();
} else {
List<RecipeItem> recipeItems = getRecipeItemList();
getRecipe().setRecipeItems(recipeItems);
}
}
return nextStep;
}
@Override
protected void onPreSave(EntityManager entityManager, Recipe entity)
throws Exception {
super.onPreSave(entityManager, entity);
// Save/update all current RecipeItems
for(FoodItemWrapper item : foodItemSet) {
RecipeItemWrapper recipeItemWrapper = item.getRecipeItem();
RecipeItem recipeItem = recipeItemWrapper.getRecipeItem();
recipeItem.setRecipe(entity);
recipeItem.setFoodItemKey(item.getFoodItem().getKey());
}
entity.setRecipeItems(getRecipeItemList());
}
@Override
protected void onPostSave(EntityManager entityManager, Recipe entity)
throws Exception {
super.onPostSave(entityManager, entity);
for(RecipeItem item : entity.getRecipeItems()) {
item.setRecipe(entity);
}
// entity = entityManager.merge(entity);
//
// // Delete RecipeItems present before and no longer present now
// Map<Key, RecipeItem> recipeItemMap = getRecipeItemMap();
// List<RecipeItem> oldRecipeItems = entity.getRecipeItems();
// for(RecipeItem item : oldRecipeItems) {
// if(!recipeItemMap.containsKey(item.getKey())) {
// RecipeItemDAO.delete(entityManager, item, getCache());
// }
// }
// RecipeDAO.save(entityManager, entity, getCache());
}
private Map<Key, RecipeItem> getRecipeItemMap() {
Map<Key, RecipeItem> recipeItemMap = new LinkedHashMap<Key, RecipeItem>();
for(FoodItemWrapper item : foodItemSet) {
RecipeItemWrapper recipeItemWrapper = item.getRecipeItem();
RecipeItem recipeItem = recipeItemWrapper.getRecipeItem();
if(recipeItem.getKey() != null) {
recipeItemMap.put(recipeItem.getKey(), recipeItem);
}
}
return recipeItemMap;
}
private List<RecipeItem> getRecipeItemList() {
List<RecipeItem> recipeItems = new ArrayList<RecipeItem>(foodItemSet.size());
for(FoodItemWrapper wrapper : foodItemSet) {
recipeItems.add(wrapper.getRecipeItem().getRecipeItem());
}
return recipeItems;
}
@Override
protected String onSaveSuccess(Recipe entity) {
List<RecipeItem> recipeItems = new ArrayList<RecipeItem>();
for(FoodItemWrapper item : foodItemSet) {
RecipeItemWrapper recipeItemWrapper = item.getRecipeItem();
RecipeItem recipeItem = recipeItemWrapper.getRecipeItem();
recipeItems.add(recipeItem);
}
entity.setRecipeItems(recipeItems);
foodItemSet.clear();
foodItemList = null;
return super.onSaveSuccess(entity);
}
private boolean validateIngredientList() {
boolean valid = true;
if(foodItemSet != null) {
for(FoodItemWrapper item : foodItemSet) {
RecipeItemWrapper recipeItem = item.getRecipeItem();
if(recipeItem == null || recipeItem.getDescription() == null || recipeItem.getDescription().trim().isEmpty()) {
valid = false;
item.setValid(false);
BeanUtil.addMessageFmt(FacesMessage.SEVERITY_ERROR, "error.ingredientList", "error.ingredientList.description", item.getName());
} else if (recipeItem.getQuantityType() == null) {
valid = false;
item.setValid(false);
BeanUtil.addMessageFmt(FacesMessage.SEVERITY_ERROR, "error.ingredientList", "error.ingredientList.quantityTypeMissing", item.getName());
} else {
item.setValid(true);
}
}
}
return valid;
}
}