# -*- coding: utf-8 -*-
"""
    tests.templater
    ---------------

    Tests templater module.
"""

import os
import pytest
import traceback
import yaml

from renoir import Renoir


@pytest.fixture(scope='function')
def templater():
    return Renoir(
        mode='plain', debug=True, path=os.path.join(
            os.path.dirname(os.path.abspath(__file__)), 'yaml'
        )
    )


@pytest.fixture(scope='function')
def templater_indent():
    return Renoir(
        mode='plain', adjust_indent=True, debug=True, path=os.path.join(
            os.path.dirname(os.path.abspath(__file__)), 'yaml'
        )
    )


@pytest.fixture(scope='function')
def templater_html():
    return Renoir(
        debug=True, path=os.path.join(
            os.path.dirname(os.path.abspath(__file__)), 'html'
        )
    )


@pytest.fixture(scope='function')
def templater_html_indent():
    return Renoir(
        escape='all', adjust_indent=True, debug=True,
        path=os.path.join(
            os.path.dirname(os.path.abspath(__file__)), 'html'
        )
    )


yaml_rendered = """
str: str
int: 1
float: 1.2
sfloat: "1.2"
obj:
  nested:
    key: str
    array:
      - foo
      - bar
  array:
    - foo
    - foo: bar
      array:
        - str
        - foo
        - 1
        - 1.2
    - bar: foo bar
    - bar2: foo foo2 bar
    - bar3: foo foo2 bar bar2
    - bar3: foo foo2 barbar2
    - bar4: foo foo2 barbar2 bar3
"""


def test_plain(templater):
    r = templater.render('basic.yaml', {})
    assert r == yaml_rendered[1:]
    data = yaml.load(r, Loader=yaml.SafeLoader)
    assert data['obj']['nested']['array'][1] == "bar"
    assert data['obj']['array'][1]['array'][-1] == 1.2


yaml_indent_rendered = """
str: str
int: 1
float: 1.2
sfloat: "1.2"
obj:
  nested:
    key: str
    array:
      - foo
      - bar
  array:
    - foo
    - foo: bar
      array: []
    - bar: foo bar
    - bar2: foo foo2 bar
    - bar3: foo foo2 bar bar2
    - bar3: foo foo2 barbar2
    - bar4: foo foo2 barbar2 bar3
inclusion:
  - inclusion_key: inclusion_val
    inclusion_nest:
      first: foo
      second: bar
    main_key: main_val
  - inclusion_1: foo
    main_key: main_val
  - inclusion_2:
      1st: foo
      2nd: bar
    main_key: main_val
  - inclusion_3:
      1st: foo
    main_key: main_val
  - inclusion_4:
      1st: foo
      2nd: bar
    main_key: main_val
added:
  indent:
    foo:
      bar:
        - baz
  ints:
    - 2
    - 4
    - 6
    - 8
"""


def test_plain_indent(templater_indent):
    r = templater_indent.render('nested.yaml', {
        'indent': lambda v, i: (
            "\n".join([
                v.split("\n")[0],
                "\n".join([
                    f"{' '*i}{el}" for el in v.split("\n")[1:]
                ])
            ])
        ),
        'additional': "foo:\n  bar:\n    - baz"
    })
    assert "\n".join([l.rstrip() for l in r.splitlines()]) == \
        yaml_indent_rendered[1:]
    data = yaml.load(r, Loader=yaml.SafeLoader)
    assert data['obj']['nested']['array'][1] == "bar"
    assert data['inclusion'][0]['main_key'] == 'main_val'
    assert data['inclusion'][0]['inclusion_nest']['first'] == 'foo'
    assert not data['obj']['array'][1]['array']
    assert data['added']['indent']['foo']['bar'][0] == "baz"
    assert data['added']['ints'][-1] == 8


html_rendered = """
<!DOCTYPE html>
<html>
    <head>
        <title>Test</title>

    </head>
    <body>
        <div>header1</div>
<div>header2</div>
        <div class="page">
            <a href="/" class="title"><h1>Test</h1></a>
            <div class="nav">
                <a href="/">nuvolosità variabile</a>
            </div>


<ul class="posts">
    <li>
        <h2>foo</h2>
        <hr />
    </li>
    <li>
        <h2>bar</h2>
        <hr />
    </li>
</ul>

        </div>
        <div>footer</div>
    </body>
</html>"""


def test_html(templater_html):
    r = templater_html.render(
        'test.html', {
            'posts': [{'title': 'foo'}, {'title': 'bar'}]
        }
    )
    assert "\n".join([l.rstrip() for l in r.splitlines()]) == \
        html_rendered[1:]


html_indent_rendered = """
<!DOCTYPE html>
<html>
    <head>
        <title>Test</title>

    </head>
    <body>
        <div>header1</div>
        <div>header2</div>
        <div class="page">
            <a href="/" class="title"><h1>Test</h1></a>
            <div class="nav">
                <a href="/">nuvolosit&#224; variabile</a>
            </div>


            <ul class="posts">
                <li>
                    <h2>foo</h2>
                    <hr />
                </li>
                <li>
                    <h2>bar</h2>
                    <hr />
                </li>
            </ul>

        </div>
        <div>footer</div>
    </body>
</html>"""


def test_html_indent(templater_html_indent):
    r = templater_html_indent.render(
        'test.html', {
            'posts': [{'title': 'foo'}, {'title': 'bar'}]
        }
    )
    assert "\n".join([l.rstrip() for l in r.splitlines()]) == \
        html_indent_rendered[1:]


html_indent_rendered2 = """
<!DOCTYPE html>
<html>
    <head>
        <title>Test</title>

    </head>
    <body>
        <div>header1</div>
        <div class="page">
            <a href="/" class="title"><h1>Test</h1></a>
            <div class="nav">
                <a href="/">nuvolosit&#224; variabile</a>
            </div>

            <ul class="posts">
                <li>
                    <h2>foo</h2>
                    <hr />
                </li>
                <li>
                    <h2>bar</h2>
                    <hr />
                </li>
            </ul>

        </div>
        <div>footer</div>
    </body>
</html>"""


def test_html_indent2(templater_html_indent):
    r = templater_html_indent.render(
        'test2.html', {
            'posts': [{'title': 'foo'}, {'title': 'bar'}]
        }
    )
    assert "\n".join([l.rstrip() for l in r.splitlines()]) == \
        html_indent_rendered2[1:]


html_pre_rendered = """
<div>
    <pre>
        <code>
var foo = 'foo';
var bar = '{{ bar }}';
var baz = 'baz';
var list = [
    '0',
    '1',
];
        </code>
    </pre>
</div>"""


def test_html_indent_pre(templater_html_indent):
    r = templater_html_indent.render('pre.html')
    assert "\n".join([l.rstrip() for l in r.splitlines()]) == \
        html_pre_rendered[1:]


def test_pyerror(templater_html):
    with pytest.raises(ZeroDivisionError) as exc:
        templater_html.render('pyerror.html')

    tbs = ''.join(traceback.format_exception(exc.type, exc.value, exc.tb))
    frame = exc.traceback[-1]

    frames = []
    tb = exc.tb
    while tb:
        frames.append(tb)
        tb = tb.tb_next
    tb_frame = frames[-1]

    tpath = os.sep.join(['html', 'pyerror.html'])

    assert frame.name == 'template'
    assert str(frame.path).endswith(tpath)
    assert tb_frame.tb_lineno == 2

    assert f'{tpath}", line 2, in template' in tbs


@pytest.fixture(scope='function')
def templater_blocks():
    return Renoir(
        mode='plain', debug=True, path=os.path.join(
            os.path.dirname(os.path.abspath(__file__)), 'blocks'
        )
    )


_target_b1 = """
super b2
parent b2
child b2
parent l1
child b1
parent l2
child l3
parent l4
child l1
child l2"""


def test_blocks_include(templater_blocks):
    r = templater_blocks.render('child.txt', {'parent_name': './parent_incl.txt'})
    assert "\n".join(
        filter(None, [l.rstrip() for l in r.splitlines()])
    ) == _target_b1[1:]


_target_b2 = """
super b2
parent b2
child b2
parent l1
child b1
parent l2
child l3
parent l4"""


def test_blocks_noinclude(templater_blocks):
    r = templater_blocks.render('child.txt', {'parent_name': './parent_noincl.txt'})
    assert "\n".join(
        filter(None, [l.rstrip() for l in r.splitlines()])
    ) == _target_b2[1:]


_target_b3 = """
parent l1
child b1
parent b2
parent c1
child l1
parent l2"""


def test_blocks_include_multi(templater_blocks):
    r = templater_blocks.render('child_multi_incl.txt', {'condition': True})
    assert "\n".join(
        filter(None, [l.rstrip() for l in r.splitlines()])
    ) == _target_b3[1:]
