package stexfires.core.modifier;

import stexfires.core.Record;
import stexfires.core.record.StandardRecord;

import java.util.*;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.stream.Stream;

/**
 * @author Mathias Kalb
 * @since 0.1
 */
public class UnpivotModifier<T extends Record, R extends Record> implements RecordStreamModifier<T, R> {

    protected final Function<? super T, Stream<? extends R>> unpivotFunction;

    public UnpivotModifier(Function<? super T, Stream<? extends R>> unpivotFunction) {
        Objects.requireNonNull(unpivotFunction);
        this.unpivotFunction = unpivotFunction;
    }

    public static <T extends Record, R extends Record> UnpivotModifier<T, R> getInstance(Function<? super T, Collection<? extends R>> unpivotFunction) {
        Objects.requireNonNull(unpivotFunction);
        return new UnpivotModifier<>(record -> unpivotFunction.apply(record).stream());
    }

    public static <T extends Record> UnpivotModifier<T, Record> getInstance(int keyIndex, IntFunction<String> nameFunction) {
        Objects.requireNonNull(nameFunction);
        return new UnpivotModifier<>(record -> {
            List<StandardRecord> list = new ArrayList<>(record.size() - 1);
            for (int i = 0; i < record.size(); i++) {
                if (i == keyIndex) {
                    continue;
                }
                list.add(new StandardRecord(record.getCategory(), record.getRecordId(), record.getValueAt(keyIndex), nameFunction.apply(i), record.getValueAt(i)));
            }
            return list.stream();
        });
    }

    public static <T extends Record> UnpivotModifier<T, Record> getInstance(int keyIndex) {
        return getInstance(keyIndex, String::valueOf);
    }

    public static <T extends Record> UnpivotModifier<T, Record> getInstance(int keyIndex, Map<Integer, String> nameMap) {
        Objects.requireNonNull(nameMap);
        return getInstance(keyIndex, nameMap::get);
    }

    @Override
    public Stream<R> modify(Stream<T> recordStream) {
        return recordStream.map(unpivotFunction).flatMap(Function.identity());
    }

}

@@ -1989,24 +1989,2078 @@
 et);%0A    %7D%0A%0A
+    public static %3CT extends Record%3E UnpivotModifier%3CT, Record%3E getInstance(List%3CInteger%3E keyIndexes,%0A                                                                            List%3CList%3CInteger%3E%3E pivotIndexes,%0A                                                                            IntFunction%3CString%3E pivotIndexFunction) %7B%0A        Objects.requireNonNull(keyIndexes);%0A        Objects.requireNonNull(pivotIndexes);%0A        return new UnpivotModifier%3C%3E(record -%3E %7B%0A            int maxSize = pivotIndexes.stream().mapToInt(list -%3E list.size()).max().orElse(0);%0A            int valuesSize = keyIndexes.size() + pivotIndexes.size();%0A            if (pivotIndexFunction != null) %7B%0A                valuesSize++;%0A            %7D%0A            List%3CStandardRecord%3E records = new ArrayList%3C%3E(maxSize);%0A            for (int pivotIndex = 0; pivotIndex %3C maxSize; pivotIndex++) %7B%0A                List%3CString%3E newValues = new ArrayList%3C%3E(valuesSize);%0A%0A                for (int j = 0; j %3C keyIndexes.size(); j++) %7B%0A                    newValues.add(record.getValueAt(keyIndexes.get(j)));%0A                %7D%0A                for (int j = 0; j %3C pivotIndexes.size(); j++) %7B%0A                    if (pivotIndexes.get(j).size() %3E pivotIndex) %7B%0A                        newValues.add(record.getValueAt(pivotIndexes.get(j).get(pivotIndex)));%0A                    %7D else %7B%0A                        newValues.add(null);%0A                    %7D%0A                %7D%0A                if (pivotIndexFunction != null) %7B%0A                    newValues.add(pivotIndexFunction.apply(pivotIndex));%0A                %7D%0A%0A                records.add(new StandardRecord(record.getCategory(), record.getRecordId(), newValues));%0A            %7D%0A            return records.stream();%0A        %7D);%0A    %7D%0A%0A    public static %3CT extends Record%3E UnpivotModifier%3CT, Record%3E getInstance(List%3CInteger%3E keyValues, List%3CList%3CInteger%3E%3E p, boolean addPivotIndex) %7B%0A        if (addPivotIndex) %7B%0A            return getInstance(keyValues, p, String::valueOf);%0A        %7D%0A        return getInstance(keyValues, p, null);%0A    %7D%0A%0A
     @Overrid

Add new getInstance method to UnpivotModifier