# -*- coding: utf-8 -*-
"""Tests for the ICCGenerator class."""

import datetime
import json
import logging
import os
import pathlib
import platform
import sys
import tempfile

import pytest

from icc_generator import logger
from icc_generator.api import ICCGenerator, HERE, PaperSizeLibrary


def test_initializing_without_any_args():
    """class ICCGenerator initializes correctly."""
    icc_gen = ICCGenerator()

    # check default values
    assert icc_gen.printer_brand == "Epson"
    assert icc_gen.printer_model == "ET-8550"
    assert icc_gen.paper_brand == "Kodak"
    assert icc_gen.paper_model == "UPPP"
    assert icc_gen.paper_finish == "Glossy"
    assert icc_gen.paper_size == PaperSizeLibrary.A4
    assert icc_gen.ink_brand == "CanonInk"
    assert icc_gen.use_high_density_mode is True
    assert icc_gen.number_of_pages == 1
    assert icc_gen.copyright_info == ""


def test_printer_brand_arg_is_skipped():
    """Default value is used if printer_brand arg is skipped."""
    icc_gen = ICCGenerator()
    assert icc_gen.printer_brand == "Epson"


def test_printer_brand_arg_is_none():
    """printer_brand arg is set to None will raise an TypeError."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(printer_brand=None)
    assert str(cm.value) == (
        "ICCGenerator.printer_brand should be a str, not NoneType: 'None'"
    )


def test_printer_brand_attr_is_set_to_none():
    """TypeError raised if printer_brand attr is set to None."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.printer_brand = None
    assert str(cm.value) == (
        "ICCGenerator.printer_brand should be a str, not NoneType: 'None'"
    )


def test_printer_brand_arg_is_not_a_str():
    """TypeError raised if printer_brand arg value is not a str."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(printer_brand=312)
    assert str(cm.value) == (
        "ICCGenerator.printer_brand should be a str, not int: '312'"
    )


def test_printer_brand_attr_is_not_set_to_a_str():
    """TypeError raised if printer_brand attr is not a str."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.printer_brand = 443

    assert str(cm.value) == (
        "ICCGenerator.printer_brand should be a str, not int: '443'"
    )


def test_printer_brand_arg_is_working_properly():
    """printer_brand arg value is properly passed to the printer_brand attr."""
    test_value = "Epson"
    icc_gen = ICCGenerator(printer_brand=test_value)
    assert icc_gen.printer_brand == test_value


def test_printer_brand_attr_is_working_properly():
    """printer_brand attr is working properly."""
    test_value = "Canon"
    icc_gen = ICCGenerator()
    assert icc_gen.printer_brand != test_value
    icc_gen.printer_brand = test_value
    assert icc_gen.printer_brand == test_value


def test_printer_model_arg_is_skipped():
    """default value is used if printer_model arg is skipped."""
    icc_gen = ICCGenerator()
    assert icc_gen.printer_model == "ET-8550"


def test_printer_model_arg_is_none():
    """printer_model arg is set to None will raise an TypeError."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(printer_model=None)
    assert str(cm.value) == (
        "ICCGenerator.printer_model should be a str, not NoneType: 'None'"
    )


def test_printer_model_attr_is_set_to_none():
    """TypeError raised if printer_model attr is set to None."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.printer_model = None

    assert str(cm.value) == (
        "ICCGenerator.printer_model should be a str, not NoneType: 'None'"
    )


def test_printer_model_arg_is_not_a_str():
    """TypeError raised if printer_model arg value is not a str."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(printer_model=312)
    assert str(cm.value) == (
        "ICCGenerator.printer_model should be a str, not int: '312'"
    )


def test_printer_model_attr_is_not_set_to_a_str():
    """TypeError raised if printer_model attr is not a str."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.printer_model = 443
    assert str(cm.value) == (
        "ICCGenerator.printer_model should be a str, not int: '443'"
    )


def test_printer_model_arg_is_working_properly():
    """printer_model arg value is properly passed to the printer_model attr."""
    test_value = "iP7250"
    icc_gen = ICCGenerator(printer_model=test_value)
    assert icc_gen.printer_model == test_value


def test_printer_model_attr_is_working_properly():
    """printer_model attr is working properly."""
    test_value = "iP7250"
    icc_gen = ICCGenerator()
    assert icc_gen.printer_model != test_value
    icc_gen.printer_model = test_value
    assert icc_gen.printer_model == test_value


def test_paper_brand_arg_is_skipped():
    """default value is used if paper_brand arg is skipped."""
    icc_gen = ICCGenerator()
    assert icc_gen.paper_brand == "Kodak"


def test_paper_brand_arg_is_none():
    """paper_brand arg is set to None will raise an TypeError."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(paper_brand=None)
    assert str(cm.value) == (
        "ICCGenerator.paper_brand should be a str, not NoneType: 'None'"
    )


def test_paper_brand_attr_is_set_to_none():
    """TypeError raised if paper_brand attr is set to None."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.paper_brand = None
    assert str(cm.value) == (
        "ICCGenerator.paper_brand should be a str, not NoneType: 'None'"
    )


def test_paper_brand_arg_is_not_a_str():
    """TypeError raised if paper_brand arg value is not a str."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(paper_brand=312)

    assert str(cm.value) == (
        "ICCGenerator.paper_brand should be a str, not int: '312'"
    )


def test_paper_brand_attr_is_not_set_to_a_str():
    """TypeError raised if paper_brand attr is set to a value other than a str."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.paper_brand = 443
    assert str(cm.value) == (
        "ICCGenerator.paper_brand should be a str, not int: '443'"
    )


def test_paper_brand_arg_is_working_properly():
    """paper_brand arg value is properly passed to the paper_brand attr."""
    test_value = "Hahnemuhle"
    icc_gen = ICCGenerator(paper_brand=test_value)
    assert icc_gen.paper_brand == test_value


def test_paper_brand_attr_is_working_properly():
    """paper_brand attr is working properly."""
    test_value = "Hahnemuhle"
    icc_gen = ICCGenerator()
    assert icc_gen.paper_brand != test_value
    icc_gen.paper_brand = test_value
    assert icc_gen.paper_brand == test_value


def test_paper_model_arg_is_skipped():
    """default value is used if paper_model arg is skipped."""
    icc_gen = ICCGenerator()
    assert icc_gen.paper_model == "UPPP"


def test_paper_model_arg_is_none():
    """paper_model arg is set to None will raise an TypeError."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(paper_model=None)
    assert str(cm.value) == (
        "ICCGenerator.paper_model should be a str, not NoneType: 'None'"
    )


def test_paper_model_attr_is_set_to_none():
    """TypeError raised if paper_model attr is set to None."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.paper_model = None
    assert str(cm.value) == (
        "ICCGenerator.paper_model should be a str, not NoneType: 'None'"
    )


def test_paper_model_arg_is_not_a_str():
    """TypeError raised if paper_model arg value is not a str."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(paper_model=312)
    assert str(cm.value) == (
        "ICCGenerator.paper_model should be a str, not int: '312'"
    )


def test_paper_model_attr_is_not_set_to_a_str():
    """TypeError raised if paper_model attr is set to a value other than a str."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.paper_model = 443
    assert str(cm.value) == (
        "ICCGenerator.paper_model should be a str, not int: '443'"
    )


def test_paper_model_arg_is_working_properly():
    """paper_model arg value is properly passed to the paper_model attr."""
    test_value = "FineArt"
    icc_gen = ICCGenerator(paper_model=test_value)
    assert icc_gen.paper_model == test_value


def test_paper_model_attr_is_working_properly():
    """paper_model attr is working properly."""
    test_value = "FineArt"
    icc_gen = ICCGenerator()
    assert icc_gen.paper_model != test_value
    icc_gen.paper_model = test_value
    assert icc_gen.paper_model == test_value


def test_paper_finish_arg_is_skipped():
    """default value is used if paper_finish arg is skipped."""
    icc_gen = ICCGenerator()
    assert icc_gen.paper_finish == "Glossy"


def test_paper_finish_arg_is_none():
    """paper_finish arg is set to None will raise an TypeError."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(paper_finish=None)
    assert str(cm.value) == (
        "ICCGenerator.paper_finish should be a str, not NoneType: 'None'"
    )


def test_paper_finish_attr_is_set_to_none():
    """TypeError raised if paper_finish attr is set to None."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.paper_finish = None
    assert str(cm.value) == (
        "ICCGenerator.paper_finish should be a str, not NoneType: 'None'"
    )


def test_paper_finish_arg_is_not_a_str():
    """TypeError raised if paper_finish arg value is not a str."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(paper_finish=312)
    assert str(cm.value) == (
        "ICCGenerator.paper_finish should be a str, not int: '312'"
    )


def test_paper_finish_attr_is_not_set_to_a_str():
    """TypeError raised if paper_finish attr is set to a value other than a str."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.paper_finish = 443
    assert str(cm.value) == (
        "ICCGenerator.paper_finish should be a str, not int: '443'"
    )


def test_paper_finish_arg_is_working_properly():
    """paper_finish arg value is properly passed to the paper_finish attr."""
    test_value = "Silk"
    icc_gen = ICCGenerator(paper_finish=test_value)
    assert icc_gen.paper_finish == test_value


def test_paper_finish_attr_is_working_properly():
    """paper_finish attr is working properly."""
    test_value = "Silk"
    icc_gen = ICCGenerator()
    assert icc_gen.paper_finish != test_value
    icc_gen.paper_finish = test_value
    assert icc_gen.paper_finish == test_value


def test_ink_brand_arg_is_skipped():
    """default value is used if ink_brand arg is skipped."""
    icc_gen = ICCGenerator()
    assert icc_gen.ink_brand == "CanonInk"


def test_ink_brand_arg_is_none():
    """ink_brand arg is set to None will raise an TypeError."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(ink_brand=None)
    assert str(cm.value) == (
        "ICCGenerator.ink_brand should be a str, not NoneType: 'None'"
    )


def test_ink_brand_attr_is_set_to_none():
    """TypeError raised if ink_brand attr is set to None."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.ink_brand = None
    assert str(cm.value) == (
        "ICCGenerator.ink_brand should be a str, not NoneType: 'None'"
    )


def test_ink_brand_arg_is_not_a_str():
    """TypeError raised if ink_brand arg value is not a str."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(ink_brand=312)
    assert str(cm.value) == (
        "ICCGenerator.ink_brand should be a str, not int: '312'"
    )


def test_ink_brand_attr_is_not_set_to_a_str():
    """TypeError raised if ink_brand attr is set to a value other than a str."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.ink_brand = 443
    assert str(cm.value) == (
        "ICCGenerator.ink_brand should be a str, not int: '443'"
    )


def test_ink_brand_arg_is_working_properly():
    """ink_brand arg value is properly passed to the ink_brand attr."""
    test_value = "PhotoInk"
    icc_gen = ICCGenerator(ink_brand=test_value)
    assert icc_gen.ink_brand == test_value


def test_ink_brand_attr_is_working_properly():
    """ink_brand attr is working properly."""
    test_value = "PhotoInk"
    icc_gen = ICCGenerator()
    assert icc_gen.ink_brand != test_value
    icc_gen.ink_brand = test_value
    assert icc_gen.ink_brand == test_value


def test_paper_size_arg_is_skipped():
    """default value is used if paper_size arg is skipped."""
    icc_gen = ICCGenerator()
    assert icc_gen.paper_size == PaperSizeLibrary.A4


def test_paper_size_arg_is_none():
    """paper_size arg is set to None will use the default."""
    ig = ICCGenerator(paper_size=None)
    assert PaperSizeLibrary.A4 == ig.paper_size


def test_paper_size_attr_is_set_to_none():
    """TypeError raised if paper_size attr is set to None."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.paper_size = None
    assert str(cm.value) == (
        "ICCGenerator.paper_size should be a PaperSize instance, not NoneType: 'None'"
    )


def test_paper_size_arg_is_not_a_paper_size_object():
    """TypeError raised if paper_size arg value is not a PaperSize instance."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(paper_size=312)
    assert str(cm.value) == (
        "ICCGenerator.paper_size should be a PaperSize instance, not int: '312'"
    )


def test_paper_size_attr_is_not_set_to_a_paper_size_instance():
    """TypeError raised if paper_size attr is not a PaperSize instance."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.paper_size = 443
    assert str(cm.value) == (
        "ICCGenerator.paper_size should be a PaperSize instance, not int: '443'"
    )


def test_paper_size_arg_is_working_properly():
    """paper_size arg value is properly passed to the paper_size attr."""
    test_value = PaperSizeLibrary.A3
    icc_gen = ICCGenerator(paper_size=test_value)
    assert icc_gen.paper_size == test_value


def test_paper_size_attr_is_working_properly():
    """paper_size attr is working properly."""
    test_value = PaperSizeLibrary.A3
    icc_gen = ICCGenerator()
    assert icc_gen.paper_size != test_value
    icc_gen.paper_size = test_value
    assert icc_gen.paper_size == test_value


def test_number_of_pages_arg_is_skipped():
    """default value is used if number_of_pages arg is skipped."""
    icc_gen = ICCGenerator()
    assert icc_gen.number_of_pages == 1


def test_number_of_pages_arg_is_none():
    """number_of_pages arg is set to None will raise an TypeError"""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(number_of_pages=None)
    assert str(cm.value) == (
        "ICCGenerator.number_of_pages should be a int, not NoneType: 'None'"
    )


def test_number_of_pages_attr_is_set_to_none():
    """TypeError raised if number_of_pages attr is set to None."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.number_of_pages = None
    assert str(cm.value) == (
        "ICCGenerator.number_of_pages should be a int, not NoneType: 'None'"
    )


def test_number_of_pages_arg_is_not_a_str():
    """TypeError raised if number_of_pages arg value is not a str."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(number_of_pages="312")
    assert str(cm.value) == (
        "ICCGenerator.number_of_pages should be a int, not str: '312'"
    )


def test_number_of_pages_attr_is_not_set_to_a_str():
    """TypeError raised if number_of_pages attr is set to a value other than a str."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.number_of_pages = "443"
    assert str(cm.value) == (
        "ICCGenerator.number_of_pages should be a int, not str: '443'"
    )


def test_number_of_pages_arg_is_working_properly():
    """number_of_pages arg value is properly passed to the number_of_pages attr."""
    test_value = 10
    icc_gen = ICCGenerator(number_of_pages=test_value)
    assert icc_gen.number_of_pages == test_value


def test_number_of_pages_attr_is_working_properly():
    """number_of_pages attr is working properly."""
    test_value = 10
    icc_gen = ICCGenerator()
    assert icc_gen.number_of_pages != test_value
    icc_gen.number_of_pages = test_value
    assert icc_gen.number_of_pages == test_value


def test_copyright_info_arg_is_skipped():
    """default value is used if copyright_info arg is skipped."""
    icc_gen = ICCGenerator()
    assert icc_gen.copyright_info == ""


def test_copyright_info_arg_is_none():
    """copyright_info arg is set to None will raise an TypeError."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(copyright_info=None)

    assert str(cm.value) == (
        "ICCGenerator.copyright_info should be a str, not NoneType: 'None'"
    )


def test_copyright_info_attr_is_set_to_none():
    """TypeError raised if copyright_info attr is set to None."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.copyright_info = None
    assert str(cm.value) == (
        "ICCGenerator.copyright_info should be a str, not NoneType: 'None'"
    )


def test_copyright_info_arg_is_not_a_str():
    """TypeError raised if copyright_info arg value is not a str."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(copyright_info=312)
    assert str(cm.value) == (
        "ICCGenerator.copyright_info should be a str, not int: '312'"
    )


def test_copyright_info_attr_is_not_set_to_a_str():
    """TypeError raised if copyright_info attr is set to a value other than a str."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.copyright_info = 443
    assert str(cm.value) == (
        "ICCGenerator.copyright_info should be a str, not int: '443'"
    )


def test_copyright_info_arg_is_working_properly():
    """copyright_info arg value is properly passed to the copyright_info attr."""
    test_value = "Erkan Ozgur Yilmaz"
    icc_gen = ICCGenerator(copyright_info=test_value)
    assert icc_gen.copyright_info == test_value


def test_copyright_info_attr_is_working_properly():
    """copyright_info attr is working properly."""
    test_value = "Erkan Ozgur Yilmaz"
    icc_gen = ICCGenerator()
    assert icc_gen.copyright_info != test_value
    icc_gen.copyright_info = test_value
    assert icc_gen.copyright_info == test_value


def test_precondition_profile_path_arg_is_skipped():
    """default value is used if precondition_profile_path arg is skipped."""
    icc_gen = ICCGenerator()
    assert icc_gen.precondition_profile_path == ""


def test_precondition_profile_path_arg_is_none():
    """precondition_profile_path arg is set to None will raise an TypeError."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(precondition_profile_path=None)

    assert str(cm.value) == (
        "ICCGenerator.precondition_profile_path should be a str, "
        "not NoneType: 'None'"
    )


def test_precondition_profile_path_attr_is_set_to_none():
    """TypeError raised if precondition_profile_path attr is set to None."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.precondition_profile_path = None

    assert str(cm.value) == (
        "ICCGenerator.precondition_profile_path should be a str, "
        "not NoneType: 'None'"
    )


def test_precondition_profile_path_arg_is_not_a_str():
    """TypeError raised if precondition_profile_path arg value is not a str."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(precondition_profile_path=312)
    assert str(cm.value) == (
        "ICCGenerator.precondition_profile_path should be a str, not int: '312'"
    )


def test_precondition_profile_path_attr_is_not_set_to_a_str():
    """TypeError raised if precondition_profile_path attr is not a str."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.precondition_profile_path = 443

    assert str(cm.value) == (
        "ICCGenerator.precondition_profile_path should be a str, not int: '443'"
    )


def test_precondition_profile_path_arg_is_working_properly():
    """precondition_profile_path arg is passed to the precondition_profile_path attr."""
    test_value = "Epson"
    icc_gen = ICCGenerator(precondition_profile_path=test_value)
    assert icc_gen.precondition_profile_path == test_value


def test_precondition_profile_path_attr_is_working_properly():
    """precondition_profile_path attr is working properly."""
    test_value = "Epson"
    icc_gen = ICCGenerator()
    assert icc_gen.precondition_profile_path != test_value
    icc_gen.precondition_profile_path = test_value
    assert icc_gen.precondition_profile_path == test_value


def test_use_high_density_mode_arg_is_skipped():
    """default value is used if use_high_density_mode arg is skipped."""
    icc_gen = ICCGenerator()
    assert icc_gen.use_high_density_mode is True


def test_use_high_density_mode_arg_is_none():
    """use_high_density_mode arg is set to None will raise an TypeError."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(use_high_density_mode=None)
    assert str(cm.value) == (
        "ICCGenerator.use_high_density_mode should be a bool (True or False), "
        "not NoneType: 'None'"
    )


def test_use_high_density_mode_attr_is_set_to_none():
    """TypeError raised if the use_high_density_mode attr is set to None."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.use_high_density_mode = None

    assert str(cm.value) == (
        "ICCGenerator.use_high_density_mode should be a bool (True or False), "
        "not NoneType: 'None'"
    )


def test_use_high_density_mode_arg_is_not_a_bool():
    """TypeError raised if the use_high_density_mode arg value is not a str."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(use_high_density_mode=312)
    assert str(cm.value) == (
        "ICCGenerator.use_high_density_mode should be a bool (True or False), "
        "not int: '312'"
    )


def test_use_high_density_mode_attr_is_not_set_to_a_str():
    """TypeError raised if the use_high_density_mode attr is not a str."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.use_high_density_mode = 443

    assert str(cm.value) == (
        "ICCGenerator.use_high_density_mode should be a bool (True or False), "
        "not int: '443'"
    )


def test_use_high_density_mode_arg_is_working_properly():
    """use_high_density_mode arg is passed to the use_high_density_mode attr."""
    test_value = False
    icc_gen = ICCGenerator(use_high_density_mode=test_value)
    assert icc_gen.use_high_density_mode == test_value


def test_use_high_density_mode_attr_is_working_properly():
    """use_high_density_mode attr is working properly."""
    test_value = False
    icc_gen = ICCGenerator()
    assert icc_gen.use_high_density_mode != test_value
    icc_gen.use_high_density_mode = test_value
    assert icc_gen.use_high_density_mode == test_value


def test_initializing_non_default_values():
    """class ICCGenerator initializes non default values correctly."""
    now = datetime.datetime.now()
    date_str = now.strftime("%Y%m%d")
    time_str = now.strftime("%H%M")
    icc_gen = ICCGenerator()

    assert icc_gen.profile_date == date_str
    assert icc_gen.profile_time == time_str
    profile_name = f"Epson_ET-8550_Default_Kodak_UPPP_Glossy_A4_CanonInk_{date_str}_{time_str}"
    assert icc_gen.profile_name == profile_name


def test_paper_sizes():
    """default page sizes are working properly."""
    icc_gen = ICCGenerator()
    assert icc_gen.paper_size == PaperSizeLibrary.A4


def test_per_page_patch_count_is_updated_properly():
    """per_page_patch_count is updated with the paper size and use_high_density_mode."""
    icc_gen = ICCGenerator()

    # Set the paper size to A4
    icc_gen.paper_size = PaperSizeLibrary.A4
    icc_gen.use_high_density_mode = False
    assert icc_gen.per_page_patch_count == 196

    icc_gen.use_high_density_mode = True
    assert icc_gen.per_page_patch_count == 728

    # Set the paper size to A3
    icc_gen.paper_size = PaperSizeLibrary.A3
    icc_gen.use_high_density_mode = False
    assert icc_gen.per_page_patch_count == 483

    icc_gen.use_high_density_mode = True
    assert icc_gen.per_page_patch_count == 1640


def test_patch_count_is_read_only():
    """patch_count is a read only property."""
    icc_gen = ICCGenerator()
    with pytest.raises(AttributeError) as _:
        icc_gen.patch_count = 120


def test_gray_patch_count_arg_is_skipped():
    """default value is used if gray_patch_count arg is skipped."""
    icc_gen = ICCGenerator()
    assert icc_gen.gray_patch_count == 128


def test_gray_patch_count_arg_is_none():
    """gray_patch_count arg is set to None will raise an TypeError."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(gray_patch_count=None)
    assert str(cm.value) == (
        "ICCGenerator.gray_patch_count should be an int, not NoneType: 'None'"
    )


def test_gray_patch_count_attr_is_set_to_none():
    """TypeError raised if gray_patch_count attr is set to None."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.gray_patch_count = None
    assert str(cm.value) == (
        "ICCGenerator.gray_patch_count should be an int, not NoneType: 'None'"
    )


def test_gray_patch_count_arg_is_not_an_int():
    """TypeError raised if gray_patch_count arg value is not an int."""
    with pytest.raises(TypeError) as cm:
        _ = ICCGenerator(gray_patch_count="312")
    assert str(cm.value) == (
        "ICCGenerator.gray_patch_count should be an int, not str: '312'"
    )


def test_gray_patch_count_attr_is_not_set_to_an_int():
    """TypeError raised if gray_patch_count attr is set to a value other than an int."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.gray_patch_count = "443"
    assert str(cm.value) == (
        "ICCGenerator.gray_patch_count should be an int, not str: '443'"
    )


def test_gray_patch_count_arg_is_working_properly():
    """gray_patch_count arg value is properly passed to the gray_patch_count attr."""
    test_value = 64
    icc_gen = ICCGenerator(gray_patch_count=test_value)
    assert icc_gen.gray_patch_count == test_value


def test_gray_patch_count_attr_is_working_properly():
    """gray_patch_count attr is working properly."""
    test_value = 64
    icc_gen = ICCGenerator()
    assert icc_gen.gray_patch_count != test_value
    icc_gen.gray_patch_count = test_value
    assert icc_gen.gray_patch_count == test_value


def test_gray_patch_count_is_updated_properly():
    """gray_patch_count is updated with the paper size and use_high_density_mode."""
    icc_gen = ICCGenerator()

    # Set the paper size to A4
    icc_gen.paper_size = PaperSizeLibrary.A4
    icc_gen.number_of_pages = 1
    assert icc_gen.gray_patch_count == 128

    icc_gen.number_of_pages = 2
    assert icc_gen.gray_patch_count == 128

    icc_gen.number_of_pages = 3
    assert icc_gen.gray_patch_count == 128

    icc_gen.number_of_pages = 4
    assert icc_gen.gray_patch_count == 128

    icc_gen.gray_patch_count = 25
    assert icc_gen.number_of_pages == 4
    assert icc_gen.gray_patch_count == 25


def test_gray_patch_count_is_not_read_only():
    """gray_patch_count is not a read only property."""
    icc_gen = ICCGenerator()
    icc_gen.gray_patch_count = 120
    assert icc_gen.gray_patch_count == 120


def test_patch_count_is_updating_properly():
    """patch_count is updating with page_size, page_count and use_high_density_mode."""
    icc_gen = ICCGenerator()

    # Paper Size:A4
    # Use High Density Mode: False
    icc_gen.paper_size = PaperSizeLibrary.A4
    icc_gen.use_high_density_mode = False

    # 1 Page
    icc_gen.number_of_pages = 1
    assert icc_gen.patch_count == 196

    # 2 Pages
    icc_gen.number_of_pages = 2
    assert icc_gen.patch_count == 392

    # 3 Pages
    icc_gen.number_of_pages = 3
    assert icc_gen.patch_count == 588

    # Use High Density Mode: True
    icc_gen.use_high_density_mode = True

    # 1 Page
    icc_gen.number_of_pages = 1
    assert icc_gen.patch_count == 728

    # 2 Pages
    icc_gen.number_of_pages = 2
    assert icc_gen.patch_count == 1456

    # 3 Pages
    icc_gen.number_of_pages = 3
    assert icc_gen.patch_count == 2184

    # Paper Size:A3
    # Use High Density Mode: False
    icc_gen.paper_size = PaperSizeLibrary.A3
    icc_gen.use_high_density_mode = False

    # 1 Page
    icc_gen.number_of_pages = 1
    assert icc_gen.patch_count == 483

    # 2 Pages
    icc_gen.number_of_pages = 2
    assert icc_gen.patch_count == 966

    # 3 Pages
    icc_gen.number_of_pages = 3
    assert icc_gen.patch_count == 1449

    # Use High Density Mode: True
    icc_gen.use_high_density_mode = True

    # 1 Page
    icc_gen.number_of_pages = 1
    assert icc_gen.patch_count == 1640

    # 2 Pages
    icc_gen.number_of_pages = 2
    assert icc_gen.patch_count == 3280

    # 3 Pages
    icc_gen.number_of_pages = 3
    assert icc_gen.patch_count == 4920


def test_profile_name_template_default_value():
    """profile_name_template default value is correct."""
    icc_gen = ICCGenerator()
    assert icc_gen.profile_name_template == (
        "{printer_brand}_{printer_model}_{printer_paper_setting}_"
        "{paper_brand}_{paper_model}_{paper_finish}_{paper_size}_{ink_brand}_"
        "{profile_date}_{profile_time}"
    )


def test_profile_name_default_value_is_properly_calculated():
    """profile_name default value is properly calculated."""
    now = datetime.datetime.now()
    date_str = now.strftime("%Y%m%d")
    time_str = now.strftime("%H%M")
    icc_gen = ICCGenerator()

    assert icc_gen.profile_date == date_str
    assert icc_gen.profile_time == time_str
    profile_name = f"Epson_ET-8550_Default_Kodak_UPPP_Glossy_A4_CanonInk_{date_str}_{time_str}"
    assert icc_gen.profile_name == profile_name


def test_profile_name_is_working_properly():
    """profile_name attr is working properly."""
    icc_gen = ICCGenerator()

    # the profile_name could be updated in any ways the user wanted
    test_value = "This is a valid profile name (but a bad one)"
    icc_gen.profile_name = test_value
    assert icc_gen.profile_name == test_value


def test_profile_path_template_default_value():
    """profile_path_template default value is correct."""
    icc_gen = ICCGenerator()

    assert (
        icc_gen._profile_path_template == "~/.cache/ICCGenerator/{printer_brand}_"
        "{printer_model}/{profile_date}"
    )


def test_profile_path_default_value_is_properly_calculated():
    """profile_path default value is properly calculated."""
    now = datetime.datetime.now()
    date_str = now.strftime("%Y%m%d")
    time_str = now.strftime("%H%M")
    icc_gen = ICCGenerator()

    assert icc_gen.profile_date == date_str
    assert icc_gen.profile_time == time_str
    profile_path = pathlib.Path(
        f"~/.cache/ICCGenerator/Epson_ET-8550/{date_str}"
    ).expanduser()
    assert icc_gen.profile_path == profile_path


def test_profile_path_is_read_only():
    """profile_path property is read only."""
    icc_gen = ICCGenerator()

    # the profile_path could be updated in any ways the user wanted
    with pytest.raises(AttributeError):
        icc_gen.profile_path = "some value"


def test_profile_absolute_path_is_properly_calculated():
    """profile_absolute_path is properly calculated."""
    now = datetime.datetime.now()
    date_str = now.strftime("%Y%m%d")
    time_str = now.strftime("%H%M")
    icc_gen = ICCGenerator()

    assert icc_gen.profile_date == date_str
    assert icc_gen.profile_time == time_str
    profile_path = pathlib.Path(
        f"~/.cache/ICCGenerator/Epson_ET-8550/{date_str}"
    ).expanduser()
    assert icc_gen.profile_absolute_path == profile_path


def test_profile_absolute_path_is_is_read_only():
    """profile_absolute_path is properly calculated."""
    now = datetime.datetime.now()
    date_str = now.strftime("%Y%m%d")
    time_str = now.strftime("%H%M")
    icc_gen = ICCGenerator()

    assert icc_gen.profile_date == date_str
    assert icc_gen.profile_time == time_str
    profile_path = pathlib.Path(
        f"~/.cache/ICCGenerator/Epson_ET-8550/{date_str}"
    ).expanduser()
    with pytest.raises(AttributeError) as cm:
        icc_gen.profile_absolute_path = profile_path

    error_message = {
        8: "can't set attribute",
        9: "can't set attribute",
        10: "can't set attribute 'profile_absolute_path'",
        11: "property 'profile_absolute_path' of 'ICCGenerator' object has no setter",
        12: "property 'profile_absolute_path' of 'ICCGenerator' object has no setter",
        13: "property 'profile_absolute_path' of 'ICCGenerator' object has no setter",
    }.get(
        sys.version_info.minor,
        "property 'profile_absolute_path' of 'ICCGenerator' object has no setter",
    )

    assert str(cm.value) == error_message


def test_profile_absolute_full_path_is_properly_calculated():
    """profile_absolute_full_path is properly calculated."""
    now = datetime.datetime.now()
    date_str = now.strftime("%Y%m%d")
    time_str = now.strftime("%H%M")
    icc_gen = ICCGenerator()

    assert icc_gen.profile_date == date_str
    assert icc_gen.profile_time == time_str
    profile_path = pathlib.Path(
        f"~/.cache/ICCGenerator/Epson_ET-8550/{date_str}"
    ).expanduser()
    assert icc_gen.profile_absolute_full_path == profile_path / icc_gen.profile_name


def test_profile_absolute_full_path_is_is_read_only():
    """profile_absolute_full_path is properly calculated."""
    now = datetime.datetime.now()
    date_str = now.strftime("%Y%m%d")
    time_str = now.strftime("%H%M")
    icc_gen = ICCGenerator()

    assert icc_gen.profile_date == date_str
    assert icc_gen.profile_time == time_str
    profile_path = pathlib.Path(
        f"~/.cache/ICCGenerator/Canon_iX6850/{date_str}"
    ).expanduser()
    with pytest.raises(AttributeError) as cm:
        icc_gen.profile_absolute_full_path = profile_path

    error_message = {
        8: "can't set attribute",
        9: "can't set attribute",
        10: "can't set attribute 'profile_absolute_full_path'",
        11: "property 'profile_absolute_full_path' of 'ICCGenerator' "
        "object has no setter",
        12: "property 'profile_absolute_full_path' of 'ICCGenerator' "
        "object has no setter",
        13: "property 'profile_absolute_full_path' of 'ICCGenerator' "
        "object has no setter",
    }.get(sys.version_info.minor)

    assert str(cm.value) == error_message


def test_generate_target_creates_the_output_folder(file_collector):
    """generate_target will create the output folder."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    # There should be files under the temp folder
    # check them
    # set it to use only one A4 page
    icc_gen.number_of_pages = 1
    icc_gen.paper_size = PaperSizeLibrary.A4
    file_collector.append(icc_gen.profile_absolute_path)
    icc_gen.generate_target()
    assert icc_gen.output_path.exists()


def test_generate_target_generates_ti_file(file_collector):
    """generate_target will generate ti file."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    # There should be files under the temp folder
    # check them
    # set it to use only one A4 page
    icc_gen.number_of_pages = 1
    icc_gen.paper_size = PaperSizeLibrary.A4
    file_collector.append(icc_gen.profile_path)
    icc_gen.generate_target()
    assert (icc_gen.profile_path / f"{icc_gen.profile_name}.ti1").exists()


def test_generate_target_with_precondition_profile_arg(
    file_collector, patch_run_external_process
):
    """generate_target will generate ti file."""
    commands = patch_run_external_process
    precondition_profile_path = "pre_condition_profile_path.icc"
    icc_gen = ICCGenerator(
        printer_brand="RandomPrinterBrand",
        precondition_profile_path=precondition_profile_path,
    )
    # set it to use only one A4 page
    icc_gen.number_of_pages = 1
    icc_gen.paper_size = PaperSizeLibrary.A4
    file_collector.append(icc_gen.profile_path)
    icc_gen.generate_target()
    assert precondition_profile_path in commands[-1]


def test_generate_target_with_precondition_profile_attr(
    file_collector, patch_run_external_process
):
    """generate_target will generate ti file."""
    commands = patch_run_external_process
    precondition_profile_path = "pre_condition_profile_path.icc"
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    icc_gen.precondition_profile_path = precondition_profile_path
    # set it to use only one A4 page
    icc_gen.number_of_pages = 1
    icc_gen.paper_size = PaperSizeLibrary.A4
    file_collector.append(icc_gen.profile_path)
    icc_gen.generate_target()
    assert precondition_profile_path in commands[-1]


def test_generate_target_without_precondition_profile_attr(
    file_collector, patch_run_external_process
):
    """generate_target will generate ti file."""
    commands = patch_run_external_process
    precondition_profile_path = "pre_condition_profile_path.icc"
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    # set it to use only one A4 page
    icc_gen.number_of_pages = 1
    icc_gen.paper_size = PaperSizeLibrary.A4
    file_collector.append(icc_gen.profile_path)
    icc_gen.generate_target()
    assert precondition_profile_path not in commands[-1]


def test_generate_tif_files_will_generate_tif_files_from_target_file(file_collector):
    """generate_tif_files will generate tif file or files from target file."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    # There should be files under the temp folder
    # check them
    # set it to use only one A4 page
    icc_gen.number_of_pages = 1
    icc_gen.paper_size = PaperSizeLibrary.A4
    file_collector.append(icc_gen.profile_path)
    icc_gen.generate_target()
    icc_gen.generate_tif()
    profile_absolute_full_path = icc_gen.profile_path / f"{icc_gen.profile_name}.tif"
    assert profile_absolute_full_path.exists()
    assert not (icc_gen.profile_path / f"{icc_gen.profile_name}_02.tif").exists()


def test_generate_tif_files_will_generates_correct_amount_of_tif_files(file_collector):
    """generate_tif_files correct amount of tif files."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    # There should be files under the temp folder
    # check them
    # set it to use only one A4 page
    icc_gen.number_of_pages = 2
    icc_gen.paper_size = PaperSizeLibrary.A4
    # append the folder to the file_collector
    # so, it is cleaned up after the test
    file_collector.append(icc_gen.profile_path)

    icc_gen.generate_target()
    icc_gen.generate_tif()

    assert (icc_gen.profile_path / f"{icc_gen.profile_name}_01.tif").exists()
    assert (icc_gen.profile_path / f"{icc_gen.profile_name}_02.tif").exists()


def test_generate_tif_files_will_fill_tif_files_attr_single_page(file_collector):
    """generate_tif_files fills the tif_files correctly if there is only one page."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    # There should be files under the temp folder
    # check them
    # set it to use only one A4 page
    icc_gen.number_of_pages = 1
    icc_gen.paper_size = PaperSizeLibrary.A4
    # append the folder to the file_collector
    # so, it is cleaned up after the test
    file_collector.append(icc_gen.profile_path)

    icc_gen.generate_target()
    icc_gen.generate_tif()

    tif1 = icc_gen.profile_path / f"{icc_gen.profile_name}.tif"
    assert icc_gen.tif_files[0] == tif1


def test_generate_tif_files_will_fill_tif_files_attr_more_than_one_page(file_collector):
    """generate_tif_files will fill the tif_files list correctly."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    # There should be files under the temp folder
    # check them
    # set it to use only one A4 page
    icc_gen.number_of_pages = 2
    icc_gen.paper_size = PaperSizeLibrary.A4
    # append the folder to the file_collector
    # so, it is cleaned up after the test
    file_collector.append(icc_gen.profile_path)

    icc_gen.generate_target()
    icc_gen.generate_tif()

    tif1 = icc_gen.profile_path / f"{icc_gen.profile_name}_01.tif"
    tif2 = icc_gen.profile_path / f"{icc_gen.profile_name}_02.tif"

    assert icc_gen.tif_files[0] == tif1
    assert icc_gen.tif_files[1] == tif2


def test_generate_tif_files_will_clear_the_tif_files_list(file_collector):
    """generate_tif_files will clear the tif_files list before running."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    # There should be files under the temp folder
    # check them
    # set it to use only one A4 page
    icc_gen.number_of_pages = 2
    icc_gen.paper_size = PaperSizeLibrary.A4
    # append the folder to the file_collector
    # so, it is cleaned up after the test
    file_collector.append(icc_gen.profile_path)

    icc_gen.generate_target()
    icc_gen.generate_tif()

    tif1 = icc_gen.profile_path / f"{icc_gen.profile_name}_01.tif"
    tif2 = icc_gen.profile_path / f"{icc_gen.profile_name}_02.tif"
    assert len(icc_gen.tif_files) == 2
    assert icc_gen.tif_files[0] == tif1
    assert icc_gen.tif_files[1] == tif2

    # change number of pages to 1
    icc_gen.number_of_pages = 1
    file_collector.append(icc_gen.profile_path)

    icc_gen.generate_target()
    icc_gen.generate_tif()

    tif1 = icc_gen.profile_path / f"{icc_gen.profile_name}.tif"
    assert len(icc_gen.tif_files) == 1
    assert icc_gen.tif_files[0] == tif1


def test_generate_tif_files_with_high_density_mode(
    file_collector, patch_run_external_process
):
    """generate_tif_files uses i1Pro if the use_high_density_mode is True."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    # There should be files under the temp folder
    # check them
    # set it to use only one A4 page
    icc_gen.number_of_pages = 2
    icc_gen.paper_size = PaperSizeLibrary.A4
    # append the folder to the file_collector
    # so, it is cleaned up after the test
    file_collector.append(icc_gen.profile_path)

    icc_gen.generate_target()
    icc_gen.generate_tif()
    # check the final call to the run_external_process
    final_command = patch_run_external_process[-1]
    assert any(["-ii1" in arg for arg in final_command])


def test_generate_tif_files_with_normal_density_mode(
    file_collector, patch_run_external_process
):
    """generate_tif_files uses ColorMunki if the use_high_density_mode is False."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    # There should be files under the temp folder
    # check them
    # set it to use only one A4 page
    icc_gen.number_of_pages = 2
    icc_gen.paper_size = PaperSizeLibrary.A4
    icc_gen.use_high_density_mode = False
    # append the folder to the file_collector
    # so, it is cleaned up after the test
    file_collector.append(icc_gen.profile_path)

    icc_gen.generate_target()
    icc_gen.generate_tif()
    # check the final call to the run_external_process
    final_command = patch_run_external_process[-1]
    assert any(["-iCM" in arg for arg in final_command])


def test_print_charts(file_collector, patch_run_external_process):
    """print_charts is working properly."""
    # patch the run_external_process and check the command
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    icc_gen.number_of_pages = 1
    file_collector.append(icc_gen.profile_path)

    icc_gen.generate_target()
    icc_gen.generate_tif()
    icc_gen.print_charts()

    # check the final call to the run_external_process
    final_command = patch_run_external_process[-1]
    system_name = platform.system().lower()
    if "linux" in system_name:
        assert "gimp" in final_command[0]
    elif "darwin" in system_name:
        assert "/Applications/Print-Tool.app/Contents/MacOS/Print-Tool"


def test_read_charts_calls_chartread_command(
    file_collector, patch_run_external_process
):
    """read_charts method will call chartread."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    icc_gen.number_of_pages = 1
    file_collector.append(icc_gen.profile_path)
    icc_gen.generate_target()
    icc_gen.generate_tif()
    icc_gen.print_charts()
    icc_gen.read_charts()

    # check the final call to the run_external_process
    final_command = patch_run_external_process[-1]
    assert "chartread" in final_command[0]


def test_read_charts_with_resume_set_to_true(
    file_collector, patch_run_external_process
):
    """read_charts method with resume=True will call chartread with -r option."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    icc_gen.number_of_pages = 1
    file_collector.append(icc_gen.profile_path)
    icc_gen.generate_target()
    icc_gen.generate_tif()
    icc_gen.print_charts()
    icc_gen.read_charts(resume=True)

    # check the final call to the run_external_process
    final_command = patch_run_external_process[-1]
    assert "chartread" in final_command[0]
    assert any(["-r" in arg for arg in final_command])


def test_read_charts_with_read_mode_set_to_1(
    file_collector, patch_run_external_process
):
    """read_charts with read_mode=1 calls chartread with -p and -P options."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    icc_gen.number_of_pages = 1
    file_collector.append(icc_gen.profile_path)
    icc_gen.generate_target()
    icc_gen.generate_tif()
    icc_gen.print_charts()
    icc_gen.read_charts(read_mode=1)

    # check the final call to the run_external_process
    final_command = patch_run_external_process[-1]
    assert "chartread" in final_command[0]
    assert any(["-p" in arg for arg in final_command])
    assert any(["-P" in arg for arg in final_command])


def test_generate_profile_1(file_collector, patch_run_external_process):
    """generate_profile method is working properly."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    icc_gen.number_of_pages = 1
    file_collector.append(icc_gen.profile_path)
    icc_gen.generate_target()
    icc_gen.generate_tif()
    icc_gen.print_charts()
    icc_gen.read_charts()
    icc_gen.generate_profile()

    # check the final call to the run_external_process
    final_command = patch_run_external_process[-1]
    assert "colprof" in final_command[0]

    assert any(["-v" in arg for arg in final_command])
    assert any(["-qh" in arg for arg in final_command])
    assert any(["-r0.5" in arg for arg in final_command])
    assert any(["-S" in arg for arg in final_command])
    assert any(["-cmt" in arg for arg in final_command])
    assert any(["-dpp" in arg for arg in final_command])
    assert any(["-D" in arg for arg in final_command])


def test_generate_profile_2(file_collector, patch_run_external_process):
    """generate_profile method is working properly."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    icc_gen.number_of_pages = 1
    icc_gen.copyright_info = "Erkan Ozgur Yilmaz(c)2021"
    file_collector.append(icc_gen.profile_path)
    icc_gen.generate_target()
    icc_gen.generate_tif()
    icc_gen.print_charts()
    icc_gen.read_charts()
    icc_gen.generate_profile()

    # check the final call to the run_external_process
    final_command = patch_run_external_process[-1]
    assert "colprof" in final_command[0]
    assert any(["-CErkan Ozgur Yilmaz(c)2021" in arg for arg in final_command])


def test_check_profile(file_collector, patch_run_external_process):
    """check_profile method is working properly."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    file_collector.append(icc_gen.profile_path)
    icc_gen.number_of_pages = 1
    icc_gen.copyright_info = "Erkan Ozgur Yilmaz(c)2021"
    file_collector.append(icc_gen.profile_path)
    icc_gen.generate_target()
    icc_gen.generate_tif()
    icc_gen.print_charts()
    icc_gen.read_charts()
    icc_gen.generate_profile()
    icc_gen.check_profile()

    final_command = patch_run_external_process[-1]
    assert "profcheck" in final_command[0]
    assert any(["-k" in arg for arg in final_command])
    assert any(["-v2" in arg for arg in final_command])
    assert not any(["-s" in arg for arg in final_command])


def test_check_profile_with_sort(file_collector, patch_run_external_process):
    """check_profile method is working properly."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    file_collector.append(icc_gen.profile_path)
    icc_gen.number_of_pages = 1
    icc_gen.copyright_info = "Erkan Ozgur Yilmaz(c)2021"
    file_collector.append(icc_gen.profile_path)
    icc_gen.generate_target()
    icc_gen.generate_tif()
    icc_gen.print_charts()
    icc_gen.read_charts()
    icc_gen.generate_profile()
    icc_gen.check_profile(sort_by_de=True)

    final_command = patch_run_external_process[-1]
    assert "profcheck" in final_command[0]
    assert any(["-k" in arg for arg in final_command])
    assert any(["-v2" in arg for arg in final_command])
    assert any(["-s" in arg for arg in final_command])


def test_check_profile_with_correct_file_extension(
    file_collector, patch_run_external_process
):
    """check_profile uses the correct profile file extension"""
    # ICM on Windows and ICC on Linux
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    file_collector.append(icc_gen.profile_path)
    icc_gen.number_of_pages = 1
    icc_gen.copyright_info = "Erkan Ozgur Yilmaz(c)2021"
    file_collector.append(icc_gen.profile_path)
    icc_gen.generate_target()
    icc_gen.generate_tif()
    icc_gen.print_charts()
    icc_gen.read_charts()
    icc_gen.generate_profile()
    icc_gen.check_profile(sort_by_de=True)

    final_command = patch_run_external_process[-1]
    assert "profcheck" in final_command[0]

    if os.name == "nt":
        assert any([".icm" in arg for arg in final_command])
        assert not any([".icc" in arg for arg in final_command])
    else:
        assert not any([".icm" in arg for arg in final_command])
        assert any([".icc" in arg for arg in final_command])


def test_install_profile_1(file_collector, patch_run_external_process):
    """install_profile method is working properly."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    icc_gen.number_of_pages = 1
    icc_gen.copyright_info = "Erkan Ozgur Yilmaz(c)2021"
    file_collector.append(icc_gen.profile_path)

    # create a dummy icc file
    dummy_icc_profile_full_path = icc_gen.profile_path / f"{icc_gen.profile_name}.icc"
    os.makedirs(icc_gen.profile_path, exist_ok=True)
    assert icc_gen.profile_path
    with open(dummy_icc_profile_full_path, "w+") as f:
        f.write("dummy icc file!!!")
    assert dummy_icc_profile_full_path.exists()
    file_collector.append(dummy_icc_profile_full_path)

    icc_gen.install_profile()

    # this is easy
    # just check if ICC file is copied to the correct folder
    profile_install_path = None
    system_name = platform.system().lower()
    if "win32" in system_name:
        profile_install_path = pathlib.Path(
            os.path.expandvars(
                f"$WINDIR/System32spool/drivers/color/{icc_gen.profile_name}.icc"
            )
        )
    elif "linux" in system_name:
        profile_install_path = pathlib.Path(
            f"~/.local/share/icc/{icc_gen.profile_name}.icc"
        ).expanduser()
    elif "darwin" in system_name:
        profile_install_path = pathlib.Path(
            f"~/Library/ColorSync/Profiles/{icc_gen.profile_name}.icc"
        ).expanduser()

    assert profile_install_path is not None
    file_collector.append(profile_install_path)
    assert profile_install_path.exists()


def test_install_profile_2(file_collector, patch_run_external_process):
    """install_profile will raise a RuntimeError if ICC has not been generated yet."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    file_collector.append(icc_gen.profile_path)
    icc_gen.number_of_pages = 1
    icc_gen.copyright_info = "Erkan Ozgur Yilmaz(c)2021"
    file_collector.append(icc_gen.profile_path)
    with pytest.raises(RuntimeError) as cm:
        icc_gen.install_profile()
    assert str(cm.value) == "ICC file doesn't exist, please generate it first!"


def test_default_logger_is_created(file_collector):
    """default logger has been created."""
    assert isinstance(logger, logging.Logger)


def test_default_log_level_is_info(file_collector):
    """default log level is info."""
    assert logger.level == logging.INFO


def test_output_path_for_windows(set_to_windows):
    """output_path variable is correctly set for Windows."""
    icc_gen = ICCGenerator()
    assert icc_gen.output_path == pathlib.Path(
        os.path.expandvars("%WINDIR%/System32/spool/drivers/color/")
    )


def test_output_path_for_linux(set_to_linux):
    """output_path variable is correctly set for Linux."""
    icc_gen = ICCGenerator()
    assert icc_gen.output_path == pathlib.Path("~/.local/share/icc/").expanduser()


def test_output_path_for_macos(set_to_macos):
    """output_path variable is correctly set for macOS."""
    icc_gen = ICCGenerator()
    assert (
        icc_gen.output_path
        == pathlib.Path("~/Library/ColorSync/Profiles/").expanduser()
    )


def test_color_correct_image_printer_profile_path_is_skipped(
    file_collector, patch_run_external_process
):
    """color_correct_image raises ValueError if printer_profile_path arg is skipped."""
    printer_profile_path_handle, printer_profile_path = tempfile.mkstemp(suffix=".icc")
    input_image_path_handle, input_image_path = tempfile.mkstemp(suffix=".tif")
    output_image_path = tempfile.mktemp(suffix=".tif")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)
    image_profile = "AdobeRGB"
    intent = "r"
    with pytest.raises(TypeError) as cm:
        ICCGenerator.color_correct_image(
            input_image_path=input_image_path,
            output_image_path=output_image_path,
            image_profile=image_profile,
            intent=intent,
        )

    assert str(cm.value) == "Please specify a proper printer_profile_path!"


def test_color_correct_image_printer_profile_path_is_none(
    file_collector, patch_run_external_process
):
    """color_correct_image raises TypeError if printer_profile_path arg is None."""
    printer_profile_path_handle, printer_profile_path = tempfile.mkstemp(suffix=".icc")
    input_image_path_handle, input_image_path = tempfile.mkstemp(suffix=".tif")
    output_image_path = tempfile.mktemp(suffix=".tif")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)
    image_profile = "AdobeRGB"
    intent = "r"
    with pytest.raises(TypeError) as cm:
        ICCGenerator.color_correct_image(
            printer_profile_path=None,
            input_image_path=input_image_path,
            output_image_path=output_image_path,
            image_profile=image_profile,
            intent=intent,
        )

    assert str(cm.value) == "Please specify a proper printer_profile_path!"


def test_color_correct_image_printer_profile_path_does_not_exist(
    file_collector, patch_run_external_process
):
    """color_correct_image raises ValueError if printer_profile_path doesn't exist."""
    printer_profile_path = tempfile.mktemp(suffix=".icc")
    input_image_path_handle, input_image_path = tempfile.mkstemp(suffix=".tif")
    output_image_path = tempfile.mktemp(suffix=".tif")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)
    image_profile = "AdobeRGB"
    intent = "r"
    with pytest.raises(ValueError) as cm:
        ICCGenerator.color_correct_image(
            printer_profile_path=printer_profile_path,
            input_image_path=input_image_path,
            output_image_path=output_image_path,
            image_profile=image_profile,
            intent=intent,
        )

    assert str(cm.value) == (
        f"printer_profile_path doesn't exists: {printer_profile_path}"
    )


def test_color_correct_image_printer_profile_path_is_not_an_icc_or_icm_file(
    file_collector, patch_run_external_process
):
    """ValueError raised if printer_profile_path arg is not path to an ICC or ICM."""
    printer_profile_path_handle, printer_profile_path = tempfile.mkstemp(
        suffix=".not_an_icc_file"
    )
    input_image_path_handle, input_image_path = tempfile.mkstemp(suffix=".tif")
    output_image_path = tempfile.mktemp(suffix=".tif")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)
    image_profile = "AdobeRGB"
    intent = "r"
    with pytest.raises(ValueError) as cm:
        ICCGenerator.color_correct_image(
            printer_profile_path=printer_profile_path,
            input_image_path=input_image_path,
            output_image_path=output_image_path,
            image_profile=image_profile,
            intent=intent,
        )

    assert str(cm.value) == (
        f"printer_profile_path should be a valid ICC/ICM file: {printer_profile_path}"
    )


def test_color_correct_image_input_image_path_is_skipped(
    file_collector, patch_run_external_process
):
    """color_correct_image raises ValueError if input_image_path arg is skipped."""
    printer_profile_path_handle, printer_profile_path = tempfile.mkstemp(suffix=".icc")
    input_image_path_handle, input_image_path = tempfile.mkstemp(suffix=".tif")
    output_image_path = tempfile.mktemp(suffix=".tif")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)
    image_profile = "AdobeRGB"
    intent = "r"
    with pytest.raises(TypeError) as cm:
        ICCGenerator.color_correct_image(
            printer_profile_path=printer_profile_path,
            output_image_path=output_image_path,
            image_profile=image_profile,
            intent=intent,
        )
    assert str(cm.value) == "Please specify a proper input_image_path!"


def test_color_correct_image_input_image_is_none(
    file_collector, patch_run_external_process
):
    """color_correct_image raises TypeError if input_image arg is None."""
    printer_profile_path_handle, printer_profile_path = tempfile.mkstemp(suffix=".icc")
    input_image_path_handle, input_image_path = tempfile.mkstemp(suffix=".tif")
    output_image_path = tempfile.mktemp(suffix=".tif")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)
    image_profile = "AdobeRGB"
    intent = "r"
    with pytest.raises(TypeError) as cm:
        ICCGenerator.color_correct_image(
            printer_profile_path=printer_profile_path,
            input_image_path=None,
            output_image_path=output_image_path,
            image_profile=image_profile,
            intent=intent,
        )

    assert str(cm.value) == "Please specify a proper input_image_path!"


def test_color_correct_image_input_image_does_not_exist(
    file_collector, patch_run_external_process
):
    """color_correct_image raises ValueError if input_image arg value doesn't exist."""
    printer_profile_path_handle, printer_profile_path = tempfile.mkstemp(suffix=".icc")
    input_image_path = tempfile.mktemp(suffix=".tif")
    output_image_path = tempfile.mktemp(suffix=".tif")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)
    image_profile = "AdobeRGB"
    intent = "r"
    with pytest.raises(ValueError) as cm:
        ICCGenerator.color_correct_image(
            printer_profile_path=printer_profile_path,
            input_image_path=input_image_path,
            output_image_path=output_image_path,
            image_profile=image_profile,
            intent=intent,
        )

    assert str(cm.value) == f"input_image_path doesn't exists: {input_image_path}"


def test_color_correct_image_input_image_path_is_not_an_jpg_or_tif_file(
    file_collector, patch_run_external_process
):
    """TypeError raised if input_image_path is not a path of a JPG or TIF file."""
    printer_profile_path_handle, printer_profile_path = tempfile.mkstemp(suffix=".icc")
    input_image_path_handle, input_image_path = tempfile.mkstemp(suffix=".bmp")
    output_image_path = tempfile.mktemp(suffix=".tif")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)
    image_profile = "AdobeRGB"
    intent = "r"
    with pytest.raises(ValueError) as cm:
        ICCGenerator.color_correct_image(
            printer_profile_path=printer_profile_path,
            input_image_path=input_image_path,
            output_image_path=output_image_path,
            image_profile=image_profile,
            intent=intent,
        )

    assert str(cm.value) == (
        f"input_image_path should be a valid JPG/TIF file: {input_image_path}"
    )


def test_color_correct_image_output_image_path_is_skipped(
    file_collector, patch_run_external_process_class_method_version
):
    """proper output_image_path generated if output_image_path arg is skipped."""
    printer_profile_path_handle, printer_profile_path = tempfile.mkstemp(suffix=".icc")
    input_image_path_handle, input_image_path = tempfile.mkstemp(suffix=".tif")
    _output_image_path = tempfile.mktemp(suffix=".tif")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)
    image_profile = "AdobeRGB"
    intent = "r"

    ICCGenerator.color_correct_image(
        printer_profile_path=printer_profile_path,
        input_image_path=input_image_path,
        image_profile=image_profile,
        intent=intent,
    )

    input_image_name, input_image_ext = os.path.splitext(input_image_path)
    expected_path = f"{input_image_name}_corrected_1{input_image_ext}"
    assert any(
        expected_path in arg
        for arg in patch_run_external_process_class_method_version[0]
    )


def test_color_correct_image_output_image_path_is_none(
    file_collector, patch_run_external_process_class_method_version
):
    """proper output_image_path generated if output_image_path arg is None."""
    printer_profile_path_handle, printer_profile_path = tempfile.mkstemp(suffix=".icc")
    input_image_path_handle, input_image_path = tempfile.mkstemp(suffix=".tif")
    _output_image_path = tempfile.mktemp(suffix=".tif")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)
    image_profile = "AdobeRGB"
    intent = "r"

    ICCGenerator.color_correct_image(
        printer_profile_path=printer_profile_path,
        input_image_path=input_image_path,
        image_profile=image_profile,
        intent=intent,
    )

    input_image_name, input_image_ext = os.path.splitext(input_image_path)
    expected_path = f"{input_image_name}_corrected_1{input_image_ext}"
    assert any(
        expected_path in arg
        for arg in patch_run_external_process_class_method_version[0]
    )


def test_color_correct_image_output_image_path_is_not_a_tif_file(file_collector):
    """ValueError raised if output_image_path is not a tif file path."""
    printer_profile_path_handle, printer_profile_path = tempfile.mkstemp(suffix=".icc")
    input_image_path_handle, input_image_path = tempfile.mkstemp(suffix=".tif")
    output_image_path = tempfile.mktemp(suffix=".bmp")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)
    image_profile = "AdobeRGB"
    intent = "r"

    with pytest.raises(ValueError) as cm:
        ICCGenerator.color_correct_image(
            printer_profile_path=printer_profile_path,
            input_image_path=input_image_path,
            output_image_path=output_image_path,
            image_profile=image_profile,
            intent=intent,
        )

    assert str(cm.value) == (
        f"output_image_path should be a valid JPG/TIF file: {output_image_path}"
    )


def test_color_correct_image_intent_is_skipped(
    file_collector, patch_run_external_process_class_method_version
):
    """default value used if intent arg is skipped."""
    printer_profile_path_handle, printer_profile_path = tempfile.mkstemp(suffix=".icc")
    input_image_path_handle, input_image_path = tempfile.mkstemp(suffix=".tif")
    output_image_path = tempfile.mktemp(suffix=".tif")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)
    image_profile = "AdobeRGB"
    _intent = "r"

    ICCGenerator.color_correct_image(
        printer_profile_path=printer_profile_path,
        input_image_path=input_image_path,
        output_image_path=output_image_path,
        image_profile=image_profile,
    )

    assert "-i" in patch_run_external_process_class_method_version[0]
    assert "r" in patch_run_external_process_class_method_version[0]


def test_color_correct_image_intent_is_none(
    file_collector, patch_run_external_process_class_method_version
):
    """default value used if intent arg is None."""
    printer_profile_path_handle, printer_profile_path = tempfile.mkstemp(suffix=".icc")
    input_image_path_handle, input_image_path = tempfile.mkstemp(suffix=".tif")
    output_image_path = tempfile.mktemp(suffix=".tif")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)
    image_profile = "AdobeRGB"
    _intent = "r"

    ICCGenerator.color_correct_image(
        printer_profile_path=printer_profile_path,
        input_image_path=input_image_path,
        output_image_path=output_image_path,
        image_profile=image_profile,
        intent=None,
    )

    assert "-i" in patch_run_external_process_class_method_version[0]
    assert "r" in patch_run_external_process_class_method_version[0]


def test_color_correct_image_intent_is_not_a_str(file_collector):
    """TypeError raised if intent arg is not a str."""
    printer_profile_path_handle, printer_profile_path = tempfile.mkstemp(suffix=".icc")
    input_image_path_handle, input_image_path = tempfile.mkstemp(suffix=".tif")
    output_image_path = tempfile.mktemp(suffix=".tif")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)
    image_profile = "AdobeRGB"
    intent = 123

    with pytest.raises(TypeError) as cm:
        ICCGenerator.color_correct_image(
            printer_profile_path=printer_profile_path,
            input_image_path=input_image_path,
            output_image_path=output_image_path,
            image_profile=image_profile,
            intent=intent,
        )

    assert str(cm.value) == "intent should be a str, not int: '123'"


def test_color_correct_image_intent_is_not_correct_enum_value(file_collector):
    """TypeError raised if intent arg is not one of p, r, s, a."""
    printer_profile_path_handle, printer_profile_path = tempfile.mkstemp(suffix=".icc")
    input_image_path_handle, input_image_path = tempfile.mkstemp(suffix=".tif")
    output_image_path = tempfile.mktemp(suffix=".tif")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)
    image_profile = "AdobeRGB"
    intent = "not one of the desired values"

    with pytest.raises(ValueError) as cm:
        ICCGenerator.color_correct_image(
            printer_profile_path=printer_profile_path,
            input_image_path=input_image_path,
            output_image_path=output_image_path,
            image_profile=image_profile,
            intent=intent,
        )

    assert str(cm.value) == f"intent should be one of p, r, s, a, not {intent}"


def test_color_correct_image_intent_is_working_properly(
    file_collector, patch_run_external_process_class_method_version
):
    """default value used if intent arg is None."""
    printer_profile_path_handle, printer_profile_path = tempfile.mkstemp(suffix=".icc")
    input_image_path_handle, input_image_path = tempfile.mkstemp(suffix=".tif")
    output_image_path = tempfile.mktemp(suffix=".tif")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)
    image_profile = "AdobeRGB"
    intent = "r"

    ICCGenerator.color_correct_image(
        printer_profile_path=printer_profile_path,
        input_image_path=input_image_path,
        output_image_path=output_image_path,
        image_profile=image_profile,
        intent=intent,
    )

    assert "-i" in patch_run_external_process_class_method_version[0]
    assert "r" in patch_run_external_process_class_method_version[0]


def test_color_correct_image_profile_is_none(
    file_collector, patch_run_external_process_class_method_version
):
    """default value used if image_profile arg is None."""
    printer_profile_path_handle, printer_profile_path = tempfile.mkstemp(suffix=".icc")
    input_image_path_handle, input_image_path = tempfile.mkstemp(suffix=".tif")
    output_image_path = tempfile.mktemp(suffix=".tif")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)
    _image_profile = "AdobeRGB"
    intent = "r"

    ICCGenerator.color_correct_image(
        printer_profile_path=printer_profile_path,
        input_image_path=input_image_path,
        output_image_path=output_image_path,
        image_profile=None,
        intent=intent,
    )

    assert "-p" in patch_run_external_process_class_method_version[0]
    assert any(
        [
            "AdobeRGB" in arg
            for arg in patch_run_external_process_class_method_version[0]
        ]
    )


def test_color_correct_image_image_profile_is_not_a_str(file_collector):
    """TypeError raised if image_profile arg is not a str."""
    printer_profile_path_handle, printer_profile_path = tempfile.mkstemp(suffix=".icc")
    input_image_path_handle, input_image_path = tempfile.mkstemp(suffix=".tif")
    output_image_path = tempfile.mktemp(suffix=".tif")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)
    image_profile = 123123
    intent = "r"

    with pytest.raises(TypeError) as cm:
        ICCGenerator.color_correct_image(
            printer_profile_path=printer_profile_path,
            input_image_path=input_image_path,
            output_image_path=output_image_path,
            image_profile=image_profile,
            intent=intent,
        )

    assert str(cm.value) == (
        "image_profile should be one of sRGB or AdobeRGB, not int: '123123'"
    )


def test_color_correct_image_image_profile_is_not_correct_enum_value(file_collector):
    """TypeError raised if image_profile arg is not one of AdobeRGB or sRGB."""
    printer_profile_path_handle, printer_profile_path = tempfile.mkstemp(suffix=".icc")
    input_image_path_handle, input_image_path = tempfile.mkstemp(suffix=".tif")
    output_image_path = tempfile.mktemp(suffix=".tif")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)
    image_profile = "not one of the desired values"
    intent = "r"

    with pytest.raises(ValueError) as cm:
        ICCGenerator.color_correct_image(
            printer_profile_path=printer_profile_path,
            input_image_path=input_image_path,
            output_image_path=output_image_path,
            image_profile=image_profile,
            intent=intent,
        )

    assert str(cm.value) == (
        f"image_profile should be one of sRGB or AdobeRGB, not {image_profile}"
    )


def test_color_correct_image_image_profile_is_working_properly(
    file_collector, patch_run_external_process_class_method_version
):
    """TypeError raised if image_profile arg is working properly."""
    printer_profile_path_handle, printer_profile_path = tempfile.mkstemp(suffix=".icc")
    input_image_path_handle, input_image_path = tempfile.mkstemp(suffix=".tif")
    output_image_path = tempfile.mktemp(suffix=".tif")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)
    image_profile = "sRGB"
    intent = "r"

    ICCGenerator.color_correct_image(
        printer_profile_path=printer_profile_path,
        input_image_path=input_image_path,
        output_image_path=output_image_path,
        image_profile=image_profile,
        intent=intent,
    )

    assert any(
        "-p" in arg for arg in patch_run_external_process_class_method_version[0]
    )
    assert any(
        "sRGB" in arg for arg in patch_run_external_process_class_method_version[0]
    )


def test_color_correct_image_image_profile_is_a_path_to_srgb_or_adobergb_file(
    file_collector, patch_run_external_process_class_method_version
):
    """image_profile can be a path to sRGB or AdobeRGB file."""
    printer_profile_path_handle, printer_profile_path = tempfile.mkstemp(suffix=".icc")
    input_image_path_handle, input_image_path = tempfile.mkstemp(suffix=".tif")
    output_image_path = tempfile.mktemp(suffix=".tif")
    file_collector.append(printer_profile_path)
    file_collector.append(input_image_path)

    image_profile = (HERE / ".." / "sRGB.icc").resolve()
    intent = "r"

    ICCGenerator.color_correct_image(
        printer_profile_path=printer_profile_path,
        input_image_path=input_image_path,
        output_image_path=output_image_path,
        image_profile=image_profile,
        intent=intent,
    )

    assert any(
        "-p" in arg for arg in patch_run_external_process_class_method_version[0]
    )
    assert any(
        "sRGB" in arg for arg in patch_run_external_process_class_method_version[0]
    )
    assert any(
        str(image_profile.resolve()) in arg
        for arg in patch_run_external_process_class_method_version[0]
    )


def test_save_settings_path_is_skipped(file_collector):
    """profile_path used if path arg value is skipped."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    settings_file_path = icc_gen.profile_path / f"{icc_gen.profile_name}.json"
    file_collector.append(settings_file_path)
    assert not settings_file_path.exists()
    icc_gen.save_settings()
    assert settings_file_path.exists()


def test_save_settings_path_is_none(file_collector):
    """profile_path used if path arg value is None."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    settings_file_path = icc_gen.profile_path / f"{icc_gen.profile_name}.json"
    file_collector.append(settings_file_path)
    assert not os.path.exists(os.path.expanduser(settings_file_path))
    icc_gen.save_settings(path=None)
    assert os.path.exists(os.path.expanduser(settings_file_path))


def test_save_settings_path_is_not_a_str():
    """TypeError raised if path arg value is not a str."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.save_settings(1)
    assert str(cm.value) == "Please specify a valid path"


def test_save_settings_is_working_properly(file_collector, patch_run_external_process):
    """save_settings function is working properly."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    path = tempfile.mktemp()
    file_collector.append(path)
    icc_gen.save_settings(path)

    assert os.path.exists(path)

    # check file content
    with open(path, "r") as f:
        data = json.load(f)

    assert data is not None
    assert icc_gen.ink_brand == data["ink_brand"]
    assert icc_gen.paper_brand == data["paper_brand"]
    assert icc_gen.paper_finish == data["paper_finish"]
    assert icc_gen.paper_model == data["paper_model"]
    assert icc_gen.paper_size.name == data["paper_size"]
    assert icc_gen.printer_brand == data["printer_brand"]
    assert icc_gen.printer_model == data["printer_model"]
    assert icc_gen.printer_paper_setting == data["printer_paper_setting"]
    assert icc_gen.profile_date == data["profile_date"]
    assert icc_gen.profile_time == data["profile_time"]


def test_load_settings_path_is_skipped():
    """RuntimeError raised if path arg is skipped."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.load_settings()

    error_message = {
        8: "load_settings() missing 1 required positional argument: 'path'",
        9: "load_settings() missing 1 required positional argument: 'path'",
        10: "ICCGenerator.load_settings() missing 1 required positional argument: 'path'",
        11: "ICCGenerator.load_settings() missing 1 required positional argument: 'path'",
        12: "ICCGenerator.load_settings() missing 1 required positional argument: 'path'",
        13: "ICCGenerator.load_settings() missing 1 required positional argument: 'path'",
    }.get(sys.version_info.minor)

    assert str(cm.value) == error_message


def test_load_settings_path_is_none():
    """RuntimeError raised if path arg value is None."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.load_settings(None)

    assert str(cm.value) == "Please specify a valid path"


def test_load_settings_path_is_not_a_str():
    """TypeError raised if path arg value is not a str."""
    icc_gen = ICCGenerator()
    with pytest.raises(TypeError) as cm:
        icc_gen.load_settings(123)

    assert str(cm.value) == "Please specify a valid path"


def test_load_settings_path_does_not_exist():
    """RuntimeError raised if path doesn't exist."""
    icc_gen = ICCGenerator()
    with pytest.raises(RuntimeError) as cm:
        icc_gen.load_settings("Some random error")

    assert str(cm.value) == "File does not exist!: Some random error"


def test_load_settings_is_working_properly(file_collector):
    """load_settings function is working properly."""
    icc_gen = ICCGenerator()

    # set some values
    icc_gen.ink_brand = "Epson673"
    icc_gen.paper_brand = "Agfa"
    icc_gen.paper_finish = "Glossy"
    icc_gen.paper_model = "HGPIP"
    icc_gen.paper_size = PaperSizeLibrary.A4
    icc_gen.printer_brand = "RandomPrinterBrand"
    icc_gen.printer_model = "L800"
    icc_gen.printer_paper_setting = "Premium_Glossy"

    path = tempfile.mktemp()
    file_collector.append(path)
    icc_gen.save_settings(path)

    assert os.path.exists(path)

    # check file content
    icc_gen2 = ICCGenerator()
    icc_gen2.load_settings(path)

    assert icc_gen.ink_brand == icc_gen2.ink_brand
    assert icc_gen.paper_brand == icc_gen2.paper_brand
    assert icc_gen.paper_finish == icc_gen2.paper_finish
    assert icc_gen.paper_model == icc_gen2.paper_model
    assert icc_gen.paper_size == icc_gen2.paper_size
    assert icc_gen.printer_brand == icc_gen2.printer_brand
    assert icc_gen.printer_model == icc_gen2.printer_model
    assert icc_gen.printer_paper_setting == icc_gen2.printer_paper_setting
    assert icc_gen.profile_date == icc_gen2.profile_date
    assert icc_gen.profile_time == icc_gen2.profile_time


def test_run_external_process_will_use_os_system_if_shell_is_true(
    file_collector, monkeypatch
):
    """run_external_process will use os.system if shell=True."""
    called = []

    class MockedOS(object):
        @classmethod
        def system(cls, command):
            called.append(command)
            print(f"This is called: {command}")

    monkeypatch.setattr("icc_generator.api.os", MockedOS)
    test_value = ["echo", "Hello"]
    expected_result = "echo Hello"

    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    for _ in icc_gen.run_external_process(test_value, shell=True):
        pass
    assert expected_result in called


def test_run_external_process_will_raise_a_runtime_error_if_command_fails(
    file_collector, monkeypatch
):
    """run_external_process will Raise a RuntimeError if command fails."""
    cmd = ["false"]
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    with pytest.raises(RuntimeError) as cm:
        for _ in icc_gen.run_external_process(cmd):
            pass


def test_generate_target_prints_commands_if_output_commands_is_true(
    file_collector,
    patch_run_external_process,
    capsys,
):
    """generate_target will print the command if output_commands is True."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand", output_commands=True)
    icc_gen.generate_target()
    assert "targen -v -d 2 -G -g" in capsys.readouterr().out


def test_generate_tiff_prints_commands_if_output_commands_is_true(
    file_collector,
    patch_run_external_process,
    capsys,
):
    """generate_target will print the command if output_commands is True."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand", output_commands=True)
    icc_gen.generate_tif()
    assert (
        "printtarg -v -ii1 -a 0.875 -R1 -T300 -M2 -L -P -p" in capsys.readouterr().out
    )


@pytest.mark.parametrize("os_name", ["linux", "darwin", "win32"])
def test_print_charts_prints_commands_if_output_commands_is_true(
    file_collector, patch_run_external_process, monkeypatch, capsys, os_name
):
    """generate_target will print the command if output_commands is True."""

    class MockedPlatform(object):
        @classmethod
        def system(cls):
            return os_name

    monkeypatch.setattr("icc_generator.api.platform", MockedPlatform)

    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand", output_commands=True)
    icc_gen.print_charts()
    command = {
        "win32": "C:/Program Files/Dry Creek Photo/Print Utility/Print Utility",
        "linux": "/usr/bin/gimp",
        "darwin": "/Applications/Print-Tool.app/Contents/MacOS/Print-Tool",
    }.get(os_name, "gimp")
    assert command in capsys.readouterr().out


def test_read_charts_prints_commands_if_output_commands_is_true(
    patch_run_external_process,
    capsys,
):
    """read_charts will print the command if output_commands is True."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand", output_commands=True)
    icc_gen.read_charts()
    assert "chartread -v -H -T 0.4" in capsys.readouterr().out


def test_generate_profile_prints_commands_if_output_commands_is_true(
    patch_run_external_process,
    capsys,
):
    """generate_profile will print the command if output_commands is True."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand", output_commands=True)
    icc_gen.generate_profile()
    assert "colprof -v -qh -r0.5 -S" in capsys.readouterr().out


def test_check_profile_prints_commands_if_output_commands_is_true(
    patch_run_external_process,
    capsys,
):
    """check_profile will print the command if output_commands is True."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand", output_commands=True)
    icc_gen.check_profile()
    assert "profcheck -k -v2" in capsys.readouterr().out


@pytest.mark.parametrize("os_name", ["linux", "darwin", "win32"])
def test_check_profile_uses_icm_under_windows_and_icc_under_linux_and_macos(
    patch_run_external_process, capsys, monkeypatch, os_name
):
    """check_profile will print the command if output_commands is True."""

    class MockedPlatform(object):
        @classmethod
        def system(cls):
            return os_name

    monkeypatch.setattr("icc_generator.api.platform", MockedPlatform)
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand", output_commands=True)
    icc_gen.check_profile()
    extension = {
        "linux": ".icc",
        "darwin": ".icc",
        "win32": ".icm",
    }.get(os_name, ".icc")
    assert f"{icc_gen.profile_absolute_full_path}{extension}" in capsys.readouterr().out


def test_install_profile_prints_out_exception_if_command_errors_out(
    file_collector,
    patch_run_external_process,
    monkeypatch,
    capsys,
):
    """install_profile will print error if command errors out."""
    error_message = "This is a fake error message."

    class MockedShUtil(object):
        @classmethod
        def copy2(cls, src, dest):
            raise OSError(error_message)

    monkeypatch.setattr("shutil.copy2", MockedShUtil.copy2)

    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand", output_commands=True)
    file_collector.append(icc_gen.profile_path)
    icc_gen.number_of_pages = 1
    icc_gen.copyright_info = "Erkan Ozgur Yilmaz(c)2025"
    icc_gen.paper_size = PaperSizeLibrary.A4
    file_collector.append(icc_gen.profile_absolute_path)

    # create a dummy icc file
    dummy_icc_profile_full_path = icc_gen.profile_path / f"{icc_gen.profile_name}.icc"
    os.makedirs(icc_gen.profile_path, exist_ok=True)
    assert icc_gen.profile_path
    with open(dummy_icc_profile_full_path, "w+") as f:
        f.write("dummy icc file!!!")
    assert dummy_icc_profile_full_path.exists()
    file_collector.append(dummy_icc_profile_full_path)

    icc_gen.install_profile()

    assert error_message in capsys.readouterr().err


def test_summary_prints_out_summary():
    """summary() prints out a summary of the ICCGenerator object."""
    icc_gen = ICCGenerator()
    icc_gen.printer_brand = "RandomPrinterBrand"
    icc_gen.printer_model = "ET-8550"
    icc_gen.printer_paper_setting = "VFA"
    icc_gen.ink_brand = "Epson"
    icc_gen.paper_brand = "Epson"
    icc_gen.paper_model = "VelvetFineArt"
    icc_gen.paper_finish = "Satin"
    icc_gen.paper_size = PaperSizeLibrary.A4
    icc_gen.number_of_pages = 2

    result = icc_gen.summary()
    assert isinstance(result, str)

    # because we can't predict the exact output format (spacing etc.)
    # we need to check for partial results
    expected_data = [
        "Parameter",
        "Value",
        "Printer:",
        "Brand",
        "RandomPrinterBrand",
        "Model",
        "ET-8550",
        "Paper Setting",
        "VFA",
        "Paper:",
        "Finish",
        "Satin",
        "Size",
        "A4",
        "Profile Settings:",
        "Number of Pages",
        "Patch Count",
        "1456",
        "Gray Patch Count",
        f"{icc_gen.gray_patch_count}",
        "Copyright Info",
        "Use High Density Mode",
        "True",
        "Precondition Profile Path",
        "Profile Date & Time",
        f"{icc_gen.profile_date}",
        f"{icc_gen.profile_time}",
        "Profile Name",
        f"{icc_gen.profile_name}",
        "Profile Path",
        f"{icc_gen.profile_path}",
        "Profile Output Path",
        f"{icc_gen.output_path}",
    ]
    assert all(d in result for d in expected_data)


def test_printer_paper_setting_arg_is_skipped():
    """printer_paper_setting arg can be skipped."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand")
    assert icc_gen.printer_paper_setting is "Default"  # default value


def test_printer_paper_setting_arg_is_none():
    """printer_paper_setting arg can be None."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand", printer_paper_setting=None)
    assert icc_gen.printer_paper_setting is "Default"


def test_printer_paper_setting_attr_can_be_set_to_none():
    """printer_paper_setting attr can be set to None."""
    icc_gen = ICCGenerator(
        printer_brand="RandomPrinterBrand",
        printer_paper_setting="VFA"
    )
    assert icc_gen.printer_paper_setting != ""
    icc_gen.printer_paper_setting = None
    assert icc_gen.printer_paper_setting == "Default"


def test_printer_paper_setting_arg_is_not_a_str():
    """printer_paper_setting arg is not a str raises TypeError."""
    with pytest.raises(TypeError) as cm:
        ICCGenerator(printer_brand="RandomPrinterBrand", printer_paper_setting=123)
    assert str(cm.value) == (
        "ICCGenerator.printer_paper_setting should be a str, not int: '123'"
    )


def test_printer_paper_setting_attr_is_not_a_str():
    """printer_paper_setting attr is not a str raises TypeError."""
    icc_gen = ICCGenerator(printer_brand="RandomPrinterBrand", printer_paper_setting="VFA")
    with pytest.raises(TypeError) as cm:
        icc_gen.printer_paper_setting = 123
    assert str(cm.value) == (
        "ICCGenerator.printer_paper_setting should be a str, not int: '123'"
    )


def test_printer_paper_setting_is_used_in_profile_name():
    """printer_paper_setting_is_used_in_profile_name."""
    icc_gen = ICCGenerator(
        printer_brand="RandomPrinterBrand", printer_paper_setting="RandomPaperSetting"
    )
    assert "RandomPaperSetting" in icc_gen.profile_name
    