package communication.protocols;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import node.company.TransactionContentGenerator;

import transaction.SudoTransactionContent;
import transaction.TransactionContent;
import transaction.TransactionCoordinator;
import transaction.TransactionCoordinator.TransactionStage;
import transaction.TransactionCoordinatorManager;
import transaction.Vault;
import transaction.WriteOnlyLock;
import communication.messages.BookingMessage;
import communication.messages.Message;
import data.system.NodeInfo;
import data.trainnetwork.BookableSection;
import data.trainnetwork.Seat;
import data.trainnetwork.Section;

/**
 * Protocol to handle requests to pre-book seats
 * @author Balazs Pete
 *
 */
public class PreBookingProtocol implements Protocol {

	private TransactionCoordinatorManager<String, Vault<BookableSection>, Set<Seat>> transactionCoordinators;
	private Vault<Map<String, Vault<BookableSection>>> sections;
	private HashSet<NodeInfo> nodes;
	private WriteOnlyLock<Integer> monitor;
	
	public PreBookingProtocol(
			TransactionCoordinatorManager<String, Vault<BookableSection>, Set<Seat>> transactionCoordinators, 
			Vault<Map<String, Vault<BookableSection>>> sections,
			HashSet<NodeInfo> nodes,
			WriteOnlyLock<Integer> monitor) {
		this.transactionCoordinators = transactionCoordinators;
		this.sections = sections;
		this.nodes = nodes;
		this.monitor = monitor;
	}
	
	@Override
	public String getAcceptedMessageType() {
		return "BookingMessage:" + BookingMessage.Action.PREBOOK;
	}

	@Override
	@SuppressWarnings("unchecked")
	public Message processMessage(Message message) {
		// TODO Auto-generated method stub
		
		HashSet<Section> sections = (HashSet<Section>) message.getContents();
		SudoTransactionContent<String, Vault<BookableSection>, Set<Seat>> content = TransactionContentGenerator.getSeatPreBookingContent(sections);
		TransactionCoordinator<String, Vault<BookableSection>, Set<Seat>> coordinator 
			= new TransactionCoordinator<String, Vault<BookableSection>, Set<Seat>>(content, this.sections, nodes, monitor);
		
		transactionCoordinators.put(coordinator.getTransactionId(), coordinator);
		
		TransactionStage stage;
		// No need to wait for TransactionStatus.DONE, it's okay to reply when the transaction is in COMMIT or ABORT stage
		while ((stage = coordinator.getStage()) == TransactionStage.COMMIT || stage == TransactionStage.ABORT) {
			try {
				// Wait until notified or timed out
				coordinator.wait(5000);
			} catch (InterruptedException e) {
				System.err.println(e.getMessage());
			}
		}
		
		return null;
	}

	@Override
	public boolean hasReply() {
		return true;
	}

}

@@ -485,24 +485,75 @@
 ingMessage;%0A
+import communication.messages.BookingReplyMessage;%0A
 import commu
@@ -575,24 +575,24 @@
 es.Message;%0A
-
 import data.
@@ -1704,48 +1704,8 @@
 ) %7B%0A
-%09%09// TODO Auto-generated method stub%0A%09%09%0A
 %09%09Ha
@@ -1848,16 +1848,20 @@
 content 
+%0A%09%09%09
 = Transa
@@ -2496,16 +2496,74 @@
 med out%0A
+%09%09%09%09System.out.println(%22gonna wait for transaction end%22);%0A
 %09%09%09%09coor
@@ -2678,19 +2678,245 @@
 %09%0A%09%09
-return null
+HashSet%3CSeat%3E returnedData = new HashSet%3CSeat%3E(content.getReturnedData());%0A%09%09BookingReplyMessage reply = new BookingReplyMessage();%0A%09%09reply.setContents(returnedData);%0A%09%09%0A%09%09System.out.println(%22content: %22 + returnedData);%0A%09%09%0A%09%09return reply
 ;%0A%09%7D

Add reply and some debugging statements to ReBookingProtocol