package br.com.caelum.vraptor.restbucks;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import br.com.caelum.vraptor.restbucks.web.ItemController;
import br.com.caelum.vraptor.restbucks.web.OrderingController;
import br.com.caelum.vraptor.restbucks.web.PaymentController;
import br.com.caelum.vraptor.restfulie.Restfulie;
import br.com.caelum.vraptor.restfulie.hypermedia.HypermediaResource;
import br.com.caelum.vraptor.restfulie.relation.Relation;
import br.com.caelum.vraptor.restfulie.resource.Cacheable;
import br.com.caelum.vraptor.restfulie.serialization.XStreamSerialize;
import com.thoughtworks.xstream.annotations.XStreamAlias;
@XStreamAlias("order")
public class Order implements HypermediaResource, Cacheable {
private String id;
private Location location;
private List<Item> items = new ArrayList<Item>();
private transient String status;
private Payment payment;
private Receipt receipt;
/**
* Cacheable for two hours.
*/
public int getMaximumAge() {
return 2 * 60 * 60;
}
public enum Location {
TO_TAKE, EAT_IN
};
public Order(String status, List<Item> items, Location location) {
this.status = status;
this.items = items;
this.location = location;
}
public Order() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@XStreamSerialize
public String getStatus() {
if(isReady()) {
return "ready";
}
return status;
}
boolean isReady() {
return status.equals("preparing") && payment.getCreatedAt().before(tenSecondsAgo());
}
private Calendar tenSecondsAgo() {
Calendar now = Calendar.getInstance();
now.add(Calendar.SECOND, -10);
return now;
}
public void cancel() {
status = "cancelled";
}
public List<Relation> getRelations(Restfulie control) {
control.relation("self").uses(OrderingController.class).get(this);
if (status.equals("unpaid")) {
control.transition("update").uses(OrderingController.class).update(this);
control.transition("cancel").uses(OrderingController.class).cancel(this);
control.relation("payment").uses(OrderingController.class).pay(this,null);
}
if(getStatus().equals("ready")) {
control.transition("retrieve").uses(OrderingController.class).cancel(this);
}
if(getStatus().equals("delivered")){
control.transition("receipt").uses(PaymentController.class).get(this);
}
control.relation("items").uses(ItemController.class).index(this);
return control.getRelations();
}
public boolean pay(Payment payment) {
if(!payment.getAmount().equals(getCost())) {
return false;
}
status = "preparing";
this.receipt = new Receipt(this);
this.payment = payment;
this.payment.setCreatedAt(new GregorianCalendar());
return true;
}
@XStreamSerialize
public BigDecimal getCost() {
return new BigDecimal(this.items.size() * 10);
}
public void setStatus(String status) {
this.status = status;
}
public Payment getPayment() {
return payment;
}
public Receipt getReceipt() {
return receipt;
}
public void finish() {
status = "delivered";
}
public List<Item> getItems() {
return items;
}
public Location getLocation() {
return location;
}
public Item findItem(int id) {
for(Item i : getItems()) {
if(i.getId()==id) {
return i;
}
}
return null;
}
}