package framework.component;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Iterator;
import main.L;
import framework.component.filter.ComponentFilter;
import framework.component.list.ChildrenComponentList;
import framework.component.list.MultiTypeComponentList;
import framework.component.list.SingleTypeComponentList;
import framework.event.Event;
import framework.event.EventSender;
import framework.event.EventSystem;
import framework.io.CustomInputStream;
import framework.io.CustomOutputStream;
import framework.io.component.ComponentLoader;
public class ParentComponent extends Component implements MultiTypeComponentList{
private final ChildrenComponentList children = new ChildrenComponentList();
private String label;
public ParentComponent(String label){
super();
if(label != null){
setLabel(label);
}
}
public ParentComponent(){
this(null);
}
public ParentComponent(CustomInputStream in, int baseID, byte formatVersion) throws IOException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException {
super(in, baseID, formatVersion);
if(formatVersion == 0){
int numChildren = in.readInt();
for(int i = 0; i < numChildren; i++){
addComponent(ComponentLoader.loadComponent(in,false,false));
}
}
}
@Override
public void writeToStream(CustomOutputStream out) throws IOException {
super.writeToStream(out);
out.writeInt(size());
for(Component c: getAllComponents()){
c.writeToStream(out);
}
}
public Component getChildByType(String type){
SingleTypeComponentList children = getChildrenByType(type);
if(children != null){
return children.getComponent(0);
}else{
return null;
}
}
public SingleTypeComponentList getChildrenByType(String type){
return children.getComponentsOfType(type);
}
public MultiTypeComponentList getChildren(){
return children;
}
@Override
public boolean allowSameTypedSiblings() {
return true;
}
@Override
public Component getComponent(String type, int slot) {
return children.getComponent(type, slot);
}
@Override
public Collection<Component> getAllComponents() {
return children.getAllComponents();
}
@Override
public Collection<Component> getComponents(ComponentFilter filter) {
return children.getComponents(filter);
}
@Override
public void addComponent(Component c) {
if(c != null){
if(c instanceof ParentComponent){
if(c.getUniqueID() == this.getUniqueID() || ((ParentComponent) c).isAncestorOf(this)){
return;
}
}
if(!c.allowSameTypedSiblings()){
removeComponent(c.getType(), 0);
}
c.setParent(this);
for(SingleTypeComponentList list: children){
for(Component sibling:list){
sibling.onSiblingAdded(c);
}
}
children.addComponent(c);
EventSystem.getInstance().pushEvent(new ChildAddedEvent(this, c));
}else{
L.e("Tried to add ancestor ("+c+")to child component ("+this+")!");
}
}
public int getSlotForComponent(Component c){
return children.getSlotFor(c);
}
public int getSlotForComponent(String type, int uniqueID){
return children.getSlotFor(type, uniqueID);
}
@Override
public int getNextFreeSlot(String type, boolean reuseOldSlots) {
return children.getNextFreeSlot(type, reuseOldSlots);
}
@Override
public Component removeComponent(String type, int slot) {
Component child = children.removeComponent(type, slot);
if(child != null){
child.setParent(null);
EventSystem.getInstance().pushEvent(new ChildRemovedEvent(this, child));
}
return child;
}
public void removeComponent(Component c){
if(c != null){
removeComponent(c.getType(), getSlotForComponent(c));
}
}
@Override
public SingleTypeComponentList getComponentsOfType(String type) {
return children.getComponentsOfType(type);
}
@Override
public int size() {
return children.size();
}
@Override
protected byte getDataFormatVersion() {
return 0;
}
@Override
protected void onDestroy() {
for(SingleTypeComponentList list: children){
for(Component child:list){
child.destroy();
}
}
if(getLabel() != null){
ComponentSystem.getInstance().removeComponentForLabel(getLabel());
}
super.onDestroy();
}
public static final class ChildAddedEvent extends Event{
private final Component child;
public ChildAddedEvent(EventSender sender, Component child) {
super(sender);
this.child = child;
}
@Override
protected final String getEventTypeID() {
return "ChildAdded";
}
public final Component getChild(){
return child;
}
}
public static final class ChildRemovedEvent extends Event{
private final Component child;
public ChildRemovedEvent(EventSender sender, Component child) {
super(sender);
this.child = child;
}
@Override
protected final String getEventTypeID() {
return "ChildRemoved";
}
public final Component getChild(){
return child;
}
}
@Override
public int getNumTypes() {
return children.getNumTypes();
}
@Override
public Collection<String> getTypeNames() {
return children.getTypeNames();
}
public final boolean isAncestorOf(ParentComponent p){
while(p != null){
if(p.equals(this)){
return true;
}
p = p.getParent();
}
return false;
}
@Override
public Iterator<SingleTypeComponentList> iterator() {
return children.iterator();
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
ComponentSystem.getInstance().setComponentLabel(this, label);
}
}