package at.ac.tuwien.sbc.valesriegler.group.gui;

import at.ac.tuwien.sbc.valesriegler.common.TableModel;
import at.ac.tuwien.sbc.valesriegler.common.Util;
import at.ac.tuwien.sbc.valesriegler.group.Group;
import at.ac.tuwien.sbc.valesriegler.types.GroupData;
import at.ac.tuwien.sbc.valesriegler.types.GroupState;
import at.ac.tuwien.sbc.valesriegler.types.Table;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * Might not the nicest way to store global data, but this is an elemental
 * Object, storing ALL the Group's data. Might consider splitting those two
 * usecases apart.
 * 
 * @author jan
 * 
 */
public class GroupOverviewModel extends TableModel<Group> {
	private static final Logger log = LoggerFactory.getLogger(GroupOverviewModel.class);

	private static final String STATE = "State";
	private static final String PIZZAS = "Pizzas";
	private static final String SIZE = "Size";
	private static final String ID = "ID";
	private static final String PIZZERIA = "Pizzeria";
	private static final String[] COLUMNS = new String[] { ID, SIZE, PIZZAS, STATE, PIZZERIA };


	@Override
	protected String[] getColumns() {
		return COLUMNS;
	}

	public List<Group> getItems() {
		return new ArrayList<Group>(items.values());
	}

	public Group getGroupByID(int id) {
		return items.get(id);
	}

	@Override
	public Object getValueAt(int rowIndex, int columnIndex) {
		List<Group> values = new ArrayList<Group>(items.values());
        // TODO make sure this is necessary...
//        Collections.sort(values, new Comparator<Group>() {
//            @Override
//            public int compare(Group o1, Group o2) {
//                final int o1Id = o1.getId();
//                final int o2Id = o2.getId();
//                if(o1Id<o2Id) return -1;
//                else if(o1Id>o2Id) return 1;
//                else return 0;
//            }
//        });
        Group group = values.get(rowIndex);
		String wantedColumn = COLUMNS[columnIndex];
		switch (wantedColumn) {
		case ID:
			int groupId = group.getGroupData().getId();
			return String.format(Util.NUMBER_DISPLAY_FORMAT, groupId);
		case SIZE:
			int groupSize = group.getGroupData().getSize();
			return groupSize;
		case PIZZAS:
			if (group.getGroupData().getOrder() == null)
				return "none";
			return Util.pizzaDisplay(group.getGroupData().getOrder().getOrderedPizzas());
		case STATE:
			return group.getGroupData().getState();
        case PIZZERIA:
            return group.getGroupData().getPizzeriaId();
		default:
			throw new RuntimeException(UNHANDLEDCOLUMN);
		}
	}

    @Override
	public void addItems(List<Group> newItems) {
		log.info("addItems()");
		super.addItems(newItems);
		for (Group g : newItems) {
			if(Util.useJMS) g.goGrabSomeFood();
		}
	}
	
	/**
	 * 
	 * This is necessary as in the space version GroupData objects get written to the space. In order to 
	 * translate from Group data to the actual group object the group object has to be looked up by the id.
	 * 
	 * @param newItems the group data of the corresponding groups
	 */
	public void addGroupData(List<GroupData> newItems) {
		List<Group> groups = new ArrayList<Group>();
		for (GroupData groupData : newItems) {
			Group group = items.get(groupData.getId());
			group.setGroupData(groupData);
			groups.add(group);
		}
		super.addItems(groups);
	}

	public void setGroupEating(int groupId) {
//		if(stateIs(groupId, GroupState.GONE) || stateIs(groupId, GroupState.PAY)) return;
		changeStateOfGroup(groupId, GroupState.EATING);
		
		fireTableDataChanged();
	}

	public void setGroupWantsToPay(int groupId) {
//		if(stateIs(groupId, GroupState.GONE)) return;
		changeStateOfGroup(groupId, GroupState.PAY);
		
		fireTableDataChanged();
	}

	private boolean stateIs(int groupId, GroupState state) {
		return items.get(groupId).getGroupData().getState() == state;
	}


	public void setGroupHasPaid(int groupId) {
		changeStateOfGroup(groupId, GroupState.GONE);
		
		fireTableDataChanged();
	}
	
	private void changeStateOfGroup(int groupId, GroupState state) {
		items.get(groupId).getGroupData().setState(state);
	}

	public void setGroupsSitting(List<Table> tables) {
		synchronized (items) {
			for (Table table : tables) {
				changeStateOfGroup(table.getGroupId(), GroupState.SITTING);
			}
		}
		
		fireTableDataChanged();
	}

	public void setOrderTaken(GroupData group) {
		changeStateOfGroup(group.getId(), GroupState.ORDERED);
		
		fireTableDataChanged();
	}

}
