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

import hu.swankey.ammo.common.script.Synthetizer;
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.YObject;

import java.util.Map;

public class YAttributeDefinition extends Definition {
	

	private YObject defaultValue;
	private YClass yclass;	
	

	protected YAttributeDefinition(String name, YAttributeDefinitionClass yclass) {
		super(name, yclass);
	}
	
	public static YAttributeDefinitionClass yclass() {
		return YAttributeDefinitionClass.singleton();
	}

	public ComplexYClassDefinition getLogicalParent(){
		return (ComplexYClassDefinition)super.getLogicalParent(); 
	} 	
	
	public void setVarClass(YClass yclass){
		this.yclass = yclass;
	}
	
	public YClass getVarClass(){
		return yclass;
	}


	public void setDefaultValue(YObject value) {
		this.defaultValue = value;
	}

	public YObject getDefaultValue() {
		return defaultValue;
	}

	public void setElementAccessLevel(int newLevel){
		setAccessLevel(newLevel);
	}
	
	@Override
	public void synchronize() {
		// TODO Auto-generated method stub
		
	}	

	public YObject getWrappedElement() {
		
//		Element defaultValue = get(ID_DEFAULT_VALUE);

		if (defaultValue != null) {
			
			try {
				YObject value = (YObject) defaultValue.clone();
				value.setName(getName());
				return value;
			} catch (CloneNotSupportedException e) {
				throw new RuntimeException(e);
			}
			
		} else {
			//YClass yclass = YClass.getYClass( getWrappedClass().getPathStrArray() );
			
			
//			if (yclass == null)
//				throw new AmmoException("Class not found: '" + getWrappedClass().getValue() + "'");			
			
			YObject element = yclass.create(getName());
			element.setAccessLevel(getAccessLevel());
			return element;

		}
	}
	
	
	public static class YAttributeDefinitionClass extends DefinitionClass {

		private static String CLASS_NAME = "YAttributeDefinition";
		private static YAttributeDefinitionClass singleton;

		public static YAttributeDefinitionClass singleton() {
			
			if (singleton == null) {
				singleton = new YAttributeDefinitionClass(CLASS_NAME);
				singleton.addSuperior(Definition.yclass());
				singleton.addMethod(SetSource.function);
				placeClass(singleton);
			}
			return singleton;
		}

		protected YAttributeDefinitionClass(String name)  {
			super(name, null);
		}
		
		
		public YAttributeDefinition create(String name, YClass yclass, YObject value) {
    		YAttributeDefinition newVarDef = new YAttributeDefinition(name, this);
    		init(newVarDef);
    		newVarDef.setVarClass(yclass);
    		newVarDef.setDefaultValue(value);
    		return newVarDef;
    	}
		
    	@Override
    	public YAttributeDefinition create(String name) {
    		YAttributeDefinition newVarDef = new YAttributeDefinition(name, this);
    		init(newVarDef);
    		return newVarDef;
    	}
    	
    	private static class SetSource extends YMethod {

    		private static final String FUNCTION_NAME = "setSource";
    		private static final String KEY_SOURCE = "source";
    		private static final YClass YCLASS_SOURCE = StringField.yclass();

    		public static final SetSource function = new SetSource();

    		protected SetSource() {
    			super(FUNCTION_NAME);
    			addParameter(KEY_SOURCE, YCLASS_SOURCE, null);
    			setReturnType( YObject.yclass() );
    		}

    		@Override
    		public YObject run(Map<String, YObject> params,/* Map<String, YObject> env,*/ YObject thisElement) {
    			
    			
    			YAttributeDefinition thisE = (YAttributeDefinition) thisElement;
    			String source = ((StringField)params.get(KEY_SOURCE)).getValue();
    			
    			YAttributeDefinition newDef = Synthetizer.createVariableDefinition(source);
    			
    			thisE.getLogicalParent().getWrapped().removeElement(thisE);
    			
    			
    			thisE.getLogicalParent().getWrapped().addElement(newDef);

    			thisE.synchronize();

    			return null;
    		}
    	}    	    	

	}	

}
