package com.knecon.fforesight.service.layoutparser.processor.utils;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Stream;

import com.knecon.fforesight.service.layoutparser.processor.model.AbstractPageBlock;
import com.knecon.fforesight.service.layoutparser.processor.model.table.Cell;
import com.knecon.fforesight.service.layoutparser.processor.model.table.TablePageBlock;

import lombok.experimental.UtilityClass;

@UtilityClass
public class TableMergingUtility {

    private static final double TABLE_ALIGNMENT_THRESHOLD = 2d;


    public List<TablePageBlock> findConsecutiveTablesWithSameColCountAndSameHeaders(TablePageBlock originalTablePageBlock, List<AbstractPageBlock> pageBlocks) {

        List<TablePageBlock> consecutiveTables = pageBlocks.stream()
                .map(abstractPageBlock -> (TablePageBlock) abstractPageBlock)
                .filter(tablePageBlock -> !tablePageBlock.equals(originalTablePageBlock))
                .toList();
        assert consecutiveTables.size() == pageBlocks.size() - 1;

        List<TablePageBlock> consecutiveTablesWithSameColCountAndHeaders = new LinkedList<>();
        for (TablePageBlock consecutiveTable : consecutiveTables) {
            if (consecutiveTable.getColCount() == originalTablePageBlock.getColCount() && !hasTableHeader(consecutiveTable) && outerBoundaryAlignsX(originalTablePageBlock,
                    consecutiveTable)) {
                consecutiveTablesWithSameColCountAndHeaders.add(consecutiveTable);
            }
        }
        return Stream.concat(Stream.of(originalTablePageBlock), consecutiveTablesWithSameColCountAndHeaders.stream()).toList();
    }


    private static boolean outerBoundaryAlignsX(TablePageBlock originalTablePageBlock, TablePageBlock consecutiveTable) {

        return Math.abs(consecutiveTable.getMinX() - originalTablePageBlock.getMinX()) < TABLE_ALIGNMENT_THRESHOLD && Math.abs(consecutiveTable.getMaxX() - originalTablePageBlock.getMaxX()) < TABLE_ALIGNMENT_THRESHOLD;
    }


    private boolean hasTableHeader(TablePageBlock table) {

        return table.getRows().stream().flatMap(Collection::stream).anyMatch(Cell::isHeaderCell);
    }

}
