<commit_before>package com.ibm.sk.ff.gui.client;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.ibm.sk.ff.gui.common.GUIOperations;
import com.ibm.sk.ff.gui.common.events.GuiEvent;
import com.ibm.sk.ff.gui.common.events.GuiEventListener;
import com.ibm.sk.ff.gui.common.mapper.Mapper;
import com.ibm.sk.ff.gui.common.objects.gui.GAntFoodObject;
import com.ibm.sk.ff.gui.common.objects.gui.GAntObject;
import com.ibm.sk.ff.gui.common.objects.gui.GFoodObject;
import com.ibm.sk.ff.gui.common.objects.gui.GHillObject;
import com.ibm.sk.ff.gui.common.objects.gui.GUIObject;
import com.ibm.sk.ff.gui.common.objects.gui.GUIObjectCrate;
import com.ibm.sk.ff.gui.common.objects.gui.GUIObjectTypes;
import com.ibm.sk.ff.gui.common.objects.operations.CloseData;
import com.ibm.sk.ff.gui.common.objects.operations.CreateGameData;
import com.ibm.sk.ff.gui.common.objects.operations.InitMenuData;
import com.ibm.sk.ff.gui.common.objects.operations.ResultData;
import com.ibm.sk.ff.gui.common.objects.operations.ScoreData;

public class GUIFacade {

	private final Client CLIENT;

	private final List<GuiEventListener> guiEventListeners = new ArrayList<>();
	
	private final List<GAntFoodObject> antFoodObjects = new ArrayList<>();
	
	private final Map<GAntObject, GAntFoodObject> notRenderedYet = new HashMap<>();
	
	public GUIFacade() {
		this.CLIENT = new Client();
		new Thread(new Runnable() {
			@Override
			public void run() {
				final int sleepTime = Integer.parseInt(Config.SERVER_POLL_INTERVAL.toString());
				while (true) {
					try {
						Thread.sleep(sleepTime);
						checkEvents();
					} catch (final Exception e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
	}

	public void set(final GUIObject object) {
		set(new GUIObject[] {object});
	}

	public void set(final GUIObject[] o) {
		if (o != null && o.length > 0) {
			GUIObject [] objects = map(o);

			final GUIObjectCrate crate = new GUIObjectCrate();
			for (final GUIObject guiObject : objects) {
				if (guiObject instanceof GHillObject) {
					final GHillObject hill = (GHillObject) guiObject;
					crate.getHills().add(hill);
				}
				if (guiObject instanceof GAntObject) {
					final GAntObject ant = (GAntObject) guiObject;
					crate.getAnts().add(ant);
				}
				if (guiObject instanceof GFoodObject) {
					final GFoodObject food = (GFoodObject) guiObject;
					crate.getFoods().add(food);
				}
				if (guiObject instanceof GAntFoodObject) {
					final GAntFoodObject antFood = (GAntFoodObject) guiObject;
					crate.getAntFoods().add(antFood);
				}
			}
			
			this.CLIENT.postMessage(GUIOperations.SET.toString(), Mapper.INSTANCE.pojoToJson(crate));
		}
		
		sendNotYetRenderedData(o);
	}
	
	private void sendNotYetRenderedData(GUIObject[] o) {
		if (notRenderedYet.size() > 0) {
			List<GAntObject> antsToRemove = new ArrayList<>();
			List<GFoodObject> foodsToRemove = new ArrayList<>();
			
			notRenderedYet.values().stream().forEach(af -> {
				antsToRemove.add(af.getAnt());
				foodsToRemove.add(af.getFood());
				}
			);
			
			remove(antsToRemove.stream().toArray(GAntObject[]::new));
			remove(foodsToRemove.stream().toArray(GFoodObject[]::new));
			
			this.CLIENT.postMessage(
				GUIOperations.SET.toString() + "/" + GUIObjectTypes.ANT_FOOD.toString(), 
				Mapper.INSTANCE.pojoToJson(mapNotYetRendered(o))
			);
		}
	}
	
	private GAntFoodObject[] mapNotYetRendered(GUIObject[] o) {
		List<GAntFoodObject> ret = new ArrayList<>();
		
		for (GUIObject it : o) {
			if (it.getType() == GUIObjectTypes.ANT) {
				GAntObject swp = (GAntObject)it;
				if (notRenderedYet.containsKey(swp)) {
					GAntFoodObject toAdd = notRenderedYet.remove(swp);
					toAdd.setLocation(swp.getLocation());
					ret.add(toAdd);
				}
			}
		}
		
		return ret.stream().toArray(GAntFoodObject[]::new);
	}
	
	private GUIObject[] map(GUIObject[] orig) {
		List<GUIObject> ret = new ArrayList<>(orig.length);
		for (GUIObject it : orig) {
			if (it.getType() == GUIObjectTypes.ANT) {
				GAntFoodObject mapped = getMapped((GAntObject)it);
				if (mapped != null && !notRenderedYet.containsValue(mapped)) {
					mapped.setLocation(it.getLocation());
					ret.add(mapped);
				} else {
					ret.add(it);
				}
			} else {
				ret.add(it);
			}
		}
		return ret.stream().toArray(GUIObject[]::new);
	}
	
	private GAntFoodObject getMapped(GAntObject ant) {
		return antFoodObjects.stream().filter(af -> af.getAnt().equals(ant)).findFirst().orElse(null);
	}

	public GAntFoodObject join(GAntObject ant, GFoodObject food) {
		GAntFoodObject gafo = new GAntFoodObject();
		gafo.setAnt(ant);
		gafo.setFood(food);
		if (!antFoodObjects.contains(getMapped(ant))) {
			antFoodObjects.add(gafo);
			notRenderedYet.put(ant, gafo);
		}
		return gafo;
	}
	
	public GUIObject[] separate(GAntObject ant) {
		List<GUIObject> retList = new ArrayList<>();
		//TODO
		
		antFoodObjects.stream()
			.filter(afo -> afo.getAnt().equals(ant))
			.forEach(afo -> retList.add(afo.getFood()));
		
		return retList.stream().toArray(GUIObject[]::new);
	}
	
	public void separate(GFoodObject food) {
		//TODO
	}
	
	public void separate(GAntObject ant, GFoodObject food) {
		//TODO
	}
	
	public void remove(final GUIObject data) {
		remove(new GUIObject [] {data});
	}

	public void remove(final GUIObject[] data) {
		if (data.length > 0) {
			this.CLIENT.postMessage(GUIOperations.REMOVE.toString() + "/" + data[0].getType().toString(), Mapper.INSTANCE.pojoToJson(data));
		}
	}<commit_msg>finished TODO for antFood gui object separation<commit_after>package com.ibm.sk.ff.gui.client;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.ibm.sk.ff.gui.common.GUIOperations;
import com.ibm.sk.ff.gui.common.events.GuiEvent;
import com.ibm.sk.ff.gui.common.events.GuiEventListener;
import com.ibm.sk.ff.gui.common.mapper.Mapper;
import com.ibm.sk.ff.gui.common.objects.gui.GAntFoodObject;
import com.ibm.sk.ff.gui.common.objects.gui.GAntObject;
import com.ibm.sk.ff.gui.common.objects.gui.GFoodObject;
import com.ibm.sk.ff.gui.common.objects.gui.GHillObject;
import com.ibm.sk.ff.gui.common.objects.gui.GUIObject;
import com.ibm.sk.ff.gui.common.objects.gui.GUIObjectCrate;
import com.ibm.sk.ff.gui.common.objects.gui.GUIObjectTypes;
import com.ibm.sk.ff.gui.common.objects.operations.CloseData;
import com.ibm.sk.ff.gui.common.objects.operations.CreateGameData;
import com.ibm.sk.ff.gui.common.objects.operations.InitMenuData;
import com.ibm.sk.ff.gui.common.objects.operations.ResultData;
import com.ibm.sk.ff.gui.common.objects.operations.ScoreData;

public class GUIFacade {

	private final Client CLIENT;

	private final List<GuiEventListener> guiEventListeners = new ArrayList<>();
	
	private final List<GAntFoodObject> antFoodObjects = new ArrayList<>();
	
	private final Map<GAntObject, GAntFoodObject> notRenderedYet = new HashMap<>();
	
	public GUIFacade() {
		this.CLIENT = new Client();
		new Thread(new Runnable() {
			@Override
			public void run() {
				final int sleepTime = Integer.parseInt(Config.SERVER_POLL_INTERVAL.toString());
				while (true) {
					try {
						Thread.sleep(sleepTime);
						checkEvents();
					} catch (final Exception e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
	}

	public void set(final GUIObject object) {
		set(new GUIObject[] {object});
	}

	public void set(final GUIObject[] o) {
		if (o != null && o.length > 0) {
			GUIObject [] objects = map(o);

			final GUIObjectCrate crate = new GUIObjectCrate();
			for (final GUIObject guiObject : objects) {
				if (guiObject instanceof GHillObject) {
					final GHillObject hill = (GHillObject) guiObject;
					crate.getHills().add(hill);
				}
				if (guiObject instanceof GAntObject) {
					final GAntObject ant = (GAntObject) guiObject;
					crate.getAnts().add(ant);
				}
				if (guiObject instanceof GFoodObject) {
					final GFoodObject food = (GFoodObject) guiObject;
					crate.getFoods().add(food);
				}
				if (guiObject instanceof GAntFoodObject) {
					final GAntFoodObject antFood = (GAntFoodObject) guiObject;
					crate.getAntFoods().add(antFood);
				}
			}
			
			this.CLIENT.postMessage(GUIOperations.SET.toString(), Mapper.INSTANCE.pojoToJson(crate));
		}
		
		sendNotYetRenderedData(o);
	}
	
	private void sendNotYetRenderedData(GUIObject[] o) {
		if (notRenderedYet.size() > 0) {
			List<GAntObject> antsToRemove = new ArrayList<>();
			List<GFoodObject> foodsToRemove = new ArrayList<>();
			
			notRenderedYet.values().stream().forEach(af -> {
				antsToRemove.add(af.getAnt());
				foodsToRemove.add(af.getFood());
				}
			);
			
			remove(antsToRemove.stream().toArray(GAntObject[]::new));
			remove(foodsToRemove.stream().toArray(GFoodObject[]::new));
			
			this.CLIENT.postMessage(
				GUIOperations.SET.toString() + "/" + GUIObjectTypes.ANT_FOOD.toString(), 
				Mapper.INSTANCE.pojoToJson(mapNotYetRendered(o))
			);
		}
	}
	
	private GAntFoodObject[] mapNotYetRendered(GUIObject[] o) {
		List<GAntFoodObject> ret = new ArrayList<>();
		
		for (GUIObject it : o) {
			if (it.getType() == GUIObjectTypes.ANT) {
				GAntObject swp = (GAntObject)it;
				if (notRenderedYet.containsKey(swp)) {
					GAntFoodObject toAdd = notRenderedYet.remove(swp);
					toAdd.setLocation(swp.getLocation());
					ret.add(toAdd);
				}
			}
		}
		
		return ret.stream().toArray(GAntFoodObject[]::new);
	}
	
	private GUIObject[] map(GUIObject[] orig) {
		List<GUIObject> ret = new ArrayList<>(orig.length);
		for (GUIObject it : orig) {
			if (it.getType() == GUIObjectTypes.ANT) {
				GAntFoodObject mapped = getMapped((GAntObject)it);
				if (mapped != null && !notRenderedYet.containsValue(mapped)) {
					mapped.setLocation(it.getLocation());
					ret.add(mapped);
				} else {
					ret.add(it);
				}
			} else {
				ret.add(it);
			}
		}
		return ret.stream().toArray(GUIObject[]::new);
	}
	
	private GAntFoodObject getMapped(GAntObject ant) {
		return antFoodObjects.stream().filter(af -> af.getAnt().equals(ant)).findFirst().orElse(null);
	}

	public GAntFoodObject join(GAntObject ant, GFoodObject food) {
		GAntFoodObject gafo = getMapped(ant);
		
		if (!antFoodObjects.contains(gafo)) {
			gafo = new GAntFoodObject();
			gafo.setAnt(ant);
			gafo.setFood(food);
			
			antFoodObjects.add(gafo);
			notRenderedYet.put(ant, gafo);
		}
		
		return gafo;
	}
	
	public GUIObject[] separate(GAntObject ant) {
		List<GUIObject> retList = new ArrayList<>();
		
		GAntFoodObject gafo = getMapped(ant);
		if (antFoodObjects.contains(gafo)) {
			antFoodObjects.stream()
				.filter(afo -> afo.getAnt().equals(ant))
				.forEach(afo -> retList.add(afo.getFood()));
			antFoodObjects.remove(gafo);
			remove(gafo);
			set(ant);
		}
		
		return retList.stream().toArray(GUIObject[]::new);
	}
	
	public void separate(GFoodObject food) {
		//TODO
	}
	
	public void separate(GAntObject ant, GFoodObject food) {
		//TODO
	}
	
	public void remove(final GUIObject data) {
		remove(new GUIObject [] {data});
	}

	public void remove(final GUIObject[] data) {
		if (data.length > 0) {
			this.CLIENT.postMessage(GUIOperations.REMOVE.toString() + "/" + data[0].getType().toString(), Mapper.INSTANCE.pojoToJson(data));
		}
	}
{'fraction_non_alphanumeric': 0.14464174176853753, 'fraction_numerical': 0.0007138395645578656, 'mean_word_length': 3.909329829172142, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2494894', 'n_tokens_mistral': 4579, 'n_tokens_neox': 3895, 'n_words': 661}