package com.sourcefellows.sideeffects;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

public class Beispiel2 {

    public static void main(String[] args) {
        int[][] matrix = Beispiel.data;

        Predicate<Integer> greaterThanFive = i -> i > 5;
        Predicate<Integer> smallerThanFour = i -> i < 4;

        List<Integer> rowIdx = rowIndexesWithValuesInFirstColumn(matrix, Beispiel2::isEven);
        for (int idx : rowIdx) {
            var currentRow = matrix[idx];

            List<Integer> indexesOfValues = columnIndexesOfValues(currentRow, greaterThanFive);
            if (indexesOfValues.isEmpty()) {
                continue;
            }

            Predicate<Integer> currentIndexPlusOne = i -> i == idx + 1;
            if (!containsRowWithValues(matrix, currentIndexPlusOne, smallerThanFour)) {
                continue;
            }

            var indexToUse = indexesOfValues.getFirst();
            System.out.println("Data point found: " + currentRow[indexToUse]);
            return;

        }

    }

    private static boolean containsRowWithValues(int[][] matrix, Predicate<Integer> predicateFirstColumn, Predicate<Integer> predicateOtherColumns) {
        List<int[]> secondRows = rowsWithValuesInFirstColumn(matrix, predicateFirstColumn);
        for (int[] r : secondRows) {
            if (!columnIndexesOfValues(r, predicateOtherColumns).isEmpty()) {
                return true;
            }
        }
        return false;
    }

    private static List<int[]> rowsWithValuesInFirstColumn(int[][] matrix, Predicate<Integer> predicate) {
        List<int[]> indexes = new ArrayList<>();
        for (int[] rows : matrix) {
            if (predicate.test(rows[0])) {
                indexes.add(rows);
            }
        }
        return indexes;
    }

    private static List<Integer> rowIndexesWithValuesInFirstColumn(int[][] matrix, Predicate<Integer> predicate) {
        List<Integer> indexes = new ArrayList<>();
        for (int i = 0; i < matrix.length; i++) {
            if (predicate.test(matrix[i][0])) {
                indexes.add(i);
            }
        }
        return indexes;
    }

    private static List<Integer> columnIndexesOfValues(int[] row, Predicate<Integer> predicate) {
        List<Integer> indexes = new ArrayList<>();
        for (int i = 0; i < row.length; i++) {
            if (predicate.test(row[i])) {
                indexes.add(i);
            }
        }
        return indexes;
    }

    private static List<Integer> rowsWithEvenValuesInFirstColumn(int[][] matrix) {
        List<Integer> indexes = new ArrayList<>();
        for (int i = 0; i < matrix.length; i++) {
            if (isEven(matrix[i][0])) {
                indexes.add(i);
            }
        }
        return indexes;
    }

    private static boolean isEven(int value) {
        return value % 2 == 0;
    }

    private static int indexOfValueGreaterThanFive(int[] row) {
        for (int l = 1; l < row.length; l++) { // Verschachtelung 2
            if (row[l] > 5) { // Entscheidung 4
                return l;
            }
        }
        return -1;
    }

    private static boolean containsValueSmallerThanFour(int[] row) {
        for (int l = 1; l < row.length; l++) { // Verschachtelung 2
            if (row[l] < 4) { // Entscheidung 4
                return true;
            }
        }
        return false;
    }

    private static boolean containsValue(int[] row, int value) {
        for (int l = 1; l < row.length; l++) {
            if (row[l] == value) { // Entscheidung 3
                return true;
            }
        }
        return false;
    }

    private int indexOfFirstColumnWithEvenValue(int[][] matrix) {
        for (int i = 0; i < matrix.length; i++) {
            var row = matrix[i];
            var cellInFirstColumn = row[0];

            if (isEven(cellInFirstColumn)) {
                return i;
            }
        }
        return -1;
    }
}