"""
Test item styles.
"""

import unittest

from gaphor.diagram.style import get_text_point, \
    get_text_point_at_line, get_text_point_at_line2, get_min_size, \
    ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT, ALIGN_TOP, ALIGN_MIDDLE, ALIGN_BOTTOM


class StyleTestCase(unittest.TestCase):
    def test_min_size(self):
        """
        Test minimum size calculation
        """
        width, height = get_min_size(10, 10, (1, 2, 3, 4))
        self.assertEqual(width, 16)
        self.assertEqual(height, 14)


    def test_align_box(self):
        """
        Test aligned text position calculation
        """
        extents = 80, 12
        padding = (1, 2, 3, 4)
        data = {
                (ALIGN_LEFT,   ALIGN_TOP,    False): (  4, 1),
                (ALIGN_LEFT,   ALIGN_MIDDLE, False): (  4, 14),
                (ALIGN_LEFT,   ALIGN_BOTTOM, False): (  4, 25),
                (ALIGN_CENTER, ALIGN_TOP,    False): ( 42, 1),
                (ALIGN_CENTER, ALIGN_MIDDLE, False): ( 42, 14),
                (ALIGN_CENTER, ALIGN_BOTTOM, False): ( 42, 25),
                (ALIGN_RIGHT,  ALIGN_TOP,    False): ( 78, 1),
                (ALIGN_RIGHT,  ALIGN_MIDDLE, False): ( 78, 14),
                (ALIGN_RIGHT,  ALIGN_BOTTOM, False): ( 78, 25),
                (ALIGN_LEFT,   ALIGN_TOP,    True):  (-84, -13),
                (ALIGN_LEFT,   ALIGN_MIDDLE, True):  (-84, 14),
                (ALIGN_LEFT,   ALIGN_BOTTOM, True):  (-84, 43),
                (ALIGN_CENTER, ALIGN_TOP,    True):  ( 40, -13),
                (ALIGN_CENTER, ALIGN_MIDDLE, True):  ( 40, 14),
                (ALIGN_CENTER, ALIGN_BOTTOM, True):  ( 40, 43),
                (ALIGN_RIGHT,  ALIGN_TOP,    True):  (162, -13),
                (ALIGN_RIGHT,  ALIGN_MIDDLE, True):  (162, 14),
                (ALIGN_RIGHT,  ALIGN_BOTTOM, True):  (162, 43),
        }

        for halign in range(-1, 2):
            for valign in range(-1, 2):
                for outside in (True, False):
                    align = (halign, valign)
                    point_expected = data[(halign, valign, outside)]
                    point = get_text_point(extents, 160, 40, \
                            align, padding, outside)

                    self.assertEqual(point[0], point_expected[0], \
                        '%s, %s -> %s' % (align, outside, point[0]))
                    self.assertEqual(point[1], point_expected[1], \
                        '%s, %s -> %s' % (align, outside, point[1]))


    def test_align_line(self):
        """
        Test aligned at the line text position calculation
        """
        p1 = 0, 0
        p2 = 20, 20

        extents = 10, 5

        x, y = get_text_point_at_line(extents, p1, p2,
                (ALIGN_LEFT, ALIGN_TOP), (2, 2, 2, 2))
        self.assertEqual(x, 5)
        self.assertEqual(y, -10)

        x, y = get_text_point_at_line(extents, p1, p2,
                (ALIGN_RIGHT, ALIGN_TOP), (2, 2, 2, 2))
        self.assertEqual(x, 5)
        self.assertEqual(y, -10)

        p2 = -20, 20
        x, y = get_text_point_at_line(extents, p1, p2,
                (ALIGN_LEFT, ALIGN_TOP), (2, 2, 2, 2))
        self.assertEqual(x, -15)
        self.assertEqual(y, -10)

        x, y = get_text_point_at_line(extents, p1, p2,
                (ALIGN_RIGHT, ALIGN_TOP), (2, 2, 2, 2))
        self.assertEqual(x, -15)
        self.assertEqual(y, -10)


    def test_align_line2_h(self):
        """
        Test aligned at the line text position calculation, horizontal mode
        """
        extents = 10, 5
        p1 = 2.0, 2.0

        # align top
        p2 = 22.0, 7.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_TOP), (3, 2, 3, 2))
        self.assertAlmostEqual(x, 7)
        self.assertAlmostEqual(y, -4.75)

        p2 = 22.0, -3.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_TOP), (3, 2, 3, 2))
        self.assertAlmostEqual(x, 7)
        self.assertAlmostEqual(y, -9.75)

        p2 = -18.0, 7.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_TOP), (3, 2, 3, 2))
        self.assertAlmostEqual(x, -13)
        self.assertAlmostEqual(y, -4.75)

        p2 = -18.0, -3.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_TOP), (3, 2, 3, 2))
        self.assertAlmostEqual(x, -13)
        self.assertAlmostEqual(y, -9.75)

        # align bottom
        p2 = 22.0, 7.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_BOTTOM), (3, 2, 3, 2))
        self.assertAlmostEqual(x, 7)
        self.assertAlmostEqual(y, 8.75)

        p2 = 22.0, -3.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_BOTTOM), (3, 2, 3, 2))
        self.assertAlmostEqual(x, 7)
        self.assertAlmostEqual(y, 3.75)

        p2 = -18.0, 7.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_BOTTOM), (3, 2, 3, 2))
        self.assertAlmostEqual(x, -13)
        self.assertAlmostEqual(y, 8.75)

        p2 = -18.0, -3.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_BOTTOM), (3, 2, 3, 2))
        self.assertAlmostEqual(x, -13)
        self.assertAlmostEqual(y, 3.75)


    def test_align_line2_v(self):
        """
        Test aligned at the line text position calculation, vertical mode
        """
        extents = 10, 5
        p1 = 2.0, 2.0

        # top align
        p2 = 7.0, 22.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_TOP), (3, 2, 3, 2))
        self.assertAlmostEqual(x, 7.125)
        self.assertAlmostEqual(y, 9.5)

        p2 = 7.0, -18.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_TOP), (3, 2, 3, 2))
        self.assertAlmostEqual(x, -8.125)
        self.assertAlmostEqual(y, -10.5)

        p2 = -3.0, 22.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_TOP), (3, 2, 3, 2))
        self.assertAlmostEqual(x, -13.125)
        self.assertAlmostEqual(y, 9.5)

        p2 = -3.0, -18.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_TOP), (3, 2, 3, 2))
        self.assertAlmostEqual(x, 2.125)
        self.assertAlmostEqual(y, -10.5)

        # bottom align
        p2 = 7.0, 22.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_BOTTOM), (3, 2, 3, 2))
        self.assertAlmostEqual(x, -8.125)
        self.assertAlmostEqual(y, 9.5)

        p2 = 7.0, -18.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_BOTTOM), (3, 2, 3, 2))
        self.assertAlmostEqual(x, 7.125)
        self.assertAlmostEqual(y, -10.5)

        p2 = -3.0, 22.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_BOTTOM), (3, 2, 3, 2))
        self.assertAlmostEqual(x, 2.125)
        self.assertAlmostEqual(y, 9.5)

        p2 = -3.0, -18.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_BOTTOM), (3, 2, 3, 2))
        self.assertAlmostEqual(x, -13.125)
        self.assertAlmostEqual(y, -10.5)


    def test_align_line2_o(self):
        """
        Test aligned at the line text position calculation, orthogonal
        lines
        """
        extents = 10, 5
        p1 = 2.0, 2.0

        # top align
        p2 = 22.0, 2.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_TOP), (3, 2, 3, 2))
        self.assertAlmostEqual(x, 7)
        self.assertAlmostEqual(y, -6)

        p2 = -18.0, 2.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_TOP), (3, 2, 3, 2))
        self.assertAlmostEqual(x, -13)
        self.assertAlmostEqual(y, -6)

        p2 = 2.0, 22.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_TOP), (3, 2, 3, 2))
        self.assertAlmostEqual(x, -10.0)
        self.assertAlmostEqual(y, 9.5)

        p2 = 2.0, -18.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_TOP), (3, 2, 3, 2))
        self.assertAlmostEqual(x, -10.0)
        self.assertAlmostEqual(y, -10.5)

        # bottom align
        p2 = 22.0, 2.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_BOTTOM), (3, 2, 3, 2))
        self.assertAlmostEqual(x, 7)
        self.assertAlmostEqual(y, 5)

        p2 = -18.0, 2.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_BOTTOM), (3, 2, 3, 2))
        self.assertAlmostEqual(x, -13.0)
        self.assertAlmostEqual(y, 5.0)

        p2 = 2.0, 22.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_BOTTOM), (3, 2, 3, 2))
        self.assertAlmostEqual(x, 4.0)
        self.assertAlmostEqual(y, 9.5)

        p2 = 2.0, -18.0
        x, y = get_text_point_at_line2(extents, p1, p2,
                (ALIGN_CENTER, ALIGN_BOTTOM), (3, 2, 3, 2))
        self.assertAlmostEqual(x, 4.0)
        self.assertAlmostEqual(y, -10.5)
