/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.ov.mixing.commons.tools;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.scytl.ov.mixing.commons.beans.IntPair;
import com.scytl.ov.mixing.commons.configuration.MatrixDimensions;

/**
 * Adaptor for IntPairCalculator that returns a List<MatrixDimensions> object as a output
 */
public class MatrixCalculator {

    private static final Logger LOG = LoggerFactory.getLogger("std");

    private final IntPairCalculator intPairCalculator = new IntPairCalculator();

    public List<MatrixDimensions> generateCombinationsWithoutOnes(final int n) {

        List<IntPair> result = intPairCalculator.generateTwoFactorCombinationsWithoutOnes(n);

        return fromIntegerToMatrix(result);
    }

    public List<MatrixDimensions> generateAllCombinations(final int n) {

        List<IntPair> result = intPairCalculator.generateAllTwoFactorCombinations(n);

        return fromIntegerToMatrix(result);
    }

    public List<MatrixDimensions> getMostOptimalCombination(final int n) {

        List<IntPair> result = intPairCalculator.getMostOptimalCombination(n);

        return fromIntegerToMatrix(result);
    }

    /**
     * @param combinations
     * @return
     */
    public MatrixDimensions getMatrixWithSmallestM(final List<MatrixDimensions> combinations) {

        if (combinations.isEmpty()) {
            LOG.error("There are not any combination to get the minor m!");
            return null;
        }

        int minorRow = Integer.MAX_VALUE;
        for (MatrixDimensions combination : combinations) {
            if (combination.getNumberOfRows() < minorRow) {
                minorRow = combination.getNumberOfRows();
            }
        }

        List<MatrixDimensions> candidates = new ArrayList<>();
        for (MatrixDimensions combination : combinations) {
            if (combination.getNumberOfRows() == minorRow) {
                candidates.add(combination);
            }
        }

        if (candidates.size() > 1) {
            LOG.error("There are more than 1 possible minor m for this combination! Returning the first one...");

        }

        return candidates.get(0);
    }

    /**
     * @param result
     * @return
     */
    private static List<MatrixDimensions> fromIntegerToMatrix(final List<IntPair> result) {
        List<MatrixDimensions> matrixDimensions = new ArrayList<>();
        for (IntPair integerPair : result) {
            MatrixDimensions dimensions = new MatrixDimensions(integerPair.getLeft(), integerPair.getRight());
            matrixDimensions.add(dimensions);
        }

        return matrixDimensions;
    }

}
