/*
 * @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 net.ranides.assira.collection.query.CQuery;
import net.ranides.assira.generic.SerializationUtils;
import net.ranides.assira.reflection.*;
import net.ranides.assira.text.StrBuilder;

import java.io.Serializable;
import java.lang.reflect.Parameter;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * This is default implementation of IArguments.
 * Storage behaviour is defined by base class {@link AElements}.
 *
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 */
public class AArguments extends AElements<IArgument> implements IArguments, Serializable {

    private static final IArguments EMPTY = new AArguments(IHints.none(), CQuery.empty());

    /**
     * Internal method, used by {@link IArguments#empty()}
     *
     * @return IArguments
     */
    public static IArguments $empty() {
        return EMPTY;
    }

    AArguments(IHints hints, CQuery<IArgument> stream) {
        super(hints, stream);
    }
    
    @Override
    public List<String> names() {
        return list(IArgument::name);
    }

    @Override
    public IClasses types() {
        return FElements.newClasses(IHints.none(), stream(IArgument::type));
    }
    
    @Override
    public IExecutables<? extends IExecutable> parent() {
        return FElements.newExecutables(IHints.none(), stream(IArgument::parent));
    }

    @Override
    public Map<String, IArgument> map() {
        return stream().collect(Collectors.toMap(IArgument::name, a -> a));
    }

    @Override
    public CQuery<Parameter> reflective() {
        return stream().map(IArgument::reflective);
    }

    @Override
    public String toString() {
        return new StrBuilder().open("(", ")", ",").append(list()).toString();
    }

    protected Object writeReplace() {
        final IHints cHints = this.hints();
        final List<IArgument> cList = this.list();
        return SerializationUtils.proxy(() -> FElements.newArguments(cHints, CQuery.from(cList)));
    }
}
