package railo.runtime.db;

import java.io.Serializable;
import java.sql.Types;

import railo.commons.lang.SizeOf;
import railo.runtime.exp.PageException;
import railo.runtime.op.Caster;
import railo.runtime.type.Sizeable;


/**
 * 
 */
public class SQLItemImpl implements SQLItem,Serializable,Sizeable {

	/** Yes or No. Indicates whether the parameter is passed as a null. If Yes, the tag ignores the 
	** 	value attribute. The default is No. */
	private boolean nulls;

	/** Specifies the actual value that Railo passes to the right of the comparison operator in a 
	** 	where clause. */
	private Object value;
	private Object cfValue;


	/** Number of decimal places of the parameter. The default value is zero. */
	private int scale=0;

	/** The SQL type that the parameter (any type) will be bound to. */
	private int type=Types.CHAR;

    private boolean isValueSet;
    
    /**
     * constructor of the class
     */
    public SQLItemImpl() {}
    
    /**
     *  constructor of the class
     * @param value
     */
    public SQLItemImpl(Object value) {
        this.value=value;
    }
    
    /**
     *  constructor of the class
     * @param value
     */
    public SQLItemImpl(Object value, int type) {
        this.value=value;
        this.type=type;
    }

    @Override
    public boolean isNulls() {
        return nulls;
    }
    @Override
    public void setNulls(boolean nulls) {
        this.nulls = nulls;
    }
    @Override
    public int getScale() {
        return scale;
    }
    @Override
    public void setScale(int scale) {
        this.scale = scale;
    }
    @Override
    public Object getValue() {
        return value;
    }
    @Override
    public void setValue(Object value) {
        isValueSet=true;
        this.value = value;
    }
    
    @Override
    public int getType() {
        return type;
    }
    @Override
    public void setType(int type) {
        this.type = type;
    }
    
    @Override
    public SQLItem clone(Object object) {
       
        SQLItemImpl item = new SQLItemImpl();
        item.nulls=nulls;
        item.scale=scale;
        item.type=type;
        item.value=object;
        return item;
    }
    
    @Override
    public Object getValueForCF() throws PageException {
        if(cfValue==null) {
            cfValue=SQLCaster.toCFTypex(this);
        }
        return cfValue;
    }
    
    @Override
    public boolean isValueSet() {
        return isValueSet;
    }
    
    public String toString() {
    	try {
			return Caster.toString(getValueForCF(),"");
		} catch (PageException e) {
			return Caster.toString(getValue(),"");
		}
    }

	public long sizeOf() {
		return SizeOf.size(this.cfValue)+
		SizeOf.size(this.isValueSet)+
		SizeOf.size(this.nulls)+
		SizeOf.size(this.value);
	}

	
	public static SQLItem duplicate(SQLItem item) {
		if(!(item instanceof SQLItemImpl)) return item;
		return ((SQLItemImpl) item).duplicate();
	}

	public SQLItem duplicate() {
		SQLItemImpl rtn = new SQLItemImpl(value,type);
		rtn.nulls=nulls;
		rtn.cfValue=cfValue;
		rtn.isValueSet=isValueSet;
		rtn.scale=scale;
		return rtn;
	}
}