from openbakery.section import Section
from openbakery.fonts_profile import profile_factory


def check_filter(item_type, item_id, item):
    # Filter out external tool checks for testing purposes.
    if item_type == "check" and item_id in ("com.google.fonts/check/ots",):
        return False

    return True


def test_external_profile():
    """Test the creation of external profiles."""
    profile = profile_factory(default_section=Section("Dalton Maag OpenType"))
    profile.auto_register(
        globals(),
        profile_imports=["openbakery.profiles.opentype"],
        filter_func=check_filter,
    )

    # Probe some tests
    expected_tests = [
        "com.google.fonts/check/family/panose_proportion",
        "com.google.fonts/check/varfont/regular_opsz_coord",
    ]
    profile.test_expected_checks(expected_tests)

    assert len(profile.sections) > 1


def test_profile_imports():
    """
    When a names array in profile_imports contained sub module names, the import
    would fail.

    https://github.com/googlefonts/fontbakery/issues/1886
    """

    def _test(profile_imports, expected_tests, expected_conditions=tuple()):
        profile = profile_factory(default_section=Section("Testing"))
        profile.auto_register({}, profile_imports=profile_imports)
        profile.test_expected_checks(expected_tests)
        if expected_conditions:
            registered_conditions = profile.conditions.keys()
            for name in expected_conditions:
                assert (
                    name in registered_conditions
                ), f'"{name}" is expected to be registered as a condition.'

    # this is in docs/writing profiles
    profile_imports = [["openbakery.profiles", ["cmap", "head"]]]
    # Probe some tests
    expected_tests = ["com.google.fonts/check/unitsperem"]  # in head
    _test(profile_imports, expected_tests)

    # the example from issue #1886
    profile_imports = (
        (
            "openbakery.profiles",
            (
                "cmap",
                "head",
                "os2",
                "post",
                "name",
                "hhea",
                "dsig",
                "gpos",
                "kern",
                "glyf",
                "fvar",
                "shared_conditions",
            ),
        ),
    )
    # Probe some tests
    expected_tests = ["com.google.fonts/check/unitsperem"]  # in head
    _test(profile_imports, expected_tests)

    # make sure the suggested workaround still works:
    # https://github.com/googlefonts/fontbakery/issues/1886#issuecomment-392535435
    profile_imports = (
        "openbakery.profiles.cmap",
        "openbakery.profiles.head",
        "openbakery.profiles.os2",
        "openbakery.profiles.post",
        "openbakery.profiles.name",
        "openbakery.profiles.hhea",
        "openbakery.profiles.dsig",
        "openbakery.profiles.gpos",
        "openbakery.profiles.kern",
        "openbakery.profiles.glyf",
        "openbakery.profiles.fvar",
        "openbakery.profiles.shared_conditions",
    )
    # Probe some tests
    expected_tests = ["com.google.fonts/check/unitsperem"]  # in head
    _test(profile_imports, expected_tests)

    # cherry pick attributes from a module (instead of getting submodules)
    # also from this is in docs/writing profiles
    # Import just certain attributes from modules.
    # Also, using absolute import module names:
    profile_imports = [
        # like we do in openbakery.profiles.fvar
        (
            "openbakery.profiles.shared_conditions",
            (
                "is_variable_font",
                "regular_wght_coord",
                "regular_wdth_coord",
                "regular_slnt_coord",
                "regular_ital_coord",
                "regular_opsz_coord",
                "bold_wght_coord",
            ),
        ),
        # just as an example: import a check and a dependency/condition of
        # that check from the googlefonts specific profile:
        (
            "openbakery.profiles.googlefonts_conditions",
            (
                # This condition is a dependency of the check below:
                "familyname",
            ),
        ),
        (
            "openbakery.profiles.googlefonts",
            (
                # "License URL matches License text on name table?"
                "com_google_fonts_check_name_license_url",
            ),
        ),
    ]
    # Probe some tests
    expected_tests = ["com.google.fonts/check/name/license_url"]  # in googlefonts
    expected_conditions = (
        "is_variable_font",
        "regular_wght_coord",
        "regular_wdth_coord",
        "regular_slnt_coord",
        "regular_ital_coord",
        "regular_opsz_coord",
        "bold_wght_coord",
        "familyname",
    )
    _test(profile_imports, expected_tests, expected_conditions)


def test_opentype_checks_load():
    profile_imports = ("openbakery.profiles.opentype",)
    profile = profile_factory(default_section=Section("OpenType Testing"))
    profile.auto_register({}, profile_imports=profile_imports)
    profile.test_dependencies()


def test_googlefonts_checks_load():
    profile_imports = ("openbakery.profiles.googlefonts",)
    profile = profile_factory(default_section=Section("Google Fonts Testing"))
    profile.auto_register({}, profile_imports=profile_imports)
    profile.test_dependencies()


def test_in_and_exclude_checks():
    profile_imports = ("openbakery.profiles.opentype",)
    profile = profile_factory(default_section=Section("OpenType Testing"))
    profile.auto_register({}, profile_imports=profile_imports)
    profile.test_dependencies()
    explicit_checks = ["06", "07"]  # "06" or "07" in check ID
    exclude_checks = ["065", "079"]  # "065" or "079" in check ID
    iterargs = {"font": 1}
    check_names = {
        c[1].id
        for c in profile.execution_order(
            iterargs, explicit_checks=explicit_checks, exclude_checks=exclude_checks
        )
    }
    check_names_expected = set()
    for section in profile.sections:
        for check in section.checks:
            if any(i in check.id for i in explicit_checks) and not any(
                x in check.id for x in exclude_checks
            ):
                check_names_expected.add(check.id)
    assert check_names == check_names_expected


def test_in_and_exclude_checks_default():
    profile_imports = ("openbakery.profiles.opentype",)
    profile = profile_factory(default_section=Section("OpenType Testing"))
    profile.auto_register({}, profile_imports=profile_imports)
    profile.test_dependencies()
    explicit_checks = None  # "All checks aboard"
    exclude_checks = None  # "No checks left behind"
    iterargs = {"font": 1}
    check_names = {
        c[1].id
        for c in profile.execution_order(
            iterargs, explicit_checks=explicit_checks, exclude_checks=exclude_checks
        )
    }
    check_names_expected = set()
    for section in profile.sections:
        for check in section.checks:
            check_names_expected.add(check.id)
    assert check_names == check_names_expected
