from fontTools.misc.loggingTools import CapturingLogHandler
from fontTools.misc.testTools import parseXML, getXML
from fontTools.misc.textTools import deHexStr
from fontTools.ttLib import TTFont, newTable
from fontTools.misc.fixedTools import log
import os
import unittest


CURR_DIR = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
DATA_DIR = os.path.join(CURR_DIR, 'data')

VHEA_DATA_VERSION_11 = deHexStr(
    '0001 1000 '  # 1.1   version
    '01F4 '       # 500   ascent
    'FE0C '       # -500  descent
    '0000 '       # 0     lineGap
    '0BB8 '       # 3000  advanceHeightMax
    'FC16 '       # -1002 minTopSideBearing
    'FD5B '       # -677  minBottomSideBearing
    '0B70 '       # 2928  yMaxExtent
    '0000 '       # 0     caretSlopeRise
    '0001 '       # 1     caretSlopeRun
    '0000 '       # 0     caretOffset
    '0000 '       # 0     reserved1
    '0000 '       # 0     reserved2
    '0000 '       # 0     reserved3
    '0000 '       # 0     reserved4
    '0000 '       # 0     metricDataFormat
    '000C '       # 12    numberOfVMetrics
)

VHEA_DATA_VERSION_10 = deHexStr('00010000') + VHEA_DATA_VERSION_11[4:]

VHEA_VERSION_11_AS_DICT = {
    'tableTag': 'vhea',
    'tableVersion': 0x00011000,
    'ascent': 500,
    'descent': -500,
    'lineGap': 0,
    'advanceHeightMax': 3000,
    'minTopSideBearing': -1002,
    'minBottomSideBearing': -677,
    'yMaxExtent': 2928,
    'caretSlopeRise': 0,
    'caretSlopeRun': 1,
    'caretOffset': 0,
    'reserved1': 0,
    'reserved2': 0,
    'reserved3': 0,
    'reserved4': 0,
    'metricDataFormat': 0,
    'numberOfVMetrics': 12,
}

VHEA_VERSION_10_AS_DICT = dict(VHEA_VERSION_11_AS_DICT)
VHEA_VERSION_10_AS_DICT['tableVersion'] = 0x00010000

VHEA_XML_VERSION_11 = [
    '<tableVersion value="0x00011000"/>',
    '<ascent value="500"/>',
    '<descent value="-500"/>',
    '<lineGap value="0"/>',
    '<advanceHeightMax value="3000"/>',
    '<minTopSideBearing value="-1002"/>',
    '<minBottomSideBearing value="-677"/>',
    '<yMaxExtent value="2928"/>',
    '<caretSlopeRise value="0"/>',
    '<caretSlopeRun value="1"/>',
    '<caretOffset value="0"/>',
    '<reserved1 value="0"/>',
    '<reserved2 value="0"/>',
    '<reserved3 value="0"/>',
    '<reserved4 value="0"/>',
    '<metricDataFormat value="0"/>',
    '<numberOfVMetrics value="12"/>',
]

VHEA_XML_VERSION_11_AS_FLOAT = [
    '<tableVersion value="1.0625"/>',
] + VHEA_XML_VERSION_11[1:]

VHEA_XML_VERSION_10 = [
    '<tableVersion value="0x00010000"/>',
] + VHEA_XML_VERSION_11[1:]

VHEA_XML_VERSION_10_AS_FLOAT = [
    '<tableVersion value="1.0"/>',
] + VHEA_XML_VERSION_11[1:]


class VheaCompileOrToXMLTest(unittest.TestCase):

    def setUp(self):
        vhea = newTable('vhea')
        vhea.tableVersion = 0x00010000
        vhea.ascent = 500
        vhea.descent = -500
        vhea.lineGap = 0
        vhea.advanceHeightMax = 3000
        vhea.minTopSideBearing = -1002
        vhea.minBottomSideBearing = -677
        vhea.yMaxExtent = 2928
        vhea.caretSlopeRise = 0
        vhea.caretSlopeRun = 1
        vhea.caretOffset = 0
        vhea.metricDataFormat = 0
        vhea.numberOfVMetrics = 12
        vhea.reserved1 = vhea.reserved2 = vhea.reserved3 = vhea.reserved4 = 0
        self.font = TTFont(sfntVersion='OTTO')
        self.font['vhea'] = vhea

    def test_compile_caretOffset_as_reserved0(self):
        vhea = self.font['vhea']
        del vhea.caretOffset
        vhea.reserved0 = 0
        self.assertEqual(VHEA_DATA_VERSION_10, vhea.compile(self.font))

    def test_compile_version_10(self):
        vhea = self.font['vhea']
        vhea.tableVersion = 0x00010000
        self.assertEqual(VHEA_DATA_VERSION_10, vhea.compile(self.font))

    def test_compile_version_10_as_float(self):
        vhea = self.font['vhea']
        vhea.tableVersion = 1.0
        with CapturingLogHandler(log, "WARNING") as captor:
            self.assertEqual(VHEA_DATA_VERSION_10, vhea.compile(self.font))
        self.assertTrue(
            len([r for r in captor.records
                 if "Table version value is a float" in r.msg]) == 1)

    def test_compile_version_11(self):
        vhea = self.font['vhea']
        vhea.tableVersion = 0x00011000
        self.assertEqual(VHEA_DATA_VERSION_11, vhea.compile(self.font))

    def test_compile_version_11_as_float(self):
        vhea = self.font['vhea']
        vhea.tableVersion = 1.0625
        with CapturingLogHandler(log, "WARNING") as captor:
            self.assertEqual(VHEA_DATA_VERSION_11, vhea.compile(self.font))
        self.assertTrue(
            len([r for r in captor.records
                 if "Table version value is a float" in r.msg]) == 1)

    def test_toXML_caretOffset_as_reserved0(self):
        vhea = self.font['vhea']
        del vhea.caretOffset
        vhea.reserved0 = 0
        self.assertEqual(getXML(vhea.toXML), VHEA_XML_VERSION_10)

    def test_toXML_version_10(self):
        vhea = self.font['vhea']
        self.font['vhea'].tableVersion = 0x00010000
        self.assertEqual(getXML(vhea.toXML), VHEA_XML_VERSION_10)

    def test_toXML_version_10_as_float(self):
        vhea = self.font['vhea']
        vhea.tableVersion = 1.0
        with CapturingLogHandler(log, "WARNING") as captor:
            self.assertEqual(getXML(vhea.toXML), VHEA_XML_VERSION_10)
        self.assertTrue(
            len([r for r in captor.records
                 if "Table version value is a float" in r.msg]) == 1)

    def test_toXML_version_11(self):
        vhea = self.font['vhea']
        self.font['vhea'].tableVersion = 0x00011000
        self.assertEqual(getXML(vhea.toXML), VHEA_XML_VERSION_11)

    def test_toXML_version_11_as_float(self):
        vhea = self.font['vhea']
        vhea.tableVersion = 1.0625
        with CapturingLogHandler(log, "WARNING") as captor:
            self.assertEqual(getXML(vhea.toXML), VHEA_XML_VERSION_11)
        self.assertTrue(
            len([r for r in captor.records
                 if "Table version value is a float" in r.msg]) == 1)


class VheaDecompileOrFromXMLTest(unittest.TestCase):

    def setUp(self):
        vhea = newTable('vhea')
        self.font = TTFont(sfntVersion='OTTO')
        self.font['vhea'] = vhea

    def test_decompile_version_10(self):
        vhea = self.font['vhea']
        vhea.decompile(VHEA_DATA_VERSION_10, self.font)
        for key in vhea.__dict__:
            self.assertEqual(getattr(vhea, key), VHEA_VERSION_10_AS_DICT[key])

    def test_decompile_version_11(self):
        vhea = self.font['vhea']
        vhea.decompile(VHEA_DATA_VERSION_11, self.font)
        for key in vhea.__dict__:
            self.assertEqual(getattr(vhea, key), VHEA_VERSION_11_AS_DICT[key])

    def test_fromXML_version_10(self):
        vhea = self.font['vhea']
        for name, attrs, content in parseXML(VHEA_XML_VERSION_10):
            vhea.fromXML(name, attrs, content, self.font)
        for key in vhea.__dict__:
            self.assertEqual(getattr(vhea, key), VHEA_VERSION_10_AS_DICT[key])

    def test_fromXML_version_10_as_float(self):
        vhea = self.font['vhea']
        with CapturingLogHandler(log, "WARNING") as captor:
            for name, attrs, content in parseXML(VHEA_XML_VERSION_10_AS_FLOAT):
                vhea.fromXML(name, attrs, content, self.font)
        self.assertTrue(
            len([r for r in captor.records
                 if "Table version value is a float" in r.msg]) == 1)
        for key in vhea.__dict__:
            self.assertEqual(getattr(vhea, key), VHEA_VERSION_10_AS_DICT[key])

    def test_fromXML_version_11(self):
        vhea = self.font['vhea']
        for name, attrs, content in parseXML(VHEA_XML_VERSION_11):
            vhea.fromXML(name, attrs, content, self.font)
        for key in vhea.__dict__:
            self.assertEqual(getattr(vhea, key), VHEA_VERSION_11_AS_DICT[key])

    def test_fromXML_version_11_as_float(self):
        vhea = self.font['vhea']
        with CapturingLogHandler(log, "WARNING") as captor:
            for name, attrs, content in parseXML(VHEA_XML_VERSION_11_AS_FLOAT):
                vhea.fromXML(name, attrs, content, self.font)
        self.assertTrue(
            len([r for r in captor.records
                 if "Table version value is a float" in r.msg]) == 1)
        for key in vhea.__dict__:
            self.assertEqual(getattr(vhea, key), VHEA_VERSION_11_AS_DICT[key])


class VheaRecalcTest(unittest.TestCase):

    def test_recalc_TTF(self):
        font = TTFont()
        font.importXML(os.path.join(DATA_DIR, '_v_h_e_a_recalc_TTF.ttx'))
        vhea = font['vhea']
        vhea.recalc(font)
        self.assertEqual(vhea.advanceHeightMax, 900)
        self.assertEqual(vhea.minTopSideBearing, 200)
        self.assertEqual(vhea.minBottomSideBearing, 377)
        self.assertEqual(vhea.yMaxExtent, 312)

    def test_recalc_OTF(self):
        font = TTFont()
        font.importXML(os.path.join(DATA_DIR, '_v_h_e_a_recalc_OTF.ttx'))
        vhea = font['vhea']
        vhea.recalc(font)
        self.assertEqual(vhea.advanceHeightMax, 900)
        self.assertEqual(vhea.minTopSideBearing, 200)
        self.assertEqual(vhea.minBottomSideBearing, 377)
        self.assertEqual(vhea.yMaxExtent, 312)

    def test_recalc_empty(self):
        font = TTFont()
        font.importXML(os.path.join(DATA_DIR, '_v_h_e_a_recalc_empty.ttx'))
        vhea = font['vhea']
        vhea.recalc(font)
        self.assertEqual(vhea.advanceHeightMax, 900)
        self.assertEqual(vhea.minTopSideBearing, 0)
        self.assertEqual(vhea.minBottomSideBearing, 0)
        self.assertEqual(vhea.yMaxExtent, 0)


if __name__ == "__main__":
    import sys
    sys.exit(unittest.main())
