package org.dynalang.mop.impl.test;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.dynalang.mop.ClassBasedMetaobjectProtocol;
import org.dynalang.mop.CallProtocol;
import org.dynalang.mop.impl.MetaobjectProtocolBase;

public class DummyMetaobjectProtocol2 extends MetaobjectProtocolBase implements ClassBasedMetaobjectProtocol {
    
    public boolean isAuthoritativeForClass(Class clazz) {
        return clazz == DynaObject2.class;
    }
    
    public Object call(Object callable, CallProtocol callProtocol, Map args) {
	return isDynaObject2(callable) ? "called2-named" : Result.noAuthority; 
    }

    public Object call(Object callable, CallProtocol callProtocol, 
	    Object... args) {
	return isDynaObject2(callable) ? "called2-positional" : Result.noAuthority; 
    }
    public Result delete(Object target, Object propertyId) {
        if(isAuthoritative(target, propertyId)) {
            DynaObject2 do2 = (DynaObject2)target;
            if(do2.propertyDefined) {
        	do2.propertyDefined = false;
        	do2.property = null;
        	return Result.ok;
            }
        }
        return Result.noAuthority;
    }

    public Object get(Object target, Object propertyId) {
        if(isAuthoritative(target, propertyId)) {
            DynaObject2 do2 = (DynaObject2)target;
            return do2.propertyDefined ? do2.property : Result.noAuthority;
        }
        return Result.noAuthority;
    }

    public Boolean has(Object target, Object propertyId) {
        if(isAuthoritative(target, propertyId)) {
            DynaObject2 do2 = (DynaObject2)target;
            return do2.propertyDefined ? Boolean.TRUE : null;
        }
        return null;
    }

    private boolean isAuthoritative(Object target, Object propertyId) {
	return isDynaObject2(target) && "prop2".equals(propertyId);
    }

    public Iterator<Entry> properties(Object target) {
	if(isDynaObject2(target)) {
	    DynaObject2 do2 = (DynaObject2)target;
	    if(do2.propertyDefined) {
                Map m = new HashMap();
                m.put("prop2", do2.property);
                return m.entrySet().iterator();
	    }
	}
	return Collections.EMPTY_MAP.entrySet().iterator();
    }

    public Result put(Object target, Object propertyId, Object value,
	    CallProtocol callProtocol) {
        if(isAuthoritative(target, propertyId)) {
            DynaObject2 do2 = (DynaObject2)target;
            do2.propertyDefined = true;
            do2.property = value;
            return Result.ok;
        }
        return Result.noAuthority;
    }

    public Object representAs(Object object, Class targetClass) {
	return isDynaObject2(object) && targetClass == String.class ? 
		((DynaObject2)object).property : Result.noAuthority;
    }

    private boolean isDynaObject2(Object object) {
	return object instanceof DynaObject2;
    }
}