"Test writing TIFF"

import os
import re
import subprocess
import tempfile
import pikepdf
from PIL import Image
from gi.repository import GLib
import config
from document import Document
from loop_helpers import safe_mainloop


def test_save_tiff(rose_pnm, temp_db, temp_tif, temp_png, import_in_mainloop):
    "Test writing TIFF"
    slist = Document(db=temp_db.name)

    import_in_mainloop(slist, [rose_pnm])

    mlp = safe_mainloop(2000)
    slist.save_tiff(
        path=temp_tif.name,
        list_of_pages=[slist.data[0][2]],
        options={
            "post_save_hook": f"convert %i {temp_png.name}",
        },
        finished_callback=lambda response: mlp.quit(),
    )
    mlp.run()

    img = Image.open(temp_tif.name)
    assert img.format == "TIFF", "valid TIFF created"
    assert img.size == (70, 46), "valid TIFF dimensions"

    img = Image.open(temp_png.name)
    assert img.format == "PNG", "ran post-save hook"
    assert img.size == (70, 46), "post-save hook dimensions"


def test_cancel_save_tiff(rose_pnm, temp_db, temp_tif, temp_jpg, import_in_mainloop):
    "Test cancel saving a TIFF"
    slist = Document(db=temp_db.name)

    import_in_mainloop(slist, [rose_pnm])

    mlp = safe_mainloop(2000)
    called = False

    def cancelled_callback(_response):
        nonlocal called
        called = True
        mlp.quit()

    slist.save_tiff(
        path=temp_tif.name,
        list_of_pages=[slist.data[0][2]],
        finished_callback=lambda response: mlp.quit(),
    )
    slist.cancel(cancelled_callback)
    mlp.run()

    assert called, "Cancelled callback"

    slist.save_image(
        path=temp_jpg.name,
        list_of_pages=[slist.data[0][2]],
        finished_callback=lambda response: mlp.quit(),
    )
    mlp = safe_mainloop(2000)
    mlp.run()

    img = Image.open(temp_jpg.name)
    assert (
        img.format == "JPEG"
    ), "can create a valid JPG after cancelling save PDF process"


def test_save_tiff_with_error(rose_pnm, temp_tif, import_in_mainloop):
    "Test writing TIFF and triggering an error"
    with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as dirname:
        slist = Document(dir=dirname)
        asserts = 0

        import_in_mainloop(slist, [rose_pnm])

        # inject error before save_djvu
        os.chmod(dirname, 0o500)  # no write access

        def error_callback1(_page, _process, _message):
            "no write access"
            assert True, "caught error injected before save_tiff"
            nonlocal asserts
            asserts += 1
            mlp.quit()

        mlp = safe_mainloop(2000)
        slist.save_tiff(
            path=temp_tif.name,
            list_of_pages=[slist.data[0][2]],
            error_callback=error_callback1,
        )
        mlp.run()

        def error_callback2(_page, _process, _message):
            assert True, "save_djvu caught error injected in queue"
            os.chmod(dirname, 0o700)  # allow write access
            nonlocal asserts
            asserts += 1
            mlp.quit()

        mlp = safe_mainloop(2000)
        slist.save_tiff(
            path=temp_tif.name,
            list_of_pages=[slist.data[0][2]],
            error_callback=error_callback2,
        )
        mlp.run()

        assert asserts == 2, "ran all callbacks"


def test_save_tiff_with_alpha(temp_png, temp_db, temp_tif, import_in_mainloop):
    "Test writing TIFF with alpha layer"

    subprocess.run(
        [
            config.CONVERT_COMMAND,
            "-fill",
            "lightblue",
            "-family",
            "DejaVu Sans",
            "-pointsize",
            "12",
            "-units",
            "PixelsPerInch",
            "-density",
            "300",
            "label:The quick brown fox",
            temp_png.name,
        ],
        check=True,
    )

    slist = Document(db=temp_db.name)

    import_in_mainloop(slist, [temp_png.name])

    mlp = safe_mainloop(2000)
    slist.save_tiff(
        path=temp_tif.name,
        list_of_pages=[slist.data[0][2]],
        options={
            "compression": "lzw",
        },
        finished_callback=lambda response: mlp.quit(),
    )
    mlp.run()

    img = Image.open(temp_tif.name)
    assert img.format == "TIFF", "valid TIFF created"
    assert img.mode == "RGB", "valid TIFF with alpha"


def test_save_tiff_as_ps(rose_pnm, temp_db, temp_tif, temp_pdf, import_in_mainloop):
    "Test writing TIFF and postscript"
    slist = Document(db=temp_db.name)

    import_in_mainloop(slist, [rose_pnm, rose_pnm])

    with tempfile.NamedTemporaryFile(suffix=".ps", prefix=" ") as temp_ps:
        mlp = safe_mainloop(2000)
        slist.save_tiff(
            path=temp_tif.name,
            list_of_pages=[slist.data[0][2], slist.data[1][2]],
            options={
                "ps": temp_ps.name,
                "post_save_hook": f"ps2pdf %i {temp_pdf.name}",
            },
            finished_callback=lambda response: mlp.quit(),
        )
        mlp.run()

        example = subprocess.check_output(["file", temp_ps.name], text=True)
        assert (
            example
            == temp_ps.name
            + ": PostScript document text conforming DSC level 3.0, type EPS, Level 3\n"
        ), "valid postscript created"

        with pikepdf.open(temp_pdf.name) as pdf:
            creator = str(pdf.docinfo.get("/Creator", ""))
        assert "tiff2ps" in creator, "ran post-save hook"


def test_save_tiff_g4(rose_png, temp_db, temp_tif, import_in_mainloop):
    "Test writing TIFF with group 4 compression"
    slist = Document(db=temp_db.name)
    import_in_mainloop(slist, [rose_png])
    mlp = safe_mainloop(2000)
    slist.save_tiff(
        path=temp_tif.name,
        list_of_pages=[slist.data[0][2]],
        options={
            "compression": "g4",
        },
        finished_callback=lambda response: mlp.quit(),
    )
    mlp.run()

    img = Image.open(temp_tif.name)
    assert img.format == "TIFF", "valid TIFF created"
    assert img.size == (70, 46), "valid TIFF dimensions"
    assert img.mode == "1", "valid TIFF with group 4 compression"
