# Copyright (c) 2011-2021, Manfred Moitzi
# License: MIT License
import pytest
import ezdxf
from ezdxf.lldxf.const import DXF12, DXF2000, DXF2018, DXF2013, DXF2007, DXF2010
from ezdxf.lldxf.tags import Tags
from ezdxf.sections.header import HeaderSection
from ezdxf.lldxf.validator import header_validator
from ezdxf.sections.headervars import version_specific_group_code

INVALID_HEADER_STRUCTURE = """   9
$ACADVER
  1
AC1009
  100
$INSBASE
 10
0.0
 20
0.0
 30
0.0
"""

INVALID_HEADER_VAR_NAME = """   9
$ACADVER
  1
AC1009
  9
INSBASE
 10
0.0
 20
0.0
 30
0.0
"""

MINIMALISTIC_DXF12 = """  0
SECTION
  2
ENTITIES
  0
ENDSEC
  0
EOF
"""


def test_new_drawing():
    dwg = ezdxf.new('AC1009')
    assert 'AC1009' == dwg.dxfversion


def test_valid_header():
    tags = Tags.from_text(TESTHEADER)[2:-1]
    result = list(header_validator(tags))
    assert 8 == len(result)


def test_invalid_header_structure():
    tags = Tags.from_text(INVALID_HEADER_STRUCTURE)
    with pytest.raises(ezdxf.DXFStructureError):
        list(header_validator(tags))


def test_invalid_header_var_name():
    tags = Tags.from_text(INVALID_HEADER_VAR_NAME)
    with pytest.raises(ezdxf.DXFValueError):
        list(header_validator(tags))


@pytest.fixture
def header():
    tags = Tags.from_text(TESTHEADER)
    tags.pop()  # remove 'ENDSEC'
    header = HeaderSection.load(tags)
    return header


def test_get_acadver(header):
    result = header['$ACADVER']
    assert 'AC1009' == result


def test_get_insbase(header):
    result = header['$INSBASE']
    assert (0., 0., 0.) == result


def test_getitem_keyerror(header):
    with pytest.raises(ezdxf.DXFKeyError):
        var = header['$TEST']


def test_get(header):
    result = header.get('$TEST', 'TEST')
    assert 'TEST' == result


def test_set_existing_var(header):
    header['$ACADVER'] = 'AC666'
    assert 'AC666' == header['$ACADVER']


def test_set_existing_point(header):
    header['$INSBASE'] = (1, 2, 3)
    assert (1, 2, 3) == header['$INSBASE']


def test_set_unknown_var(header):
    with pytest.raises(ezdxf.DXFKeyError):
        header['$TEST'] = 'test'


def test_create_var(header):
    header['$LIMMAX'] = (10, 20)
    assert (10, 20) == header['$LIMMAX']


def test_create_var_wrong_args_2d(header):
    header['$LIMMAX'] = (10, 20, 30)
    assert (10, 20) == header['$LIMMAX']


def test_create_var_wrong_args_3d(header):
    with pytest.raises(ezdxf.DXFValueError):
        header['$PUCSORG'] = (10, 20)


def test_contains(header):
    assert '$ACADVER' in header


def test_not_contains(header):
    assert '$MOZMAN' not in header


def test_remove_headervar(header):
    del header['$ACADVER']
    assert '$ACADVER' not in header


def test_str_point(header):
    insbase_str = str(header.hdrvars['$INSBASE'])
    assert INSBASE == insbase_str


def test_new_dxf12():
    header = HeaderSection.new(ezdxf.const.DXF12)
    assert header['$ACADVER'] == DXF12


@pytest.fixture
def header_custom():
    tags = Tags.from_text(TESTCUSTOMPROPERTIES)
    tags.pop()  # remove 'ENDSEC'
    header = HeaderSection.load(tags)
    return header


def test_custom_properties_exists(header_custom):
    assert header_custom.custom_vars.has_tag("Custom Property 1")


def test_order_of_occurrence(header_custom):
    properties = header_custom.custom_vars.properties
    assert ("Custom Property 1", "Custom Value 1") == properties[0]
    assert ("Custom Property 2", "Custom Value 2") == properties[1]


def test_get_custom_property(header_custom):
    assert "Custom Value 1" == header_custom.custom_vars.get(
        "Custom Property 1")


def test_get_custom_property_2(header_custom):
    assert "Custom Value 2" == header_custom.custom_vars.get(
        "Custom Property 2")


def test_add_custom_property(header_custom):
    header_custom.custom_vars.append("Custom Property 3", "Custom Value 3")
    assert 3 == len(header_custom.custom_vars)
    assert "Custom Value 3" == header_custom.custom_vars.get(
        "Custom Property 3")


def test_remove_custom_property(header_custom):
    header_custom.custom_vars.remove("Custom Property 1")
    assert 1 == len(header_custom.custom_vars)


def test_remove_not_existing_property(header_custom):
    with pytest.raises(ValueError):
        header_custom.custom_vars.remove("Does not Exist")


def test_replace_custom_property(header_custom):
    header_custom.custom_vars.replace("Custom Property 1", "new value")
    assert "new value" == header_custom.custom_vars.get("Custom Property 1")


def test_replace_not_existing_property(header_custom):
    with pytest.raises(ValueError):
        header_custom.custom_vars.replace("Does not Exist", "new value")


@pytest.mark.parametrize('name,version,expected', [
    ('$ACADMAINTVER', DXF2018, 90),
    ('$ACADMAINTVER', DXF2013, 70),
    ('$XCLIPFRAME', DXF2007, 290),
    ('$XCLIPFRAME', DXF2010, 280),
])
def test_version_specific_header_vars(name, version, expected):
    assert version_specific_group_code(name, version) == expected


def test_version_specific_group_code_raises_key_error_for_unknown_names():
    with pytest.raises(KeyError):
        version_specific_group_code('$MOZMAN', DXF2000)


INSBASE = """ 10
0.0
 20
0.0
 30
0.0
"""

TESTHEADER = """  0
SECTION
  2
HEADER
  9
$ACADVER
  1
AC1009
  9
$INSBASE
 10
0.0
 20
0.0
 30
0.0
  9
$EXTMIN
 10
1.0000000000000000E+020
 20
1.0000000000000000E+020
 30
1.0000000000000000E+020
  9
$EXTMAX
 10
-1.0000000000000000E+020
 20
-1.0000000000000000E+020
 30
-1.0000000000000000E+020
  0
ENDSEC
"""

TESTCUSTOMPROPERTIES = """  0
SECTION
  2
HEADER
  9
$ACADVER
  1
AC1009
  9
$CUSTOMPROPERTYTAG
  1
Custom Property 1
  9
$CUSTOMPROPERTY
  1
Custom Value 1
  9
$CUSTOMPROPERTYTAG
  1
Custom Property 2
  9
$CUSTOMPROPERTY
  1
Custom Value 2
  0
ENDSEC
"""
