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

import java.awt.geom.Rectangle2D;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.Rectangle;
import com.knecon.fforesight.service.layoutparser.processor.model.text.TextPageBlock;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public abstract class AbstractPageBlock extends Rectangle {

    protected Rectangle2D bBox; // in initial user space

    @JsonIgnore
    protected float minX;
    @JsonIgnore
    protected float maxX;
    @JsonIgnore
    protected float minY;
    @JsonIgnore
    protected float maxY;
    @JsonIgnore
    protected PageBlockType classification;
    @JsonIgnore
    protected int page;

    @JsonIgnore
    private Orientation orientation = Orientation.NONE;


    public abstract String getText();


    public boolean isHeadline() {

        return this instanceof TextPageBlock && this.getClassification() != null && this.getClassification().isHeadline();
    }


    public boolean containsBlock(TextPageBlock other) {

        return this.minX <= other.getPdfMinX() && this.maxX >= other.getPdfMaxX() && this.minY >= other.getPdfMinY() && this.maxY <= other.getPdfMaxY();
    }


    public boolean contains(AbstractPageBlock other) {

        return this.minX <= other.minX && this.maxX >= other.maxX && this.minY >= other.minY && this.maxY <= other.maxY;
    }


    public boolean contains(Rectangle other) {

        return page == other.getPage() && this.minX <= other.getTopLeft().getX() && this.maxX >= other.getTopLeft().getX() + other.getWidth() && this.minY <= other.getTopLeft()
                .getY() && this.maxY >= other.getTopLeft().getY() + other.getHeight();
    }


    @JsonIgnore
    public float getHeight() {

        return maxY - minY;
    }


    @JsonIgnore
    public float getWidth() {

        return maxX - minX;
    }


    public boolean intersectsY(AbstractPageBlock apb) {

        return this.minY <= apb.getMaxY() && this.maxY >= apb.getMinY();
    }


    public boolean almostIntersects(AbstractPageBlock apb, float yThreshold, float xThreshold) {

        return this.almostIntersectsX(apb, xThreshold) && this.almostIntersectsY(apb, yThreshold);
    }


    private boolean almostIntersectsY(AbstractPageBlock apb, float threshold) {

        return this.minY - threshold <= apb.getMaxY() && this.maxY + threshold >= apb.getMinY();
    }


    private boolean almostIntersectsX(AbstractPageBlock apb, float threshold) {

        return this.minX - threshold <= apb.getMaxX() && this.maxX + threshold >= apb.getMinX();
    }
    

    public abstract boolean isEmpty();

}
