package leigh.conflux.nodegraph;

import leigh.eo.EO;
import leigh.eo.EOLoop;
import leigh.mecha.log.MechaLogger;
import leigh.mecha.log.MechaLoggerFactory;
import leigh.mecha.nodegraph.Node;
import leigh.mecha.nodegraph.ProcessorState;
import leigh.mecha.nodegraph.UselessAttribute;

import java.io.Serializable;

/**
 * A {@link Node} which provides aggregate row operations.
 *
 * @author Alex Leigh
 */
public abstract class AggregateNode extends Node {
    public static final String NODE_NAME = "leigh.conflux.v1.Aggregate";
    public static final String KEY_INPUT_OBJECTS = "objs";
    public static final String KEY_OUTPUT_VALUE = "value";
    private static final MechaLogger logger = MechaLoggerFactory.getLogger(AggregateNode.class);

    public static AggregateNode build(String type, String id) {
        switch (type) {
            case "sum":
                return new SumNode(id);
            case MinNode.TYPE:
                return new MinNode(id);
            case MaxNode.TYPE:
                return new MaxNode(id);
            case CountNode.TYPE:
                return new CountNode(id);
            case AverageNode.TYPE:
                return new AverageNode(id);
        }
        throw new IllegalStateException("Unknown aggregate type: " + type);
    }

    public AggregateNode(String id) {
        super(id);
        addOutput(KEY_OUTPUT_VALUE, new UselessAttribute() {
            public Serializable getSingleValue(ProcessorState state) throws Exception {
                start(state);
                logger.info("KEY_OUTPUT_VALUE read...");
                EOLoop rows = getInputObjects(KEY_INPUT_OBJECTS, state);
                logger.info("Located rows: {}", rows);
                String key = getInputStaticString(KEY_INPUT_OBJECTS, state);
                for (EO eo : rows) {
                    processRow(eo, key, state);
                }
                return finish(state);
            }
        });
    }

    public abstract void start(ProcessorState state);

    public abstract void processRow(EO row, String key, ProcessorState state) throws Exception;

    public abstract Serializable finish(ProcessorState state);
}
