/*
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */

package net.ranides.assira.reflection.impl;

import java.io.Serializable;
import java.lang.reflect.Parameter;

import net.ranides.assira.collection.query.CQuery;
import net.ranides.assira.reflection.*;

/**
 * Basic implementation of IArgument.
 * It stores type and name explicitly.
 *
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 */
public class CArgument extends AElement implements IArgument, Serializable {

    private static final long serialVersionUID = 1L;
    
    private static final IAttributes NORMAL = IAttributes.of(IAttribute.DECLARED, IAttribute.PACKAGE).immutable();
    
    private static final IAttributes GENERIC = IAttributes.of(IAttribute.DECLARED, IAttribute.PACKAGE, IAttribute.PARAMETERIZED).immutable();

    private final IClass<?> type;

    private final String name;

    CArgument(String name, IClass<?> type) {
        this.type = type;
        this.name = name;
    }

    @Override
    public IContext context() {
        return IContext.getDefault();
    }
        
    @Override
    public IArguments collect() {
        return FElements.newArguments(IHints.none(), CQuery.from().value(this));
    }

    @Override
    public IClass<?> type() {
        return type;
    }

    @Override
    public IExecutable parent() {
        throw new IReflectiveException("IArgument does not define parent");
    }

    @Override
    public Parameter reflective() {
        throw new IReflectiveException("IArgument is not reflective");
    }

    @Override
    public String name() {
        if(null == name) {
            throw new IReflectiveException("IArgument does not have information about name");
        }
        return name;
    }

    @Override
    public IAttributes attributes() {
        return type.attributes().contains(IAttribute.PARAMETERIZED) ? GENERIC : NORMAL;
    }

    @Override
    public IAnnotations annotations() {
        return IAnnotations.empty();
    }

    @Override
    public final int hashCode() {
        return this.type().hashCode();
    }

    @Override
    public final boolean equals(Object object) {
        return (object instanceof IArgument) && ((IArgument)object).type().equals(type());
    }
    
}
