import pytest

from easyansi import drawing as d
from easyansi import cursor as cur


####################################################################################################
# box, box_code
####################################################################################################


# Validations


def test_box_code_invalid_width():
    with pytest.raises(ValueError) as vl_error:
        d.box_code(d.MIN_BOX_WIDTH - 1, d.MIN_BOX_HEIGHT)
    assert "Box Width" in str(vl_error.value)


def test_box_code_invalid_height():
    with pytest.raises(ValueError) as vl_error:
        d.box_code(d.MIN_BOX_WIDTH, d.MIN_BOX_HEIGHT - 1)
    assert "Box Height" in str(vl_error.value)


def test_box_code_invalid_style():
    with pytest.raises(ValueError) as vl_error:
        d.box(10, 10, style="")
    assert "Box Line Style" in str(vl_error.value)


# Test box is drawing correctly

def test_box_and_box_code(capsys):
    width = 10
    height = 5
    style = d.styles.DOUBLE
    top = "_"
    bottom = "~"
    left = "["
    right = "]"
    top_left = "A"
    top_right = "B"
    bottom_left = "C"
    bottom_right = "D"
    top_bottom = "*"
    left_right = "@"
    all_corners = "$"
    all_sides = "#"
    all_chars = "."
    actual_code = d.box_code(width=width, height=height, style=style, top=top, bottom=bottom,
                             left=left, right=right, top_left=top_left, top_right=top_right,
                             bottom_left=bottom_left, bottom_right=bottom_right,
                             top_bottom=top_bottom, left_right=left_right, all_corners=all_corners,
                             all_sides=all_sides, all_chars=all_chars)
    d.box(width=width, height=height, style=style, top=top, bottom=bottom,
          left=left, right=right, top_left=top_left, top_right=top_right,
          bottom_left=bottom_left, bottom_right=bottom_right,
          top_bottom=top_bottom, left_right=left_right, all_corners=all_corners,
          all_sides=all_sides, all_chars=all_chars)
    captured = capsys.readouterr()
    assert actual_code == captured.out


def _build_box_code(top_lt, top_hline_cd, top_rt, rt_vline_cd,
                    lt_vline_cd, bot_lt, bot_hline_cd, bot_rt,
                    vline_len, hline_len):
    # Build the expected code to draw a box
    # top
    box_cd = top_lt + top_hline_cd + top_rt
    box_cd += cur.down_code(1) + cur.left_code(1)
    # right
    box_cd += rt_vline_cd
    if vline_len > 1:
        box_cd += cur.up_code(vline_len - 1)
    if vline_len > 0:
        box_cd += cur.left_code(1)
    box_cd += cur.left_code(len(top_lt) + hline_len + len(top_rt) - 1)
    #left
    box_cd += lt_vline_cd
    if vline_len > 0:
        box_cd += cur.down_code(1) + cur.left_code(1)
    # bottom
    box_cd += bot_lt + bot_hline_cd + bot_rt
    return box_cd


def test_box_code_2_by_2():
    hline_len = 0
    vline_len = 0
    top_lt = d.single.TOP_LEFT
    top_hline_cd = ""
    top_rt = d.single.TOP_RIGHT
    rt_vline_cd = ""
    lt_vline_cd = ""
    bot_lt = d.single.BOTTOM_LEFT
    bot_hline_cd = ""
    bot_rt = d.single.BOTTOM_RIGHT
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(2, 2)
    assert expected_box_code == actual_box_code


def test_box_code_3_by_3():
    hline_len = 1
    vline_len = 1
    top_lt = d.single.TOP_LEFT
    top_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    top_rt = d.single.TOP_RIGHT
    rt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    lt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    bot_lt = d.single.BOTTOM_LEFT
    bot_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    bot_rt = d.single.BOTTOM_RIGHT
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(3, 3)
    assert expected_box_code == actual_box_code


def test_box_code_4_by_4():
    hline_len = 2
    vline_len = 2
    top_lt = d.single.TOP_LEFT
    top_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    top_rt = d.single.TOP_RIGHT
    rt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    lt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    bot_lt = d.single.BOTTOM_LEFT
    bot_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    bot_rt = d.single.BOTTOM_RIGHT
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(4, 4)
    assert expected_box_code == actual_box_code


def test_box_code_2_by_4():
    hline_len = 0
    vline_len = 2
    top_lt = d.single.TOP_LEFT
    top_hline_cd = ""
    top_rt = d.single.TOP_RIGHT
    rt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    lt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    bot_lt = d.single.BOTTOM_LEFT
    bot_hline_cd = ""
    bot_rt = d.single.BOTTOM_RIGHT
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(2, 4)
    assert expected_box_code == actual_box_code


def test_box_code_4_by_2():
    hline_len = 2
    vline_len = 0
    top_lt = d.single.TOP_LEFT
    top_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    top_rt = d.single.TOP_RIGHT
    rt_vline_cd = ""
    lt_vline_cd = ""
    bot_lt = d.single.BOTTOM_LEFT
    bot_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    bot_rt = d.single.BOTTOM_RIGHT
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(4, 2)
    assert expected_box_code == actual_box_code


# Test styles


def test_box_code_double_style():
    hline_len = 5
    vline_len = 3
    top_lt = d.double.TOP_LEFT
    top_hline_cd = d.hline_code(hline_len, char=d.double.HORIZONTAL)
    top_rt = d.double.TOP_RIGHT
    rt_vline_cd = d.vline_code(vline_len, char=d.double.VERTICAL)
    lt_vline_cd = d.vline_code(vline_len, char=d.double.VERTICAL)
    bot_lt = d.double.BOTTOM_LEFT
    bot_hline_cd = d.hline_code(hline_len, char=d.double.HORIZONTAL)
    bot_rt = d.double.BOTTOM_RIGHT
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(7, 5, style=d.styles.DOUBLE)
    assert expected_box_code == actual_box_code


def test_box_code_keyboard_style():
    hline_len = 5
    vline_len = 3
    top_lt = d.keyboard.TOP_LEFT
    top_hline_cd = d.hline_code(hline_len, char=d.keyboard.HORIZONTAL)
    top_rt = d.keyboard.TOP_RIGHT
    rt_vline_cd = d.vline_code(vline_len, char=d.keyboard.VERTICAL)
    lt_vline_cd = d.vline_code(vline_len, char=d.keyboard.VERTICAL)
    bot_lt = d.keyboard.BOTTOM_LEFT
    bot_hline_cd = d.hline_code(hline_len, char=d.keyboard.HORIZONTAL)
    bot_rt = d.keyboard.BOTTOM_RIGHT
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(7, 5, style=d.styles.KEYBOARD)
    assert expected_box_code == actual_box_code


def test_box_code_single_style():
    hline_len = 5
    vline_len = 3
    top_lt = d.single.TOP_LEFT
    top_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    top_rt = d.single.TOP_RIGHT
    rt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    lt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    bot_lt = d.single.BOTTOM_LEFT
    bot_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    bot_rt = d.single.BOTTOM_RIGHT
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(7, 5, style=d.styles.SINGLE)
    assert expected_box_code == actual_box_code


def test_box_code_single_style_equals_default_style():
    expected_box_code = d.box_code(7, 5)
    actual_box_code = d.box_code(7, 5, style=d.styles.SINGLE)
    assert expected_box_code == actual_box_code


# Test character overrides: corners


def test_box_code_empty_corners():
    with pytest.raises(ValueError) as vl_error:
        d.box(10, 10, all_corners="")
    assert "All Corners Character" in str(vl_error.value)


def test_box_code_long_corners():
    with pytest.raises(ValueError) as vl_error:
        d.box(10, 10, all_corners="@@")
    assert "All Corners Character Length" in str(vl_error.value)


def test_box_code_corners_override():
    all_corners = "@"
    hline_len = 5
    vline_len = 3
    top_lt = all_corners
    top_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    top_rt = all_corners
    rt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    lt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    bot_lt = all_corners
    bot_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    bot_rt = all_corners
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(7, 5, all_corners=all_corners)
    assert expected_box_code == actual_box_code


def test_box_code_empty_top_left():
    with pytest.raises(ValueError) as vl_error:
        d.box(10, 10, top_left="")
    assert "Top Left Character" in str(vl_error.value)


def test_box_code_long_top_left():
    with pytest.raises(ValueError) as vl_error:
        d.box(10, 10, top_left="@@")
    assert "Top Left Character Length" in str(vl_error.value)


def test_box_code_top_left_override():
    top_left = "A"
    hline_len = 5
    vline_len = 3
    top_lt = top_left
    top_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    top_rt = d.single.TOP_RIGHT
    rt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    lt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    bot_lt = d.single.BOTTOM_LEFT
    bot_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    bot_rt = d.single.BOTTOM_RIGHT
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(7, 5, top_left=top_left)
    assert expected_box_code == actual_box_code


def test_box_code_empty_top_right():
    with pytest.raises(ValueError) as vl_error:
        d.box(10, 10, top_right="")
    assert "Top Right Character" in str(vl_error.value)


def test_box_code_long_top_right():
    with pytest.raises(ValueError) as vl_error:
        d.box(10, 10, top_right="@@")
    assert "Top Right Character Length" in str(vl_error.value)


def test_box_code_top_right_override():
    top_right = "B"
    hline_len = 5
    vline_len = 3
    top_lt = d.single.TOP_LEFT
    top_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    top_rt = top_right
    rt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    lt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    bot_lt = d.single.BOTTOM_LEFT
    bot_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    bot_rt = d.single.BOTTOM_RIGHT
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(7, 5, top_right=top_right)
    assert expected_box_code == actual_box_code


def test_box_code_empty_bottom_left():
    with pytest.raises(ValueError) as vl_error:
        d.box(10, 10, bottom_left="")
    assert "Bottom Left Character" in str(vl_error.value)


def test_box_code_long_bottom_left():
    with pytest.raises(ValueError) as vl_error:
        d.box(10, 10, bottom_left="@@")
    assert "Bottom Left Character Length" in str(vl_error.value)


def test_box_code_bottom_left_override():
    bottom_left = "C"
    hline_len = 5
    vline_len = 3
    top_lt = d.single.TOP_LEFT
    top_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    top_rt = d.single.TOP_RIGHT
    rt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    lt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    bot_lt = bottom_left
    bot_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    bot_rt = d.single.BOTTOM_RIGHT
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(7, 5, bottom_left=bottom_left)
    assert expected_box_code == actual_box_code


def test_box_code_empty_bottom_right():
    with pytest.raises(ValueError) as vl_error:
        d.box(10, 10, bottom_right="")
    assert "Bottom Right Character" in str(vl_error.value)


def test_box_code_long_bottom_right():
    with pytest.raises(ValueError) as vl_error:
        d.box(10, 10, bottom_right="@@")
    assert "Bottom Right Character Length" in str(vl_error.value)


def test_box_code_bottom_right_override():
    bottom_right = "D"
    hline_len = 5
    vline_len = 3
    top_lt = d.single.TOP_LEFT
    top_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    top_rt = d.single.TOP_RIGHT
    rt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    lt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    bot_lt = d.single.BOTTOM_LEFT
    bot_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    bot_rt = bottom_right
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(7, 5, bottom_right=bottom_right)
    assert expected_box_code == actual_box_code


def test_box_code_all_corners_overridden_by_individual_corners():
    all_corners = "@"
    top_left = "A"
    top_right = "B"
    bottom_left = "C"
    bottom_right = "D"
    hline_len = 5
    vline_len = 3
    top_lt = top_left
    top_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    top_rt = top_right
    rt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    lt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    bot_lt = bottom_left
    bot_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    bot_rt = bottom_right
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(7, 5, all_corners=all_corners, top_right=top_right,
                                 top_left=top_left, bottom_right=bottom_right,
                                 bottom_left=bottom_left)
    assert expected_box_code == actual_box_code


# Test character overrides: sides


def test_box_code_all_sides_overridden():
    all_sides = "#"
    hline_len = 5
    vline_len = 3
    top_lt = d.single.TOP_LEFT
    top_hline_cd = d.hline_code(hline_len, char=all_sides)
    top_rt = d.single.TOP_RIGHT
    rt_vline_cd = d.vline_code(vline_len, char=all_sides)
    lt_vline_cd = d.vline_code(vline_len, char=all_sides)
    bot_lt = d.single.BOTTOM_LEFT
    bot_hline_cd = d.hline_code(hline_len, char=all_sides)
    bot_rt = d.single.BOTTOM_RIGHT
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(7, 5, all_sides=all_sides)
    assert expected_box_code == actual_box_code


def test_box_code_top_bottom_overridden():
    top_bottom = "#"
    hline_len = 5
    vline_len = 3
    top_lt = d.single.TOP_LEFT
    top_hline_cd = d.hline_code(hline_len, char=top_bottom)
    top_rt = d.single.TOP_RIGHT
    rt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    lt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    bot_lt = d.single.BOTTOM_LEFT
    bot_hline_cd = d.hline_code(hline_len, char=top_bottom)
    bot_rt = d.single.BOTTOM_RIGHT
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(7, 5, top_bottom=top_bottom)
    assert expected_box_code == actual_box_code


def test_box_code_left_right_overridden():
    left_right = "#"
    hline_len = 5
    vline_len = 3
    top_lt = d.single.TOP_LEFT
    top_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    top_rt = d.single.TOP_RIGHT
    rt_vline_cd = d.vline_code(vline_len, char=left_right)
    lt_vline_cd = d.vline_code(vline_len, char=left_right)
    bot_lt = d.single.BOTTOM_LEFT
    bot_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    bot_rt = d.single.BOTTOM_RIGHT
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(7, 5, left_right=left_right)
    assert expected_box_code == actual_box_code


def test_box_code_all_sides_top_bottom_left_right_overridden():
    all_sides = "#"
    top_bottom = "@"
    left_right = "%"
    hline_len = 5
    vline_len = 3
    top_lt = d.single.TOP_LEFT
    top_hline_cd = d.hline_code(hline_len, char=top_bottom)
    top_rt = d.single.TOP_RIGHT
    rt_vline_cd = d.vline_code(vline_len, char=left_right)
    lt_vline_cd = d.vline_code(vline_len, char=left_right)
    bot_lt = d.single.BOTTOM_LEFT
    bot_hline_cd = d.hline_code(hline_len, char=top_bottom)
    bot_rt = d.single.BOTTOM_RIGHT
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(7, 5, all_sides=all_sides, top_bottom=top_bottom,
                                 left_right=left_right)
    assert expected_box_code == actual_box_code


def test_box_code_top_overridden():
    top = "*"
    hline_len = 5
    vline_len = 3
    top_lt = d.single.TOP_LEFT
    top_hline_cd = d.hline_code(hline_len, char=top)
    top_rt = d.single.TOP_RIGHT
    rt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    lt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    bot_lt = d.single.BOTTOM_LEFT
    bot_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    bot_rt = d.single.BOTTOM_RIGHT
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(7, 5, top=top)
    assert expected_box_code == actual_box_code


def test_box_code_bottom_overridden():
    bottom = "*"
    hline_len = 5
    vline_len = 3
    top_lt = d.single.TOP_LEFT
    top_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    top_rt = d.single.TOP_RIGHT
    rt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    lt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    bot_lt = d.single.BOTTOM_LEFT
    bot_hline_cd = d.hline_code(hline_len, char=bottom)
    bot_rt = d.single.BOTTOM_RIGHT
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(7, 5, bottom=bottom)
    assert expected_box_code == actual_box_code


def test_box_code_left_overridden():
    left = "*"
    hline_len = 5
    vline_len = 3
    top_lt = d.single.TOP_LEFT
    top_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    top_rt = d.single.TOP_RIGHT
    rt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    lt_vline_cd = d.vline_code(vline_len, char=left)
    bot_lt = d.single.BOTTOM_LEFT
    bot_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    bot_rt = d.single.BOTTOM_RIGHT
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(7, 5, left=left)
    assert expected_box_code == actual_box_code


def test_box_code_right_overridden():
    right = "*"
    hline_len = 5
    vline_len = 3
    top_lt = d.single.TOP_LEFT
    top_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    top_rt = d.single.TOP_RIGHT
    rt_vline_cd = d.vline_code(vline_len, char=right)
    lt_vline_cd = d.vline_code(vline_len, char=d.single.VERTICAL)
    bot_lt = d.single.BOTTOM_LEFT
    bot_hline_cd = d.hline_code(hline_len, char=d.single.HORIZONTAL)
    bot_rt = d.single.BOTTOM_RIGHT
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(7, 5, right=right)
    assert expected_box_code == actual_box_code


def test_box_code_all_sides_each_side_overridden():
    all_sides = "#"
    top = "A"
    bottom = "B"
    left = "C"
    right = "D"
    hline_len = 5
    vline_len = 3
    top_lt = d.single.TOP_LEFT
    top_hline_cd = d.hline_code(hline_len, char=top)
    top_rt = d.single.TOP_RIGHT
    rt_vline_cd = d.vline_code(vline_len, char=right)
    lt_vline_cd = d.vline_code(vline_len, char=left)
    bot_lt = d.single.BOTTOM_LEFT
    bot_hline_cd = d.hline_code(hline_len, char=bottom)
    bot_rt = d.single.BOTTOM_RIGHT
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(7, 5, all_sides=all_sides, top=top, bottom=bottom,
                                 left=left, right=right)
    assert expected_box_code == actual_box_code


# Test character overrides: all characters

def test_box_code_empty_all_chars():
    with pytest.raises(ValueError) as vl_error:
        d.box(10, 10, all_chars="")
    assert "All Characters Character" in str(vl_error.value)


def test_box_code_long_all_chars():
    with pytest.raises(ValueError) as vl_error:
        d.box(10, 10, all_chars="@@")
    assert "All Characters Character Length" in str(vl_error.value)


def test_box_code_all_chars_override():
    all_chars = "*"
    hline_len = 5
    vline_len = 3
    top_lt = all_chars
    top_hline_cd = d.hline_code(hline_len, char=all_chars)
    top_rt = all_chars
    rt_vline_cd = d.vline_code(vline_len, char=all_chars)
    lt_vline_cd = d.vline_code(vline_len, char=all_chars)
    bot_lt = all_chars
    bot_hline_cd = d.hline_code(hline_len, char=all_chars)
    bot_rt = all_chars
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(7, 5, all_chars=all_chars)
    assert expected_box_code == actual_box_code


def test_box_code_all_chars_overriden_by_specifics():
    all_chars = "*"
    top_left = "A"
    top_right = "B"
    bottom_left = "C"
    bottom_right = "D"
    top = "a"
    bottom = "b"
    left = "c"
    right = "d"
    hline_len = 5
    vline_len = 3
    top_lt = top_left
    top_hline_cd = d.hline_code(hline_len, char=top)
    top_rt = top_right
    rt_vline_cd = d.vline_code(vline_len, char=right)
    lt_vline_cd = d.vline_code(vline_len, char=left)
    bot_lt = bottom_left
    bot_hline_cd = d.hline_code(hline_len, char=bottom)
    bot_rt = bottom_right
    expected_box_code = _build_box_code(top_lt=top_lt, top_hline_cd=top_hline_cd, top_rt=top_rt,
                                        rt_vline_cd=rt_vline_cd, lt_vline_cd=lt_vline_cd,
                                        bot_lt=bot_lt, bot_hline_cd=bot_hline_cd, bot_rt=bot_rt,
                                        hline_len=hline_len, vline_len=vline_len)
    actual_box_code = d.box_code(7, 5, all_chars=all_chars, top=top, bottom=bottom, left=left,
                                 right=right, top_left=top_left, top_right=top_right,
                                 bottom_left=bottom_left, bottom_right=bottom_right)
    assert expected_box_code == actual_box_code
