package de.fau.cs.mad.fablab.android.model; import android.os.Handler; import java.util.ArrayList; import java.util.List; import de.fau.cs.mad.fablab.android.model.entities.CartEntry; import de.fau.cs.mad.fablab.android.model.events.CartStatusPushedEvent; import de.fau.cs.mad.fablab.android.model.util.CancellableCallback; import de.fau.cs.mad.fablab.rest.core.CartEntryServer; import de.fau.cs.mad.fablab.rest.core.CartServer; import de.fau.cs.mad.fablab.rest.core.CartStatus; import de.fau.cs.mad.fablab.rest.core.PlatformType; import de.fau.cs.mad.fablab.rest.myapi.CartApi; import de.greenrobot.event.EventBus; import retrofit.RetrofitError; import retrofit.client.Response; public class CheckoutModel { private static final long POLLING_FREQUENCY = 3 * 1000; // 3 seconds private CartModel mCartModel; private PushModel mPushModel; private CartApi mCartApi; private EventBus mEventBus = EventBus.getDefault(); private Handler mCartStatusHandler = new Handler(); private CartStatusRunnable mCartStatusRunnable = new CartStatusRunnable(); private CancellableCallback<Response> mCartCreationCallback; private CancellableCallback<CartStatus> mCartPollingCallback; private CartStatus mCheckoutStatus = CartStatus.SHOPPING; private String mCartCode = null; public CheckoutModel(CartModel cartModel, CartApi cartApi, PushModel pushModel) { mCartModel = cartModel; mCartApi = cartApi; mPushModel = pushModel; mEventBus.register(this); } public CartStatus getStatus() { return mCheckoutStatus; } public void startCheckout(String cartCode) { mCheckoutStatus = CartStatus.WAITING; mEventBus.post(CartStatus.WAITING); mCartCode = cartCode; CartServer cartServer = new CartServer(); cartServer.setCartCode(cartCode); cartServer.setStatus(CartStatus.PENDING); cartServer.setPushToken(mPushModel.getPushId()); cartServer.setPlatformType(PlatformType.ANDROID); List<CartEntryServer> cartEntriesServer = new ArrayList<>(); for (CartEntry entry : mCartModel.getCartEntries()) { cartEntriesServer.add(new CartEntryServer(entry.getProduct().getProductId(), cartServer, entry.getAmount())); } cartServer.setItems(cartEntriesServer); mCartCreationCallback = new CancellableCallback<Response>() { @Override public void success(Response response, Response response2) { if (!isCancelled()) { mCheckoutStatus = CartStatus.PENDING; mEventBus.post(CartStatus.PENDING); mCartStatusHandler.postDelayed(mCartStatusRunnable, POLLING_FREQUENCY); } } @Override public void failure(RetrofitError error) { if (!isCancelled()) { mCheckoutStatus = CartStatus.FAILED; mEventBus.post(CartStatus.FAILED); } } }; mCartApi.create(cartServer, mCartCreationCallback); } private class CartStatusRunnable implements Runnable { @Override public void run() { mCartPollingCallback = new CancellableCallback<CartStatus>() { @Override public void success(CartStatus cartStatus, Response response) { if (!isCancelled()) { switch (cartStatus) { case CANCELLED: mCheckoutStatus = CartStatus.CANCELLED; mEventBus.post(CartStatus.CANCELLED); break; case PAID: mCartModel.markCartAsPaid(); mCheckoutStatus = CartStatus.PAID; mEventBus.post(CartStatus.PAID); break; default: mCartStatusHandler.postDelayed(mCartStatusRunnable, POLLING_FREQUENCY); } } } @Override public void failure(RetrofitError error) { if (!isCancelled()) { mCheckoutStatus = CartStatus.FAILED; mEventBus.post(CartStatus.FAILED); } } }; mCartApi.getStatus(mCartCode, mCartPollingCallback); } } public void cancelCheckout() { if (mCartCreationCallback != null) { mCartCreationCallback.cancel(); } if (mCartPollingCallback != null) { mCartPollingCallback.cancel(); } mCartStatusHandler.removeCallbacks(mCartStatusRunnable); finishCheckout(); } public void finishCheckout() { mCartCreationCallback = null; mCartPollingCallback = null; mCheckoutStatus = CartStatus.SHOPPING; mCartCode = null; } public void onEvent(CartStatusPushedEvent event) { if (mCheckoutStatus == CartStatus.PENDING) { if (mCartPollingCallback != null) { mCartPollingCallback.cancel(); } mCartStatusHandler.removeCallbacks(mCartStatusRunnable); switch (event.getCartStatus()) { case CANCELLED: mCheckoutStatus = CartStatus.CANCELLED; mEventBus.post(CartStatus.CANCELLED); break; case PAID: mCartModel.markCartAsPaid(); mCheckoutStatus = CartStatus.PAID; mEventBus.post(CartStatus.PAID); break; } } } }