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 VariableDefinition extends Definition {
	
//	private static final String ID_DEFAULT_VALUE = "default";
	private YObject defaultValue;
	private YClass yclass;	
	
//
//	private VariableDefinition(YClass yclass, String name, Element defaultValue) {
//		this(name, yclass.getClassPathString(), defaultValue);
//	}
	
//	public VariableDefinition(String name, String yclass, Element defaultValue) {
//		this(name, yclass());
//		this.classLink = yclass;
////		put( new SoftLink(ID_CLASS, yclass) );
//		
//		if (defaultValue != null) {
//			defaultValue.setName(ID_DEFAULT_VALUE);
//			this.defaultValue = defaultValue;
////			put( defaultValue );
//		}
//	}

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

	public ComplexClassDefinition getParent(){
		return (ComplexClassDefinition)super.getParent(); 
	} 	
//	public void setClassName(String className) {
//		//set(ID_CLASS, className);
//		classLink = className;
//	}
	
//	public void setWrapped(Method method){
//		
//		if (getWrapped() != null) {
//			getParent().getWrapped().removeElement(this);
//			getWrapped().removeMethod(getWrapped());
//			getWrapped().getOwnerClass().addMethod(method);
//		}
//		
//		wrapped = method;
//		method.setWrapperElement(this);
//	}
	
	public void setVarClass(YClass yclass){
		this.yclass = yclass;
	}
	
	public YClass getVarClass(){
		return yclass;
	}

//	public SoftLink getWrappedClass() {
//		return yclass.getPathString()
//	}

	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 ComplexClassDefinition getContainerClass(){
//		Container container = getParent();
//		while(!(container instanceof ClassDefinition))
//			container = container.getParent();
//		return (ComplexClassDefinition) container;
//	}
	
	public static class VariableDefinitionClass extends ElementDefinitionClass {

		private static String CLASS_NAME = "VariableDef";
		private static VariableDefinitionClass singleton;

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

		protected VariableDefinitionClass(String name)  {
			super(name, null);
		}
		
//		public VariableDefinition create(String name, String classPath, YObject value) {
//    		VariableDefinition newVarDef = new VariableDefinition(name, this);
//    		init(newVarDef);
//    		newVarDef.setWrappedClass(classPath);
//    		newVarDef.setDefaultValue(value);
//    		return newVarDef;
//    	}		
		
		public VariableDefinition create(String name, YClass yclass, YObject value) {
    		VariableDefinition newVarDef = new VariableDefinition(name, this);
    		init(newVarDef);
    		newVarDef.setVarClass(yclass);
    		newVarDef.setDefaultValue(value);
    		return newVarDef;
    	}
		
    	@Override
    	public VariableDefinition create(String name) {
    		VariableDefinition newVarDef = new VariableDefinition(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) {
    			
    			
    			VariableDefinition thisE = (VariableDefinition) thisElement;
    			String source = ((StringField)params.get(KEY_SOURCE)).getValue();
    			
    			VariableDefinition newDef = Synthetizer.createVariableDefinition(source);
    			
    			thisE.getParent().getWrapped().removeElement(thisE);
    			
    			
    			thisE.getParent().getWrapped().addElement(newDef);
//    			thisE.setName(newDef.getName());
//    			thisE.defaultValue = newDef.defaultValue;
//    			thisE.classLink = newDef.classLink;
    			
    			//thisE.setSource( newDef.getSource() );
    			thisE.synchronize();

    			return null;
    		}
    	}    	    	

	}	

}
