#include <library/cpp/testing/gtest/gtest.h>
#include <maps/wikimap/mapspro/services/mrc/libs/common/include/image_box.h>

namespace maps::mrc::common::tests {

TEST(image_box, intersection)
{
    { // empty
        const ImageBox a{10, 10 , 10, 10};
        const ImageBox b{0, 0 , 40, 40};

        EXPECT_EQ(intersect(a, b), std::nullopt);
    }

    { // a & b = 0
        const ImageBox a{10, 10 , 20, 20};
        const ImageBox b{30, 30 , 40, 40};

        EXPECT_EQ(intersect(a, b), std::nullopt);
    }

    { // a = b
        const ImageBox a{10, 10 , 20, 20};

        EXPECT_EQ(intersect(a, a), a);
    }

    { // b in a
        const ImageBox a{10, 10 , 40, 40};
        const ImageBox b{20, 20 , 30, 30};

        EXPECT_EQ(intersect(a, b), b);
    }

    { // a & b != 0
        const ImageBox a{10, 10 , 30, 30};
        const ImageBox b{20, 20 , 40, 40};

        const ImageBox expected{20, 20, 30, 30};

        EXPECT_EQ(intersect(a, b), expected);
    }
}

TEST(image_box, IoU)
{
    {
        const ImageBox a{10, 10 , 10, 10};
        const ImageBox b{0, 0 , 40, 40};

        EXPECT_EQ(getIoU(a, b), 0.0);
    }

    { // a & b = 0
        const ImageBox a{10, 10 , 20, 20};
        const ImageBox b{30, 30 , 40, 40};

        EXPECT_EQ(getIoU(a, b), 0.0);
    }

    { // a = b
        const ImageBox a{10, 10 , 20, 20};

        EXPECT_EQ(getIoU(a, a), 1.0);
    }

    { // b in a
        const ImageBox a{0, 0 , 40, 40};
        const ImageBox b{10, 10 , 30, 30};
        const double expected = 0.25;

        EXPECT_EQ(getIoU(a, b), expected);
    }

    { // a & b != 0
        const ImageBox a{10, 10 , 30, 30};
        const ImageBox b{20, 20 , 40, 40};
        const double expected = 1.0 / 7.0;

        EXPECT_EQ(getIoU(a, b), expected);
    }
}

TEST(image_box, mask_intersection_ratio)
{
    double data[9] = {
        0, 0, 0,
        0, 1, 1,
        0, 1, 1,
    };
    const cv::Mat mask = cv::Mat(3, 3, CV_64F, data);

    {   // empty box
        const ImageBox box{1, 1, 1, 1};
        EXPECT_EQ(getIntersectionRatio(box, mask), 0.0);
    }

    {   // full intersection
        const ImageBox box{1, 1, 3, 3};
        EXPECT_EQ(getIntersectionRatio(box, mask), 1.0);
    }

    {   // part intersection
        const ImageBox box{0, 0, 2, 2};
        EXPECT_EQ(getIntersectionRatio(box, mask), 0.25);
    }

    {   // empty intersection
        const ImageBox box{0, 0, 1, 1};
        EXPECT_EQ(getIntersectionRatio(box, mask), 0.0);
    }
}

TEST(image_box, box_to_image_size_ratio)
{
    // empty box
    EXPECT_EQ(getBoxToFrameSizeRatio(ImageBox{1, 1, 1, 1}, Size{10, 10}), 0.0);

    // empty size
    EXPECT_EQ(getBoxToFrameSizeRatio(ImageBox{1, 1, 3, 3}, Size{0, 0}), 0.0);

    // default
    EXPECT_EQ(getBoxToFrameSizeRatio(ImageBox{1, 1, 3, 3}, Size{10, 10}), 0.04);
}

} // namespace maps::mrc::common::tests
