#  Copyright (c) 2020, Manfred Moitzi
#  License: MIT License

import pytest
from ezdxf.tools import fonts

# Load default font definitions, included in ezdxf:
fonts.load()


def test_find_font_face_without_definition():
    assert fonts.find_font_face("mozman.ttf") is None
    assert fonts.find_font_face(None) is None, "should accept None as argument"


def test_find_font_face():
    assert fonts.find_font_face("Arial.ttf") == (
        "arial.ttf",
        "Arial",
        "normal",
        "normal",
        400,
    )


def test_get_font_without_definition():
    # Creates a pseudo entry:
    assert fonts.get_font_face("mozman.ttf") == (
        "mozman.ttf",
        "mozman",
        "normal",
        "normal",
        "normal",
    )
    with pytest.raises(TypeError):
        fonts.get_font_face(None)  # should not accept None as argument"


def test_get_font_face_with_definition():
    assert fonts.get_font_face("Arial.ttf") is fonts.find_font_face("arial.ttf")


def test_map_shx_to_ttf():
    assert fonts.map_shx_to_ttf("TXT") == "txt_____.ttf"
    assert fonts.map_shx_to_ttf("TXT.SHX") == "txt_____.ttf"
    assert fonts.map_shx_to_ttf("txt.shx") == "txt_____.ttf"


def test_map_ttf_to_shx():
    assert fonts.map_ttf_to_shx("txt_____.ttf") == "TXT.SHX"
    assert fonts.map_ttf_to_shx("TXT_____.TTF") == "TXT.SHX"
    assert fonts.map_ttf_to_shx("xxx.ttf") is None


def test_get_font_face_for_shx_fonts():
    assert fonts.get_font_face("TXT") == (
        "txt_____.ttf",
        "Txt",
        "normal",
        "normal",
        400,
    )


def test_get_font_measurement():
    assert fonts.get_font_measurements("Arial.ttf") == (
        0.0,
        0.71578125,
        0.51859375,
        0.19875,
    )


def test_get_font_measurement_for_shx_fonts():
    assert fonts.get_font_measurements("TXT.shx") == (
        -0.0053125,
        0.7293750000000001,
        0.49171875,
        0.23390625,
    )


def test_get_undefined_font_measurement():
    assert fonts.get_font_measurements("mozman.ttf") == (
        0.0,
        1,
        fonts.X_HEIGHT_FACTOR,
        fonts.DESCENDER_FACTOR,
    )


def test_get_cache_file_path():
    path = fonts.get_cache_file_path(None, name="mozman.cfg")
    assert path.name == "mozman.cfg"
    path = fonts.get_cache_file_path("~/ezdxf", "mozman.json")
    assert path.name == "mozman.json"
    assert path.parent.name == "ezdxf"


def test_save_and_load_caches(tmp_path):
    fonts.save(tmp_path)
    assert (tmp_path / "font_face_cache.json").exists()
    assert (tmp_path / "font_measurement_cache.json").exists()
    fonts.font_face_cache = {}
    fonts.font_measurement_cache = {}
    fonts.load(tmp_path)
    assert len(fonts.font_face_cache) > 0
    assert len(fonts.font_measurement_cache) > 0


def test_same_font_faces_have_equal_hash_values():
    f1 = fonts.FontFace("arial.ttf", "Arial")
    f2 = fonts.FontFace("arial.ttf", "Arial")
    assert hash(f1) == hash(f2)


def test_font_face_is_italic():
    assert fonts.FontFace(style="italic").is_italic is True
    assert fonts.FontFace(style="oblique-italic").is_italic is True
    assert fonts.FontFace(style="").is_italic is False
    assert fonts.FontFace().is_italic is False


def test_font_face_is_oblique():
    assert fonts.FontFace(style="oblique").is_oblique is True
    assert fonts.FontFace(style="oblique-italic").is_oblique is True
    assert fonts.FontFace(style="").is_oblique is False
    assert fonts.FontFace().is_oblique is False


def test_font_face_is_bold():
    assert fonts.FontFace().is_bold is False
    assert fonts.FontFace(weight=300).is_bold is False
    assert fonts.FontFace(weight="bold").is_bold is True
    assert fonts.FontFace(weight="black").is_bold is True
    assert fonts.FontFace(weight=500).is_bold is True


class TestFontMeasurements:
    @pytest.fixture
    def default(self):
        return fonts.FontMeasurements(
            baseline=1.3, cap_height=1.0, x_height=0.5, descender_height=0.25
        )

    def test_total_height(self, default):
        assert default.total_height == 1.25

    def test_scale(self, default):
        fm = default.scale(2)
        assert fm.baseline == 2.6, "expected scaled baseline"
        assert fm.total_height == 2.5, "expected scaled total height"

    def test_shift(self, default):
        fm = default.shift(1.0)
        assert fm.baseline == 2.3
        assert fm.total_height == 1.25

    def test_scale_from_baseline(self, default):
        fm = default.scale_from_baseline(desired_cap_height=2.0)
        assert fm.baseline == 1.3, "expected unchanged baseline value"
        assert fm.cap_height == 2.0
        assert fm.x_height == 1.0
        assert fm.descender_height == 0.50
        assert fm.total_height == 2.5

    def test_cap_top(self, default):
        assert default.cap_top == 2.3

    def test_x_top(self, default):
        assert default.x_top == 1.8

    def test_bottom(self, default):
        assert default.bottom == 1.05

    def test_monospace_font(self):
        font = fonts.MonospaceFont(2.5, 0.75)
        assert font.text_width("1234") == 7.5


def test_find_font_file_by_family():
    assert fonts.find_font_face_by_family("simsun").ttf == "simsun.ttc"
    assert fonts.find_font_face_by_family("mozman") is None


if __name__ == "__main__":
    pytest.main([__file__])
