package at.ac.tuwien.sbc.valesriegler.xvsm;

import at.ac.tuwien.sbc.valesriegler.common.Util;
import at.ac.tuwien.sbc.valesriegler.types.GroupData;
import at.ac.tuwien.sbc.valesriegler.types.GroupState;
import at.ac.tuwien.sbc.valesriegler.types.Order;
import at.ac.tuwien.sbc.valesriegler.xvsm.spacehelpers.SpaceAction;
import org.mozartspaces.core.MzsConstants.RequestTimeout;
import org.mozartspaces.core.TransactionReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;

public class GroupXVSM extends AbstractXVSMConnector {
	private static final Logger log = LoggerFactory.getLogger(GroupXVSM.class);
	
	private int groupId;

	public GroupXVSM(int groupId, int port) {
		super(port);
		this.groupId = groupId;
		
		paymentRequestContainer = useContainerOfSpaceWithPort(Util.PAYMENT_REQUEST, port) ;
		orderDeliveredContainer = useContainerOfSpaceWithPort(Util.ORDER_COMPLETE, port) ;
        pizzeriaGroupContainer = useContainerOfSpaceWithPort(Util.PIZZERIA_GROUP, port);
	}

	public void waitForMyOrder() {
        getDefaultBuilder().setCref(orderDeliveredContainer).setSpaceAction(new SpaceAction() {
            @Override
            public void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
            	final List<GroupData> groups = castEntries(entries);
        
                final Order order = groups.get(0).getOrder();
        
				if(order.getGroupId() == groupId) {
					eatAndThenPay();
				}
            }}).createSpaceListenerImpl();
	}
	
	private void eatAndThenPay() {
        try {
            int timeToEat = Util.getRandom(3, 5);
            log.info("I eat {} seconds now...", timeToEat);

            try {
                Thread.sleep(timeToEat * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            GroupData groupData = new GroupData();
            groupData.setId(groupId);
            groupData.setState(GroupState.EATING);
            final TransactionReference tx = getDefaultTransaction();

            final GroupData group = takeMatchingEntity(groupData, pizzeriaGroupContainer, tx, RequestTimeout.DEFAULT, "Group does not exist!");

            group.setState(GroupState.PAY);
            final List<GroupData> groupList = Arrays.asList(group);
            sendItemsToContainer(groupList, paymentRequestContainer, RequestTimeout.DEFAULT, tx);
            sendItemsToContainer(groupList, pizzeriaGroupContainer, RequestTimeout.DEFAULT, tx);
            capi.commitTransaction(tx);
            log.info("I sent my payment request to the space! GroupId: {}", groupId);

            notificationMgr.shutdown();

        } catch(NullPointerException e) {
            // npe from the space
        } catch (Exception e) {
            log.error("Customer group fail, groupId: {}", groupId);
        }
    }

}
