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

import hu.swankey.ammo.common.script.yunits.YClass;
import hu.swankey.ammo.common.script.yunits.YMethod;

import java.util.Map;

public class Field extends YObject {

    /** Value of the field */
    private Object value;

    /** Instantiate a general field */
    public Field(String name) {
        this(name, yclass(), null);
    }

    /** Instantiate a general field */
    protected Field(String name, FieldClass type, Object value) {
        super(name, type);
        
        if (value == null)
        		setValue(getYClass().getDefaultValue());
        else
        	setValue(value);
    }
    
    public static FieldClass yclass(){
    	return FieldClass.singleton();
    }

//    public Object getDefaultValue() {
//        return ((FieldType)getType()).getDefaultValue();
//    }

    /** Set the field's value */
    public void setValue(Object value) {
        if (value == null) {
            throw new NullPointerException("A Field's value cannot be null.");
        }
        
        if (container != null)
            container.reportChangedElement(this);

        this.value = value;
    }

    /** Get the field's value */
    public Object getValue() {
        return value;
    }

//    @Override
//    public boolean equals(Object o){
//		if (!(o instanceof Field))
//			return false;
//		
//		return ((Field)o).getValue().equals(getValue());
//    }
    
    public int hashCode(){
    	return value.hashCode();
    }
    
	@Override
	public String toString() {
		return value.toString();
	}


//    PUBLIC ELEMENT COMPUTE(MAP<STRING, ELEMENT> ENVRIONMENT) THROWS AMMOSCRIPTEXCEPTION {
//        RETURN THIS;
//    }
//    
    public FieldClass getYClass(){
        return (FieldClass) super.getYClass();
    }
        
    
    public static class FieldClass extends YClass {

        /** The name of the type */
        private static final String CLASS_NAME = "Field";
        
        /** The instantiated type */
        private static FieldClass singleton;

        /** Default value */
        private static final Object DEFAULT_VALUE = 0;
        
        public static FieldClass singleton() {
        	if (singleton == null) {
        		singleton =  new FieldClass(CLASS_NAME);
        		singleton.addSuperior( YObject.yclass() );
                singleton.addMethod(Assignment.function);
        		placeClass(singleton);
        	}
        	return singleton;
        }




        /** Instantiate a general FieldType */
        /*private FieldType() {
            super(TYPENAME);
        }*/



        /** Instantiate a specific FieldType */
        protected FieldClass(String name) {
            super(name, null);
        }



//        public Object getDefaultValue() {
//            return DEFAULT_VALUE;
//        }


	    
	    public YObject create(String name) {
	         return new Field(name, this, null);
	    }

//        @Override
//        public Field create(String name, Object value) {
//            return new Field(name, value);
//        }



//        /** Get the instantiated general FieldType */
//        public static FieldType type() {
//            return TYPE;
//        }



        /** Get the name of the type */
        @Override
        public String getName() {
            return CLASS_NAME;
        }
        
        public Object getDefaultValue() {
            return DEFAULT_VALUE;
        }
    }
    
    
    private static class Assignment extends YMethod {

        private static final String FUNCTION_NAME = "=";
        private static final String KEY_VALUE = "value";
        private static final YClass YCLASS_VALUE = FieldClass.singleton();

        public static final Assignment function = new Assignment();

        protected Assignment() {
            super(FUNCTION_NAME);
            addParameter(KEY_VALUE, YCLASS_VALUE, null);
            setReturnType(IntegerField.yclass());
        }

        @Override
        public YObject run(Map<String, YObject> params, YObject thisElement) {
            
            int newValue = ((IntegerField)params.get(KEY_VALUE)).getValue();
            ((Field)thisElement).setValue( newValue );

            return thisElement;
        }
    }       
}