# -*- coding: utf-8 -*-

import os
from io import BytesIO

import pytest
from jsonschema import ValidationError, validate

from PyPDFForm import Annotations, BlankPage, Fields, PdfArray, PdfWrapper
from PyPDFForm.constants import DA, UNIQUE_SUFFIX_LENGTH, T, V
from PyPDFForm.deprecation import deprecation_notice
from PyPDFForm.middleware.base import Widget
from PyPDFForm.template import get_widgets_by_page


def test_deprecation_warning():
    with pytest.warns(
        DeprecationWarning, match="foo will be deprecated soon. Use bar instead."
    ):
        deprecation_notice(
            "foo",
            "bar",
        )


def test_base_schema_definition():
    assert Widget("foo").schema_definition == {}


def test_write(template_stream, pdf_samples):
    assert PdfWrapper(template_stream).write(
        os.path.join(pdf_samples, "sample_template.pdf")
    )


def test_write_io(template_stream):
    buff = BytesIO()
    PdfWrapper(template_stream).write(buff)
    buff.seek(0)

    assert buff.read() == template_stream


def test_fill_flatten_then_unflatten(template_stream, pdf_samples, data_dict, request):
    expected_path = os.path.join(pdf_samples, "test_fill_flatten_then_unflatten.pdf")
    with open(expected_path, "rb+") as f:
        obj = PdfWrapper(template_stream).fill(data_dict, flatten=True)
        obj.widgets["test_2"].readonly = False
        obj.widgets["check_3"].readonly = False

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()
        assert len(obj.read()) == len(obj.read())
        assert obj.read() == obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


def test_register_bad_fonts():
    assert not PdfWrapper().register_font("foo", b"foo").read()
    assert not PdfWrapper().register_font("foo", "foo").read()

    obj = PdfWrapper().register_font("foo", b"foo")
    assert "foo" not in obj.fonts


@pytest.mark.posix_only
def test_fill_with_customized_widgets(
    template_stream, pdf_samples, sample_font_stream, data_dict, request
):
    expected_path = os.path.join(pdf_samples, "test_fill_with_customized_widgets.pdf")
    with open(
        expected_path,
        "rb+",
    ) as f:
        obj = PdfWrapper(template_stream).register_font(
            "new_font",
            sample_font_stream,
        )
        obj.widgets["test"].font = "new_font"
        obj.widgets["test"].font_size = 20
        obj.widgets["test"].font_color = (1, 0, 0)
        obj.widgets["test_2"].font_color = (0, 1, 0)
        obj.fill(
            data_dict,
        )

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


@pytest.mark.posix_only
def test_fill_with_customized_widgets_flatten(
    template_stream, pdf_samples, sample_font_stream, data_dict, request
):
    expected_path = os.path.join(
        pdf_samples, "test_fill_with_customized_widgets_flatten.pdf"
    )
    with open(
        expected_path,
        "rb+",
    ) as f:
        obj = PdfWrapper(template_stream).register_font(
            "new_font",
            sample_font_stream,
        )
        obj.widgets["test"].font = "new_font"
        obj.widgets["test"].font_size = 20
        obj.widgets["test"].font_color = (1, 0, 0)
        obj.widgets["test_2"].font_color = (0, 1, 0)
        obj.fill(
            data_dict,
            flatten=True,
        )

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


def test_fill_with_varied_int_values(template_stream, pdf_samples, request):
    expected_path = os.path.join(pdf_samples, "test_fill_with_varied_int_values.pdf")
    with open(expected_path, "rb+") as f:
        obj = PdfWrapper(template_stream).fill(
            {
                "test": 100,
                "test_2": -250,
                "test_3": 0,
            }
        )

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


def test_fill_radiobutton_flatten(
    template_with_radiobutton_stream, pdf_samples, request
):
    expected_path = os.path.join(pdf_samples, "test_fill_radiobutton_flatten.pdf")
    with open(
        expected_path,
        "rb+",
    ) as f:
        obj = PdfWrapper(template_with_radiobutton_stream).fill(
            {
                "radio_1": 0,
                "radio_2": 1,
                "radio_3": 2,
            },
            flatten=True,
        )

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


def test_fill_radiobutton_flatten_then_unflatten(
    template_with_radiobutton_stream, pdf_samples, request
):
    expected_path = os.path.join(
        pdf_samples, "test_fill_radiobutton_flatten_then_unflatten.pdf"
    )
    with open(
        expected_path,
        "rb+",
    ) as f:
        obj = PdfWrapper(template_with_radiobutton_stream).fill(
            {
                "radio_1": 0,
                "radio_2": 1,
                "radio_3": 2,
            },
            flatten=True,
        )
        obj.widgets["radio_2"].readonly = False

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


def test_fill_sejda(sejda_template, pdf_samples, sejda_data, request):
    expected_path = os.path.join(pdf_samples, "test_fill_sejda.pdf")
    with open(
        expected_path,
        "rb+",
    ) as f:
        obj = PdfWrapper(sejda_template).fill(sejda_data)

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


def test_fill_sejda_flatten(sejda_template, pdf_samples, sejda_data, request):
    expected_path = os.path.join(pdf_samples, "test_fill_sejda_flatten.pdf")
    with open(
        expected_path,
        "rb+",
    ) as f:
        obj = PdfWrapper(sejda_template).fill(
            sejda_data,
            flatten=True,
        )

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


def test_fill_sejda_flatten_then_unflatten(
    sejda_template, pdf_samples, sejda_data, request
):
    expected_path = os.path.join(
        pdf_samples, "test_fill_sejda_flatten_then_unflatten.pdf"
    )
    with open(
        expected_path,
        "rb+",
    ) as f:
        obj = PdfWrapper(sejda_template).fill(
            sejda_data,
            flatten=True,
        )
        obj.widgets["buyer_name"].readonly = False
        obj.widgets["at_future_date"].readonly = False
        obj.widgets["purchase_option"].readonly = False

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


def test_addition_operator_3_times(template_stream, data_dict):
    result = PdfWrapper()

    for _ in range(3):
        result += PdfWrapper(template_stream).fill(data_dict)

    assert len((result + PdfWrapper()).read()) == len(result.read())
    assert (result + PdfWrapper()).read() == result.read()
    assert len(result.pages) == len(PdfWrapper(template_stream).pages) * 3

    result_2 = PdfWrapper()

    for _ in range(3):
        result_2 += PdfWrapper(template_stream).fill(data_dict).pages

    assert len(result_2.pages) == len(result.pages)


def test_merging_unique_suffix(template_stream):
    result = PdfWrapper()

    for i in range(10):
        obj = PdfWrapper(
            PdfWrapper(template_stream).fill({"test": f"value-{i}"}).read()
        )
        result += obj

    merged = PdfWrapper(result.read())

    for page, widgets in get_widgets_by_page(result.read()).items():
        for widget in widgets:
            assert widget[T] in merged.widgets
            if widget[T] == "test":
                assert widget[V] == "value-0"
            elif V in widget and "value-" in widget[V]:
                assert widget[V] == f"value-{page // 3}"
                assert widget[T].split("-")[0] == "test"
                assert len(widget[T].split("-")[1]) == UNIQUE_SUFFIX_LENGTH


def test_merge_preserve_font_and_data(template_stream, sample_font_stream):
    result = PdfWrapper()

    for i in range(10):
        obj = PdfWrapper(template_stream).register_font("new_font", sample_font_stream)
        obj.widgets["test"].font = "new_font"
        result += obj.fill({"test": f"test_{i}"})

    for page, widgets in get_widgets_by_page(result.read()).items():
        for widget in widgets:
            if widget[T] == "test":
                assert widget[V] == "test_0"
                assert widget[DA].startswith("/F1")
            elif widget[T].startswith("test-"):
                assert widget[V] == f"test_{page // 3}"
                assert widget[DA].startswith("/F1")


def test_schema(sample_template_with_comb_text_field):
    data = {
        "FirstName": "John",
        "MiddleName": "Joe",
        "LastName": "XXXXXXX",
        "Awesomeness": True,
        "Gender": 0,
    }
    schema = PdfWrapper(sample_template_with_comb_text_field).schema

    assert schema["type"] == "object"
    properties = schema["properties"]
    for key, value in data.items():
        if key == "LastName":
            assert properties[key]["maxLength"] == 7
        if isinstance(value, str):
            assert properties[key]["type"] == "string"
        elif isinstance(value, bool):
            assert properties[key]["type"] == "boolean"
        elif isinstance(value, int):
            assert properties[key]["type"] == "integer"
            assert properties[key]["maximum"] == 1

    validate(instance=data, schema=schema)

    data["LastName"] = "XXXXXXXX"
    try:
        validate(instance=data, schema=schema)
        raise AssertionError
    except ValidationError:
        pass

    data["LastName"] = "XXXXXXX"
    data["Gender"] = 1
    validate(instance=data, schema=schema)

    data["Gender"] = 2
    try:
        validate(instance=data, schema=schema)
        raise AssertionError
    except ValidationError:
        pass


def test_sample_data(sejda_template_complex):
    obj = PdfWrapper(sejda_template_complex)
    try:
        validate(instance=obj.sample_data, schema=obj.schema)
    except ValidationError:
        raise AssertionError from ValidationError

    widget = Widget("foo")
    try:
        widget.sample_value()
        raise AssertionError
    except NotImplementedError:
        pass


def test_sample_data_max_boundary(sample_template_with_comb_text_field):
    obj = PdfWrapper(sample_template_with_comb_text_field)
    try:
        validate(instance=obj.sample_data, schema=obj.schema)
    except ValidationError:
        raise AssertionError from ValidationError

    assert obj.sample_data["LastName"] == "LastNam"
    assert obj.sample_data["Gender"] == 1


def test_fill_right_aligned(
    sample_template_with_right_aligned_text_field, pdf_samples, request
):
    expected_path = os.path.join(pdf_samples, "test_fill_right_aligned.pdf")
    with open(expected_path, "rb+") as f:
        obj = PdfWrapper(sample_template_with_right_aligned_text_field).fill(
            {
                "name": "Hans Mustermann",
                "fulladdress": "Musterstr. 12, 82903 Musterdorf, Musterland",
                "advisorname": "Karl Test",
            },
        )

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


def test_version(pdf_samples):
    versions = ["1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "2.0"]

    for version in versions:
        obj = PdfWrapper(os.path.join(pdf_samples, "versions", f"{version}.pdf"))
        assert obj.version == version
        assert obj.change_version("2.0").version == "2.0"

    obj = PdfWrapper(os.path.join(pdf_samples, "versions", "unknown.pdf"))
    assert obj.version is None


@pytest.mark.posix_only
def test_fill_font_color(sample_template_with_font_colors, pdf_samples, request):
    expected_path = os.path.join(pdf_samples, "test_fill_font_color.pdf")
    with open(expected_path, "rb+") as f:
        obj = PdfWrapper(sample_template_with_font_colors).fill(
            {
                "red_12": "red",
                "green_14": "green",
                "blue_16": "blue",
                "mixed_auto": "mixed",
            },
        )

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


@pytest.mark.posix_only
def test_fill_complex_fonts(sample_template_with_complex_fonts, pdf_samples, request):
    expected_path = os.path.join(pdf_samples, "test_fill_complex_fonts.pdf")
    with open(expected_path, "rb+") as f:
        obj = PdfWrapper(sample_template_with_complex_fonts).fill(
            {
                "Courier": "Test",
                "Courier-Bold": "Test",
                "Courier-BoldOblique": "Test",
                "Courier-Oblique": "Test",
                "Helvetica": "Test",
                "Helvetica-Bold": "Test",
                "Helvetica-BoldOblique": "Test",
                "Helvetica-Oblique": "Test",
                "Times-Bold": "Test",
                "Times-BoldItalic": "Test",
                "Times-Italic": "Test",
                "Times-Roman": "Test",
            },
        )

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


@pytest.mark.posix_only
def test_pages_preserve_font(template_stream, pdf_samples, sample_font_stream, request):
    expected_path = os.path.join(pdf_samples, "pages", "test_pages_preserve_font.pdf")
    obj = PdfWrapper(template_stream)
    obj.register_font("new_font", sample_font_stream)
    obj.widgets["test_2"].font = "new_font"

    with open(expected_path, "rb+") as f:
        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.pages[1].read()
        assert obj.pages[1].read() == f.read()


def test_sejda_pages_1(sejda_template, pdf_samples, request):
    expected_path = os.path.join(pdf_samples, "pages", "test_sejda_pages_1.pdf")
    obj = PdfWrapper(sejda_template)

    with open(expected_path, "rb+") as f:
        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.pages[0].read()
        assert obj.pages[0].read() == f.read()


def test_sejda_pages_2(sejda_template, pdf_samples, request):
    expected_path = os.path.join(pdf_samples, "pages", "test_sejda_pages_2.pdf")
    obj = PdfWrapper(sejda_template)

    with open(expected_path, "rb+") as f:
        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.pages[1].read()
        assert obj.pages[1].read() == f.read()


def test_radio_pages_1(template_with_radiobutton_stream, pdf_samples, request):
    expected_path = os.path.join(pdf_samples, "pages", "test_radio_pages_1.pdf")
    obj = PdfWrapper(template_with_radiobutton_stream)

    with open(expected_path, "rb+") as f:
        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.pages[0].read()
        assert obj.pages[0].read() == f.read()


def test_radio_pages_2(template_with_radiobutton_stream, pdf_samples, request):
    expected_path = os.path.join(pdf_samples, "pages", "test_radio_pages_2.pdf")
    obj = PdfWrapper(template_with_radiobutton_stream)

    with open(expected_path, "rb+") as f:
        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.pages[1].read()
        assert obj.pages[1].read() == f.read()


def test_radio_pages_3(template_with_radiobutton_stream, pdf_samples, request):
    expected_path = os.path.join(pdf_samples, "pages", "test_radio_pages_3.pdf")
    obj = PdfWrapper(template_with_radiobutton_stream)

    with open(expected_path, "rb+") as f:
        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.pages[2].read()
        assert obj.pages[2].read() == f.read()


def test_pages_inherit_attributes(template_stream):
    obj = PdfWrapper(
        template_stream,
        use_full_widget_name=True,
    )

    for page in obj.pages:
        assert getattr(page, "use_full_widget_name")


def test_generate_coordinate_grid_margin_50(template_stream, pdf_samples, request):
    expected_path = os.path.join(
        pdf_samples, "test_generate_coordinate_grid_margin_50.pdf"
    )
    with open(expected_path, "rb+") as f:
        obj = PdfWrapper(template_stream).generate_coordinate_grid((1, 0, 1), margin=50)

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


def test_update_radio_key(template_with_radiobutton_stream, pdf_samples, request):
    expected_path = os.path.join(pdf_samples, "test_update_radio_key.pdf")
    with open(expected_path, "rb+") as f:
        obj = PdfWrapper(template_with_radiobutton_stream)
        obj.update_widget_key("radio_3", "RADIO")
        obj.fill({"RADIO": 0})

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


def test_update_sejda_key(sejda_template, pdf_samples, request):
    expected_path = os.path.join(pdf_samples, "test_update_sejda_key.pdf")
    with open(expected_path, "rb+") as f:
        obj = PdfWrapper(sejda_template)
        obj.update_widget_key("year", "YEAR")
        obj.update_widget_key("at_future_date", "FUTURE_DATE")
        obj.update_widget_key("purchase_option", "PURCHASE_OPTION")
        obj.update_widget_key("buyer_signed_date", "BUYER_SIGNED_DATE")
        obj.fill(
            {
                "YEAR": "12",
                "FUTURE_DATE": True,
                "PURCHASE_OPTION": 1,
                "BUYER_SIGNED_DATE": "2012-01-01",
            }
        )

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


def test_uncheck_checkbox(pdf_samples, request):
    expected_path = os.path.join(pdf_samples, "test_uncheck_checkbox.pdf")
    with open(
        expected_path,
        "rb+",
    ) as f:
        obj = PdfWrapper(os.path.join(pdf_samples, "sample_template_filled.pdf")).fill(
            {"check": False, "check_2": False, "check_3": False},
        )

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


@pytest.mark.posix_only
def test_blank_page(pdf_samples, request):
    expected_path = os.path.join(pdf_samples, "test_blank_page.pdf")
    with open(expected_path, "rb+") as f:
        obj = PdfWrapper(BlankPage() * 1)

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        request.config.results["skip_regenerate"] = len(obj.read()) == len(expected)


@pytest.mark.posix_only
def test_blank_page_custom_size_multiply(pdf_samples, request):
    expected_path = os.path.join(
        pdf_samples, "test_blank_page_custom_size_multiply.pdf"
    )
    with open(expected_path, "rb+") as f:
        obj = PdfWrapper(BlankPage(595.35, 841.995) * 3)

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        request.config.results["skip_regenerate"] = len(obj.read()) == len(expected)


def test_widget_coord_resolution():
    obj = PdfWrapper(BlankPage()).bulk_create_fields(
        [
            Fields.TextField("text", 1, 50, 100, width=200, height=150),
            Fields.CheckBoxField("check", 1, 150, 200, size=60),
            Fields.RadioGroup("radio", 1, [400, 500, 600], [450, 550, 650], size=10),
            Fields.DropdownField(
                "dropdown", 1, 400, 100, width=250, height=200, options=["foo", "bar"]
            ),
            Fields.ImageField("image", 1, 300, 400, width=400, height=300),
            Fields.SignatureField("signature", 1, 500, 600, width=600, height=500),
        ]
    )

    assert obj.widgets["text"].x == 50
    assert obj.widgets["text"].y == 100
    assert obj.widgets["text"].width == 200
    assert obj.widgets["text"].height == 150

    assert obj.widgets["check"].x == 150
    assert obj.widgets["check"].y == 200
    assert obj.widgets["check"].width == 60
    assert obj.widgets["check"].height == 60

    assert obj.widgets["radio"].x == [400, 500, 600]
    assert obj.widgets["radio"].y == [450, 550, 650]
    assert obj.widgets["radio"].width == 10
    assert obj.widgets["radio"].height == 10

    assert obj.widgets["dropdown"].x == 400
    assert obj.widgets["dropdown"].y == 100
    assert obj.widgets["dropdown"].width == 250
    assert obj.widgets["dropdown"].height == 200

    assert obj.widgets["image"].x == 300
    assert obj.widgets["image"].y == 400
    assert obj.widgets["image"].width == 400
    assert obj.widgets["image"].height == 300

    assert obj.widgets["signature"].x == 500
    assert obj.widgets["signature"].y == 600
    assert obj.widgets["signature"].width == 600
    assert obj.widgets["signature"].height == 500


def test_hidden_text_check(template_stream, pdf_samples, request):
    expected_path = os.path.join(pdf_samples, "test_hidden_text_check.pdf")
    with open(expected_path, "rb+") as f:
        obj = PdfWrapper(template_stream)
        obj.widgets["test"].hidden = True
        obj.widgets["check_2"].hidden = True

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


def test_hidden_radio(template_with_radiobutton_stream, pdf_samples, request):
    expected_path = os.path.join(pdf_samples, "test_hidden_radio.pdf")
    with open(expected_path, "rb+") as f:
        obj = PdfWrapper(template_with_radiobutton_stream)
        obj.widgets["radio_2"].hidden = True

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


def test_hidden_sejda(sejda_template, pdf_samples, request):
    expected_path = os.path.join(pdf_samples, "test_hidden_sejda.pdf")
    with open(expected_path, "rb+") as f:
        obj = PdfWrapper(sejda_template)
        obj.widgets["buyer_name"].hidden = True
        obj.widgets["purchase_option"].hidden = True
        obj.widgets["at_future_date"].hidden = True

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


def test_merge(template_stream):
    pdf_list = PdfArray()
    for i in range(20):
        pdf_list.append(
            PdfWrapper(template_stream).fill(
                {
                    "test": f"test_1_{i}",
                    "check": True,
                    "test_2": f"test_2_{i}",
                    "check_2": False,
                    "test_3": f"test_3_{i}",
                    "check_3": True,
                }
            )
        )

    result = pdf_list.merge()
    assert len(result.pages) == 60

    for page, fields in get_widgets_by_page(result.read()).items():
        for field in fields:
            key = field[T]
            if key.startswith("test-"):
                assert field[V] == f"test_1_{int(page / 3)}"
            elif key.startswith("test_2-"):
                assert field[V] == f"test_2_{int(page / 3)}"
            elif key.startswith("test_3-"):
                assert field[V] == f"test_3_{int(page / 3 - 0.5)}"


def test_annotate(template_stream, pdf_samples, request):
    expected_path = os.path.join(pdf_samples, "test_annotate.pdf")
    with open(expected_path, "rb+") as f:
        obj = PdfWrapper(template_stream).annotate(
            [
                Annotations.TextAnnotation(
                    1, 100, 100, contents="this is an annotation"
                ),
                Annotations.TextAnnotation(
                    1,
                    200,
                    100,
                    contents="this is a second annotation",
                    title="Annotation 2",
                    icon=Annotations.TextAnnotation.comment_icon,
                ),
                Annotations.TextAnnotation(
                    1,
                    100,
                    200,
                    contents="this is a third annotation",
                    icon=Annotations.TextAnnotation.help_icon,
                ),
                Annotations.TextAnnotation(
                    1,
                    200,
                    200,
                    contents="this is a forth annotation",
                    icon=Annotations.TextAnnotation.key_icon,
                ),
                Annotations.TextAnnotation(
                    2,
                    100,
                    300,
                    contents="this is a fifth annotation",
                    icon=Annotations.TextAnnotation.insert_icon,
                ),
            ]
        )

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


def test_annotate_no_annotations(pdf_samples, request):
    expected_path = os.path.join(pdf_samples, "test_annotate_no_annotations.pdf")
    with open(expected_path, "rb+") as f:
        obj = PdfWrapper(os.path.join(pdf_samples, "dummy.pdf")).annotate(
            [
                Annotations.TextAnnotation(
                    1, 100, 100, contents="this is an annotation"
                ),
                Annotations.TextAnnotation(
                    1,
                    200,
                    100,
                    contents="this is a second annotation",
                    title="Annotation 2",
                    icon=Annotations.TextAnnotation.comment_icon,
                ),
                Annotations.TextAnnotation(
                    1,
                    100,
                    200,
                    contents="this is a third annotation",
                    icon=Annotations.TextAnnotation.help_icon,
                ),
                Annotations.TextAnnotation(
                    1,
                    200,
                    200,
                    contents="this is a forth annotation",
                    icon=Annotations.TextAnnotation.key_icon,
                ),
                Annotations.TextAnnotation(
                    1,
                    100,
                    300,
                    contents="this is a fifth annotation",
                    icon=Annotations.TextAnnotation.insert_icon,
                ),
            ]
        )

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected


def test_rubber_stamp_annotation(template_stream, pdf_samples, request):
    expected_path = os.path.join(pdf_samples, "test_rubber_stamp_annotation.pdf")
    with open(expected_path, "rb+") as f:
        obj = PdfWrapper(template_stream).annotate(
            [
                Annotations.RubberStampAnnotation(
                    1,
                    0,
                    400,
                    width=50,
                    height=50,
                    name=Annotations.RubberStampAnnotation.approved,
                ),
                Annotations.RubberStampAnnotation(
                    1,
                    100,
                    400,
                    width=50,
                    height=50,
                    name=Annotations.RubberStampAnnotation.experimental,
                ),
                Annotations.RubberStampAnnotation(
                    1,
                    200,
                    400,
                    width=50,
                    height=50,
                    name=Annotations.RubberStampAnnotation.not_approved,
                ),
                Annotations.RubberStampAnnotation(
                    1,
                    300,
                    400,
                    width=50,
                    height=50,
                    name=Annotations.RubberStampAnnotation.as_is,
                ),
                Annotations.RubberStampAnnotation(
                    1,
                    400,
                    400,
                    width=50,
                    height=50,
                    name=Annotations.RubberStampAnnotation.expired,
                ),
                Annotations.RubberStampAnnotation(
                    1,
                    0,
                    500,
                    width=50,
                    height=50,
                    name=Annotations.RubberStampAnnotation.not_for_public_release,
                ),
                Annotations.RubberStampAnnotation(
                    1,
                    100,
                    500,
                    width=50,
                    height=50,
                    name=Annotations.RubberStampAnnotation.confidential,
                ),
                Annotations.RubberStampAnnotation(
                    1,
                    200,
                    500,
                    width=50,
                    height=50,
                    name=Annotations.RubberStampAnnotation.final,
                ),
                Annotations.RubberStampAnnotation(
                    1,
                    300,
                    500,
                    width=50,
                    height=50,
                    name=Annotations.RubberStampAnnotation.sold,
                ),
                Annotations.RubberStampAnnotation(
                    1,
                    400,
                    500,
                    width=50,
                    height=50,
                    name=Annotations.RubberStampAnnotation.departmental,
                ),
                Annotations.RubberStampAnnotation(
                    1,
                    0,
                    600,
                    width=50,
                    height=50,
                    name=Annotations.RubberStampAnnotation.for_comment,
                ),
                Annotations.RubberStampAnnotation(
                    1,
                    100,
                    600,
                    width=50,
                    height=50,
                    name=Annotations.RubberStampAnnotation.top_secret,
                ),
                Annotations.RubberStampAnnotation(
                    1,
                    200,
                    600,
                    width=50,
                    height=50,
                    name=Annotations.RubberStampAnnotation.draft,
                ),
                Annotations.RubberStampAnnotation(
                    1,
                    300,
                    600,
                    width=50,
                    height=50,
                    name=Annotations.RubberStampAnnotation.for_public_release,
                ),
            ]
        )

        request.config.results["expected_path"] = expected_path
        request.config.results["stream"] = obj.read()

        expected = f.read()

        assert len(obj.read()) == len(expected)
        assert obj.read() == expected
