package net.onedaybeard.dominatrix.experimental.ui;
import java.util.Comparator;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;
import com.artemis.EntitySystem;
import com.artemis.World;
import com.artemis.utils.ImmutableBag;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.scenes.scene2d.utils.Align;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Sort;
/**
* Shows a table for toggling systems held by {@link World}.
*/
public final class SystemsHud
{
private static final int PADDING = 10;
private static final int COLUMNS = 5;
private Window systemsWindow;
public SystemsHud(Skin skin, Stage ui, World world)
{
systemsWindow = createSystemWindow(skin, world);
systemsWindow.setPosition(ui.getWidth() / 2 - systemsWindow.getWidth() / 2,
ui.getHeight() - systemsWindow.getHeight() - PADDING);
systemsWindow.setVisible(false);
ui.addActor(systemsWindow);
}
public void toggle()
{
systemsWindow.setVisible(!systemsWindow.isVisible());
}
public boolean isVisible()
{
return systemsWindow.isVisible();
}
public void setVisible(boolean visible)
{
systemsWindow.setVisible(visible);
}
private static Window createSystemWindow(Skin skin, World world)
{
SortedMap<String, Array<EntitySystem>> systemMap =
new TreeMap<String, Array<EntitySystem>>();
ImmutableBag<EntitySystem> systems = world.getSystems();
String commonPackage = findCommonPackage(systems);
for (int i = 0, s = systems.size(); s > i; i++)
{
addSystemToMap(systemMap, systems.get(i), commonPackage.length());
}
Window w = new Window("systems", skin);
w.defaults().pad(PADDING).align(Align.center);
for (Entry<String, Array<EntitySystem>> entry : systemMap.entrySet())
{
if (!entry.getKey().equals(""))
{
w.row();
w.add(entry.getKey()).colspan(COLUMNS).fillX();
}
addSystemsToWindow(w, skin, entry.getValue());
}
w.pack();
return w;
}
private static String findCommonPackage(ImmutableBag<EntitySystem> systems)
{
String prefix = "";
// String prefix = systems.get(0).getClass().getPackage().getName();
for (int i = 1, s = systems.size(); s > i; i++)
{
String p = systems.get(i).getClass().getPackage().getName();
for (int j = 0, l = Math.min(prefix.length(), p.length()); l > j; j++)
{
if (prefix.charAt(j) != p.charAt(j))
{
prefix = prefix.substring(0, j);
break;
}
}
}
return prefix;
}
private static void addSystemsToWindow(Window w, Skin skin, Array<EntitySystem> systems)
{
Sort.instance().sort(systems, new SystemNameComparator());
for (int i = 0; systems.size > i; i++)
{
if (i % COLUMNS == 0)
w.row();
w.add(addButton(skin, systems.get(i))).fillX();
}
}
private static void addSystemToMap(SortedMap<String,Array<EntitySystem>> systemMap, EntitySystem system, int offset)
{
String p = system.getClass().getPackage().getName().substring(offset);
if (p.startsWith("."))
p = p.substring(1);
if (!systemMap.containsKey(p))
systemMap.put(p, new Array<EntitySystem>());
systemMap.get(p).add(system);
}
private static TextButton addButton(Skin skin, final EntitySystem system)
{
String title = system.getClass().getSimpleName().replaceAll("System$", "");
final TextButton button = new TextButton(title, skin.get("toggle", TextButtonStyle.class));
button.setChecked(!system.isEnabled());
button.addListener(new ClickListener()
{
@Override
public void clicked(InputEvent event, float x, float y)
{
system.setEnabled(!system.isEnabled());
event.cancel();
}
});
return button;
}
private static final class SystemNameComparator implements Comparator<EntitySystem>
{
@Override
public int compare(EntitySystem o1, EntitySystem o2)
{
return o1.getClass().getSimpleName().compareTo(o2.getClass().getSimpleName());
}
}
}