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

import at.ac.tuwien.sbc.valesriegler.common.Util;
import at.ac.tuwien.sbc.valesriegler.jms.nac.JMSNAC;
import at.ac.tuwien.sbc.valesriegler.pizzeria.actions.TableNew;
import at.ac.tuwien.sbc.valesriegler.pizzeria.gui.PizzeriaFrame;
import at.ac.tuwien.sbc.valesriegler.pizzeria.gui.tablemodels.*;
import at.ac.tuwien.sbc.valesriegler.pizzeria.jms.JMSPizzeriaConnector;
import at.ac.tuwien.sbc.valesriegler.pizzeria.jms.PizzeriaJMSNACMsgListener;
import at.ac.tuwien.sbc.valesriegler.types.Table;
import at.ac.tuwien.sbc.valesriegler.xvsm.PizzeriaAgentXVSM;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.*;
import java.util.List;

/**
 * The Main class of the Pizzeria compoment.
 * <p />
 * Start the communication and the Pizzeria GUI
 * 
 * @author Gregor Riegler <gregor DOT riegler AT gmail DOT com>
 * @author jan
 */
public class PizzeriaAgent {
	private static final String USAGE = "This application needs 2 parameters: <\"XVSM\"|\"JMS\"> <XVSM-Space-Identifier|JMS-Server-URL>";
	private static final Logger log = LoggerFactory.getLogger(PizzeriaAgent.class);

	private static PizzeriaAgent pizzeriaAgent;

	private OrdersOverviewModel ordersModel;
	private GroupsOverviewModel groupModel;
	private TablesOverviewModel tablesModel;
	private WaitersOfOrderModel waitersModel;
	private PizzasOfOrderModel pizzasOfOrderModel;
	private DeliveryDetailsModel deliveryDetailsModel;
	private PizzasOfOrderModel pizzasOfDeliveryModel;
	private DeliveryOrdersModel deliveryOrdersModel;

	private PizzeriaAgentXVSM xvsm;
	private JMSPizzeriaConnector jmspc;
	private JMSNAC jmsnac;

	public static void main(String[] args) {
		if (args.length != 2) {
			throw new IllegalArgumentException(USAGE);
		}
		String mw = args[0];
		log.info("Middleware: " + mw);
		pizzeriaAgent = new PizzeriaAgent();
		switch (mw) {
			case "XVSM" :
				pizzeriaAgent.createModels();
				pizzeriaAgent.initXVSM(args[1]);
				if (!Util.runSimulation) {
					pizzeriaAgent.initGUI(args[1]);
				}
				Util.useJMS = false;
				break;
			case "JMS" :
				pizzeriaAgent.createModels();
				pizzeriaAgent.jmspc = new JMSPizzeriaConnector(args[1]);
				pizzeriaAgent.jmspc.init();
				pizzeriaAgent.jmsnac = new JMSNAC(new PizzeriaJMSNACMsgListener());
				if (!Util.runSimulation) {
					pizzeriaAgent.initGUI(args[1]);
				}
				Util.useJMS = true;
				break;
			default :
				throw new IllegalArgumentException(USAGE);
		}
	}
	private void initXVSM(String arg) {
		int port = 0;
		try {
			port = Integer.parseInt(arg);
		} catch (NumberFormatException e) {
			log.error("The XVSM-Space-Identifier needs to be an integer port!");
			System.exit(1);
		}

		xvsm = new PizzeriaAgentXVSM(port);
		xvsm.initializeOrderId();
		xvsm.notifyGroupAgent();

		xvsm.listenForDeliveryUpdates();
		xvsm.listenForTablesUpdates();
		xvsm.listenForGroupUpdates();
	}

	private void initGUI(String pizzeriaIdentifier) {
		PizzeriaGUI gui = new PizzeriaGUI(pizzeriaIdentifier );
		SwingUtilities.invokeLater(gui);
	}

	class PizzeriaGUI implements Runnable {
        private final String id;

        public PizzeriaGUI(String pizzeriaIdentifier) {
            this.id = pizzeriaIdentifier;
        }

        @Override
		public void run() {
			PizzeriaFrame frame = new PizzeriaFrame(id);
			frame.setOnTablesCreatedHandler(new TablesCreatedHandler() {

				@Override
				public void freeTablesCreated(List<Table> tables) {
					if (!Util.useJMS) {
						xvsm.sendFreeTablesToContainer(tables);
					} else {
						for (Table t : tables) {
							jmspc.send(new TableNew(t));
						}
					}
				}
			});
			frame.start();
			frame.pack();
			frame.setVisible(true);
		}
	}

	private void createModels() {
		ordersModel = new OrdersOverviewModel();
		groupModel = new GroupsOverviewModel();
		tablesModel = new TablesOverviewModel();
		waitersModel = new WaitersOfOrderModel();
		pizzasOfOrderModel = new PizzasOfOrderModel();
		deliveryOrdersModel = new DeliveryOrdersModel();
		deliveryDetailsModel = new DeliveryDetailsModel();
		pizzasOfDeliveryModel = new PizzasOfOrderModel();
	}

	public static PizzeriaAgent getInstance() {
		return pizzeriaAgent;
	}

	public OrdersOverviewModel getOrdersModel() {
		return ordersModel;
	}

	public DeliveryOrdersModel getDeliveryOrdersModel() {
		return deliveryOrdersModel;
	}

	public DeliveryDetailsModel getDeliveryDetailsModel() {
		return deliveryDetailsModel;
	}

	public PizzasOfOrderModel getPizzasOfDeliveryModel() {
		return pizzasOfDeliveryModel;
	}

	public GroupsOverviewModel getGroupModel() {
		return groupModel;
	}

	public TablesOverviewModel getTablesModel() {
		return tablesModel;
	}

	public WaitersOfOrderModel getWaitersModel() {
		return waitersModel;
	}

	public PizzasOfOrderModel getPizzasOfOrderModel() {
		return pizzasOfOrderModel;
	}

	public JMSNAC getJmsnac() {
		return jmsnac;
	}

	public JMSPizzeriaConnector getJmspc() {
		return jmspc;
	}

	public interface TablesCreatedHandler {
		public void freeTablesCreated(List<Table> tables);
	}

}
