"Test importing TIFF"

import os
import pathlib
import re
import subprocess
import tempfile
from unittest.mock import MagicMock
from PIL import Image
from gi.repository import GLib
import config
from document import Document
from loop_helpers import safe_mainloop


def test_import_tiff(rose_tif, temp_db, get_page_sync):
    "Test importing basic TIFF"
    slist = Document(db=temp_db.name)

    mlp = safe_mainloop(2000)

    slist.import_files(
        paths=[rose_tif],
        finished_callback=lambda response: mlp.quit(),
    )
    mlp.run()

    page = get_page_sync(slist.thread, id=1)
    assert page.image_object.mode == "RGB", "TIFF imported correctly"


def test_import_tiff_with_units(temp_tif, temp_db, get_page_sync):
    "Test importing TIFF with units"

    subprocess.run(
        [
            config.CONVERT_COMMAND,
            "rose:",
            "-units",
            "PixelsPerInch",
            "-density",
            "72x72",
            temp_tif.name,
        ],
        check=True,
    )

    slist = Document(db=temp_db.name)

    mlp = safe_mainloop(2000)

    slist.import_files(
        paths=[temp_tif.name],
        finished_callback=lambda response: mlp.quit(),
    )
    mlp.run()

    page = get_page_sync(slist.thread, id=1)
    assert page.image_object.mode == "RGB", "TIFF imported correctly"


def test_import_tiff_with_error(rose_tif):
    "Test importing TIFF"
    with tempfile.TemporaryDirectory() as dirname:
        slist = Document(dir=dirname)

        mlp = safe_mainloop()

        asserts = 0

        # inject error during import file
        os.chmod(dirname, 0o500)  # allow access

        def error_cb(*args):
            nonlocal asserts
            message = args[-1] if len(args) > 1 else args[0].status
            assert message, "error_cb"
            asserts += 1

            # inject error during import file
            os.chmod(dirname, 0o700)  # allow write access

        slist.import_files(
            paths=[rose_tif],
            error_callback=error_cb,
            finished_callback=lambda response: mlp.quit(),
        )
        mlp.run()

        def queued_cb(response):
            nonlocal asserts
            if asserts == 1:
                asserts += 1

                # inject error during import file
                os.chmod(dirname, 0o500)  # no write access

        slist.import_files(
            paths=[rose_tif],
            queued_callback=queued_cb,
            error_callback=error_cb,
            finished_callback=lambda response: mlp.quit(),
        )
        mlp.run()

        assert asserts == 3, "all callbacks run"


def test_import_multipage_tiff(rose_tif, temp_db):
    "Test importing TIFF"
    with tempfile.NamedTemporaryFile(suffix=".tif") as temp_tif2:
        subprocess.run(["tiffcp", rose_tif, rose_tif, temp_tif2.name], check=True)

        slist = Document(db=temp_db.name)

        mlp = safe_mainloop(2000)

        slist.import_files(
            paths=[temp_tif2.name],
            finished_callback=lambda response: mlp.quit(),
        )
        mlp.run()

        assert len(slist.data) == 2, "imported 2 pages"


def test_import_linked_tiff(rose_tif, temp_db, get_page_sync):
    "Test importing TIFF"
    with tempfile.TemporaryDirectory() as temp_dir:
        temp_tif = pathlib.Path(temp_dir) / "test.tif"
        subprocess.run(["ln", "-s", rose_tif, temp_tif], check=True)
        img = Image.open(rose_tif)
        img.load()  # verify file is readable

        slist = Document(db=temp_db.name)

        mlp = safe_mainloop(2000)

        slist.import_files(
            paths=[str(temp_tif)],
            finished_callback=lambda response: mlp.quit(),
        )
        mlp.run()

        page = get_page_sync(slist.thread, id=1)
        assert page.image_object.mode == "RGB", "TIFF imported correctly"


def test_import_multiple_tiffs_with_corrupt(temp_db, rose_tif, clean_up_files):
    "Test importing TIFF"

    slist = Document(db=temp_db.name)
    paths = [rose_tif for _ in range(9)]

    # insert a zero-length file
    subprocess.run(["touch", "5.tif"], check=True)
    paths.insert(4, "5.tif")

    mlp = safe_mainloop(4000)

    asserts = 0

    def error_cb(response):
        nonlocal asserts
        assert (
            response.status == "Error importing zero-length file 5.tif."
        ), "caught error importing corrupt file"
        asserts += 1

    slist.import_files(
        paths=paths,
        error_callback=error_cb,
        finished_callback=lambda response: mlp.quit(),
    )
    mlp.run()

    assert len(slist.data) == 9, "imported 9 pages"
    assert asserts == 1, "all callbacks run"

    #########################

    clean_up_files(["5.tif"])


def test_cancel_import_tiff(rose_tif, temp_db, import_in_mainloop, get_page_sync):
    "Test importing TIFF"
    img = Image.open(rose_tif)
    img.load()  # verify file is readable

    slist = Document(db=temp_db.name)

    mlp = safe_mainloop(2000)

    asserts = 0
    finished_cb = MagicMock()

    def cancelled_cb(response):
        nonlocal asserts
        assert len(slist.data) == 0, "TIFF not imported"
        asserts += 1
        mlp.quit()

    slist.import_files(
        paths=[rose_tif],
        finished_callback=finished_cb,
    )
    slist.cancel(cancelled_cb)

    mlp.run()

    assert asserts == 1, "all callbacks run"
    finished_cb.assert_not_called(), "no error callback called"

    import_in_mainloop(slist, [rose_tif])
    page = get_page_sync(slist.thread, id=1)
    assert (
        page.image_object.mode == "RGB"
    ), "TIFF imported correctly after cancelling previous import"
