package hu.swankey.ammo.common.yggdrasil.definition;

import hu.swankey.ammo.common.script.AmmoScriptException;
import hu.swankey.ammo.common.script.yunits.YClass;
import hu.swankey.ammo.common.script.yunits.YMethod;
import hu.swankey.ammo.common.yggdrasil.basics.StringField;
import hu.swankey.ammo.common.yggdrasil.basics.YContainer;
import hu.swankey.ammo.common.yggdrasil.basics.YObject;

import java.util.Map;


public class ComplexClassDefinition extends ClassDefinition {
	
	public static final String KEY_FIELDS = "fields";
	
	protected ComplexClassDefinition(String name, ComplexClassDefinitionClass yclass){
		super(name, yclass);
	}
	
	
	public static ComplexClassDefinitionClass yclass(){
		return ComplexClassDefinitionClass.singleton();
	}
	

	
	public YContainer getFieldContainer(){
		return (YContainer)get(KEY_FIELDS);
	}
	

	public void addElement(VariableDefinition var) {
		getWrapped().addElement(var);
	}
	

	@Override
	public ComplexClass getWrapped() {
		return (ComplexClass) wrapped;
	}
	
	
	@Override
	public void synchronize(boolean report){
		super.synchronize(false);
		
		boolean changed = false;
		
		// Insert new fields:
		for(VariableDefinition varDef: getWrapped().getFields()){
		if (!getFieldContainer().containsKey(varDef.getName()) )
			getFieldContainer().put( varDef );
			varDef.setLogicalParent(this);
			changed = true;
		}
		
		// Remove removed superiors:
//		Iterator<YObject> it = getSuperiorsContainer().getElements().iterator();
//		while (it.hasNext()) {
//			YClass superior = (YClass) YObject.yclass().getRootPackage().get((SoftLink)it.next());
//			if ( !getWrapped().getSuperiors().contains(superior))
//				it.remove();
//		}
		
		if (changed && report)
			reportChange();
	}	
	
	
	public static class ComplexClassDefinitionClass extends ClassDefinitionClass {
		
		private static String CLASS_NAME = "ComplexClassDef";
		private static ComplexClassDefinitionClass singleton;
		
		public static ComplexClassDefinitionClass singleton(){
			if (singleton == null) {
				singleton = new ComplexClassDefinitionClass(CLASS_NAME);
				singleton.addSuperior( ClassDefinition.yclass() );
				singleton.addMethod( AddField.function );
				singleton.addElement( VariableDefinition.yclass().create(KEY_FIELDS, ContainerClass.getContainerClass(VariableDefinition.yclass()), null));				
				placeClass(singleton);
			}
			return singleton;
		}

		protected ComplexClassDefinitionClass(String name) {
			super(name);
		}
		
    	public ComplexClassDefinition create(ComplexClass wrappedYClass) {
    		ComplexClassDefinition classDef = new ComplexClassDefinition(wrappedYClass.getName(), this);
    		init(classDef);
    		classDef.setWrapped(wrappedYClass);
    		return classDef;
    	}		
		
    	@Override
    	public ComplexClassDefinition create(String name) {
    		ComplexClassDefinition classDef = new ComplexClassDefinition(name, this);
    		init(classDef);
    		
    		ComplexClass newClass = new ComplexClass(name, null);    		
    		classDef.setWrapped(newClass);
    		placeClass(newClass);
    		
    		return classDef;
    	}
    	    	
		
//    	@Override
//    	public ComplexClassDefinition create(String name) {
//    		ComplexClassDefinition classDef = create( new ComplexClass(name, null) );
//    		placeClass(classDef.getWrapped());
//    		return classDef;
//    	}
    	
	}
	
	private static class AddField extends YMethod {
		
	    private static final String FUNCTION_NAME = "addField";
	    private static final String KEY_CLASS = "yclass";
	    private static final String KEY_NAME = "name";
	    private static final YClass YCLASS_CLASS = ClassDefinition.yclass();
	    private static final YClass YCLASS_NAME = StringField.yclass();
	    
	    public static final AddField function = new AddField();

	    protected AddField() {
	        super(FUNCTION_NAME);
	        addParameter(KEY_CLASS, YCLASS_CLASS, null);
	        addParameter(KEY_NAME, YCLASS_NAME, null);
	    }

		@Override
		public YObject run(Map<String, YObject> params/*, Map<String, YObject> env*/, YObject thisElement) throws AmmoScriptException {
			YClass yclass = ((ClassDefinition)params.get(KEY_CLASS)).getWrapped();
			String name = ((StringField) params.get(KEY_NAME)).getValue();
			
			
			VariableDefinition varDef = VariableDefinition.yclass().create(name);
			varDef.setVarClass(yclass);
			
			((ComplexClassDefinition)thisElement).getWrapped().addElement( varDef );
			
			
			
	        return null;
	    }
	}

}
