package ec.gp.semantic.utils;

import ec.gp.GPNode;
import ec.gp.semantic.func.SimpleNodeBase;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * Class that joins list of programs/instructions using given instruction.
 */
public class InstructionJoiner {

	public static SimpleNodeBase<?> join(List<SimpleNodeBase<?>> toJoin, Class joinUsing, int arity) {
		assert toJoin.size() > 0;
		try {
			while (toJoin.size() > 1) {
				assert toJoin.size() >= arity : "Number of elements in toJoin is not dividable by arity";

				List<SimpleNodeBase<?>> newList = new ArrayList<SimpleNodeBase<?>>();

				SimpleNodeBase<?> top = null;
				int chIndex = 0;

				for (int i = 0; i < toJoin.size() - toJoin.size() % arity; ++i) {
					if (top == null) {
						top = (SimpleNodeBase<?>) joinUsing.newInstance();
						top.children = new GPNode[arity];
						chIndex = 0;
					}

					top.children[chIndex++] = toJoin.get(i);

					if (chIndex >= top.children.length) {
						newList.add(top);
						top = null;
					}
				}

				for (int i = toJoin.size() - toJoin.size() % arity; i < toJoin.size(); ++i) {
					newList.add(toJoin.get(i));
				}

				toJoin = newList;
			}


			return toJoin.iterator().next();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

}
