package com.knecon.fforesight.service.layoutparser.processor.services.mapper;

import java.awt.geom.Rectangle2D;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import com.knecon.fforesight.service.layoutparser.internal.api.data.redaction.DocumentStructure;
import com.knecon.fforesight.service.layoutparser.processor.model.graph.nodes.DuplicatedParagraph;
import com.knecon.fforesight.service.layoutparser.processor.model.graph.nodes.Image;
import com.knecon.fforesight.service.layoutparser.processor.model.graph.nodes.ImageType;
import com.knecon.fforesight.service.layoutparser.processor.model.graph.nodes.Table;
import com.knecon.fforesight.service.layoutparser.processor.model.graph.nodes.TableCell;
import com.knecon.fforesight.service.layoutparser.processor.model.graph.textblock.AtomicTextBlock;
import com.knecon.fforesight.service.layoutparser.processor.model.graph.textblock.TextBlock;

public class PropertiesMapper {

    public static Map<String, String> buildImageProperties(Image image) {

        Map<String, String> properties = new HashMap<>();
        properties.put(DocumentStructure.ImageProperties.IMAGE_TYPE, image.getImageType().toString());
        properties.put(DocumentStructure.ImageProperties.TRANSPARENT, String.valueOf(image.isTransparent()));
        properties.put(DocumentStructure.ImageProperties.POSITION, toString(image.getPosition()));
        properties.put(DocumentStructure.ImageProperties.ID, image.getId());
        return properties;
    }


    public static Map<String, String> buildTableCellProperties(TableCell tableCell) {

        Map<String, String> properties = new HashMap<>();
        properties.put(DocumentStructure.TableCellProperties.ROW, String.valueOf(tableCell.getRow()));
        properties.put(DocumentStructure.TableCellProperties.COL, String.valueOf(tableCell.getCol()));
        properties.put(DocumentStructure.TableCellProperties.HEADER, String.valueOf(tableCell.isHeader()));

        if (tableCell.getPages().size() > 1 || tableCell.getBBox().keySet().size() > 1) {
            throw new IllegalArgumentException("TableCell can only occur on a single page!");
        }
        String bBoxString = toString(tableCell.getBBox().get(tableCell.getPages().stream().findFirst().get()));
        properties.put(DocumentStructure.TableCellProperties.B_BOX, bBoxString);

        return properties;
    }


    public static Map<String, String> buildTableProperties(Table table) {

        Map<String, String> properties = new HashMap<>();
        properties.put(DocumentStructure.TableProperties.NUMBER_OF_ROWS, String.valueOf(table.getNumberOfRows()));
        properties.put(DocumentStructure.TableProperties.NUMBER_OF_COLS, String.valueOf(table.getNumberOfCols()));
        return properties;
    }


    public static void parseImageProperties(Map<String, String> properties, Image.ImageBuilder builder) {

        builder.imageType(parseImageType(properties.get(DocumentStructure.ImageProperties.IMAGE_TYPE)));
        builder.transparent(Boolean.parseBoolean(properties.get(DocumentStructure.ImageProperties.TRANSPARENT)));
        builder.position(DocumentStructure.parseRectangle2D(properties.get(DocumentStructure.ImageProperties.POSITION)));
    }


    public static void parseTableCellProperties(Map<String, String> properties, TableCell.TableCellBuilder builder) {

        builder.row(Integer.parseInt(properties.get(DocumentStructure.TableCellProperties.ROW)));
        builder.col(Integer.parseInt(properties.get(DocumentStructure.TableCellProperties.COL)));
        builder.header(Boolean.parseBoolean(properties.get(DocumentStructure.TableCellProperties.HEADER)));
        builder.bBox(DocumentStructure.parseRectangle2D(properties.get(DocumentStructure.TableCellProperties.B_BOX)));
    }


    public static void parseTableProperties(Map<String, String> properties, Table.TableBuilder builder) {

        builder.numberOfRows(Integer.parseInt(properties.get(DocumentStructure.TableProperties.NUMBER_OF_ROWS)));
        builder.numberOfCols(Integer.parseInt(properties.get(DocumentStructure.TableProperties.NUMBER_OF_COLS)));
    }


    public static Map<String, String> buildDuplicateParagraphProperties(DuplicatedParagraph duplicatedParagraph) {

        Map<String, String> properties = new HashMap<>();
        properties.put(DocumentStructure.DuplicateParagraphProperties.UNSORTED_TEXTBLOCK_ID, Arrays.toString(toAtomicTextBlockIds(duplicatedParagraph.getUnsortedLeafTextBlock())));
        return properties;
    }


    public static boolean isDuplicateParagraph(Map<String, String> properties) {

        return properties.containsKey(DocumentStructure.DuplicateParagraphProperties.UNSORTED_TEXTBLOCK_ID);
    }


    public static Long[] getUnsortedTextblockIds(Map<String, String> properties) {

        return toLongArray(properties.get(DocumentStructure.DuplicateParagraphProperties.UNSORTED_TEXTBLOCK_ID));
    }


    public static Long[] toLongArray(String ids) {

        return Arrays.stream(ids.substring(1, ids.length() - 1).trim().split(",")).map(Long::valueOf).toArray(Long[]::new);
    }


    private static ImageType parseImageType(String imageType) {

        return switch (imageType) {
            case "LOGO" -> ImageType.LOGO;
            case "FORMULA" -> ImageType.FORMULA;
            case "SIGNATURE" -> ImageType.SIGNATURE;
            case "OCR" -> ImageType.OCR;
            default -> ImageType.OTHER;
        };
    }


    public static String toString(Rectangle2D rectangle2D) {

        return String.format(Locale.US,
                "%f%s%f%s%f%s%f",
                rectangle2D.getX(),
                DocumentStructure.RECTANGLE_DELIMITER,
                rectangle2D.getY(),
                DocumentStructure.RECTANGLE_DELIMITER,
                rectangle2D.getWidth(),
                DocumentStructure.RECTANGLE_DELIMITER,
                rectangle2D.getHeight());
    }


    private static Long[] toAtomicTextBlockIds(TextBlock textBlock) {

        return textBlock.getAtomicTextBlocks().stream().map(AtomicTextBlock::getId).toArray(Long[]::new);
    }

}
