"""
    weasyprint.tests.test_counters
    ------------------------------

    Test CSS counters.

"""

import pytest
from weasyprint import HTML

from .testing_utils import assert_no_logs, assert_tree, parse_all, render_pages


@assert_no_logs
def test_counters_1():
    assert_tree(parse_all('''
      <style>
        p { counter-increment: p 2 }
        p:before { content: counter(p); }
        p:nth-child(1) { counter-increment: none; }
        p:nth-child(2) { counter-increment: p; }
      </style>
      <p></p>
      <p></p>
      <p></p>
      <p style="counter-reset: p 117 p"></p>
      <p></p>
      <p></p>
      <p style="counter-reset: p -13"></p>
      <p></p>
      <p></p>
      <p style="counter-reset: p 42"></p>
      <p></p>
      <p></p>'''), [
        ('p', 'Block', [
            ('p', 'Line', [
                ('p::before', 'Inline', [
                    ('p::before', 'Text', counter)])])])
        for counter in '0 1 3  2 4 6  -11 -9 -7  44 46 48'.split()])


@assert_no_logs
def test_counters_2():
    assert_tree(parse_all('''
      <ol style="list-style-position: inside">
        <li></li>
        <li></li>
        <li></li>
        <li><ol>
          <li></li>
          <li style="counter-increment: none"></li>
          <li></li>
        </ol></li>
        <li></li>
      </ol>'''), [
        ('ol', 'Block', [
            ('li', 'Block', [
                ('li', 'Line', [
                    ('li::marker', 'Inline', [
                        ('li::marker', 'Text', '1. ')])])]),
            ('li', 'Block', [
                ('li', 'Line', [
                    ('li::marker', 'Inline', [
                        ('li::marker', 'Text', '2. ')])])]),
            ('li', 'Block', [
                ('li', 'Line', [
                    ('li::marker', 'Inline', [
                        ('li::marker', 'Text', '3. ')])])]),
            ('li', 'Block', [
                ('li', 'Block', [
                    ('li', 'Line', [
                        ('li::marker', 'Inline', [
                            ('li::marker', 'Text', '4. ')])])]),
                ('ol', 'Block', [
                    ('li', 'Block', [
                        ('li', 'Line', [
                            ('li::marker', 'Inline', [
                                ('li::marker', 'Text', '1. ')])])]),
                    ('li', 'Block', [
                        ('li', 'Line', [
                            ('li::marker', 'Inline', [
                                ('li::marker', 'Text', '1. ')])])]),
                    ('li', 'Block', [
                        ('li', 'Line', [
                            ('li::marker', 'Inline', [
                                ('li::marker', 'Text', '2. ')])])])])]),
            ('li', 'Block', [
                ('li', 'Line', [
                    ('li::marker', 'Inline', [
                        ('li::marker', 'Text', '5. ')])])])])])


@assert_no_logs
def test_counters_3():
    assert_tree(parse_all('''
      <style>
        p { display: list-item; list-style: inside decimal }
      </style>
      <div>
        <p></p>
        <p></p>
        <p style="counter-reset: list-item 7 list-item -56"></p>
      </div>
      <p></p>'''), [
        ('div', 'Block', [
            ('p', 'Block', [
                ('p', 'Line', [
                    ('p::marker', 'Inline', [
                        ('p::marker', 'Text', '1. ')])])]),
            ('p', 'Block', [
                ('p', 'Line', [
                    ('p::marker', 'Inline', [
                        ('p::marker', 'Text', '2. ')])])]),
            ('p', 'Block', [
                ('p', 'Line', [
                    ('p::marker', 'Inline', [
                        ('p::marker', 'Text', '-55. ')])])])]),
        ('p', 'Block', [
            ('p', 'Line', [
                ('p::marker', 'Inline', [
                    ('p::marker', 'Text', '1. ')])])])])


@assert_no_logs
def test_counters_4():
    assert_tree(parse_all('''
      <style>
        section:before { counter-reset: h; content: '' }
        h1:before { counter-increment: h; content: counters(h, '.') }
      </style>
      <body>
        <section><h1></h1>
          <h1></h1>
          <section><h1></h1>
            <h1></h1>
          </section>
          <h1></h1>
        </section>
      </body>'''), [
        ('section', 'Block', [
            ('section', 'Block', [
                ('section', 'Line', [
                    ('section::before', 'Inline', [])])]),
            ('h1', 'Block', [
                ('h1', 'Line', [
                    ('h1::before', 'Inline', [
                        ('h1::before', 'Text', '1')])])]),
            ('h1', 'Block', [
                ('h1', 'Line', [
                    ('h1::before', 'Inline', [
                        ('h1::before', 'Text', '2')])])]),
            ('section', 'Block', [
                ('section', 'Block', [
                    ('section', 'Line', [
                        ('section::before', 'Inline', [])])]),
                ('h1', 'Block', [
                    ('h1', 'Line', [
                        ('h1::before', 'Inline', [
                            ('h1::before', 'Text', '2.1')])])]),
                ('h1', 'Block', [
                    ('h1', 'Line', [
                        ('h1::before', 'Inline', [
                            ('h1::before', 'Text', '2.2')])])])]),
            ('h1', 'Block', [
                ('h1', 'Line', [
                    ('h1::before', 'Inline', [
                        ('h1::before', 'Text', '3')])])])])])


@assert_no_logs
def test_counters_5():
    assert_tree(parse_all('''
      <style>
        p:before { content: counter(c) }
      </style>
      <div>
        <span style="counter-reset: c">
          Scope created now, deleted after the div
        </span>
      </div>
      <p></p>'''), [
        ('div', 'Block', [
            ('div', 'Line', [
                ('span', 'Inline', [
                    ('span', 'Text',
                     'Scope created now, deleted after the div ')])])]),
        ('p', 'Block', [
            ('p', 'Line', [
                ('p::before', 'Inline', [
                    ('p::before', 'Text', '0')])])])])


@assert_no_logs
def test_counters_6():
    # counter-increment may interfere with display: list-item
    assert_tree(parse_all('''
      <p style="counter-increment: c;
                display: list-item; list-style: inside decimal">'''), [
        ('p', 'Block', [
            ('p', 'Line', [
                ('p::marker', 'Inline', [
                    ('p::marker', 'Text', '0. ')])])])])


@assert_no_logs
def test_counters_7():
    # Test that counters are case-sensitive
    # See https://github.com/Kozea/WeasyPrint/pull/827
    assert_tree(parse_all('''
      <style>
        p { counter-increment: p 2 }
        p:before { content: counter(p) '.' counter(P); }
      </style>
      <p></p>
      <p style="counter-increment: P 3"></p>
      <p></p>'''), [
        ('p', 'Block', [
            ('p', 'Line', [
                ('p::before', 'Inline', [
                    ('p::before', 'Text', counter)])])])
        for counter in '2.0 2.3 4.3'.split()])


@assert_no_logs
def test_counters_8():
    assert_tree(parse_all('''
      <style>
        p:before { content: 'a'; display: list-item }
      </style>
      <p></p>
      <p></p>'''), 2 * [
        ('p', 'Block', [
          ('p::before', 'Block', [
            ('p::marker', 'Block', [
              ('p::marker', 'Line', [
                ('p::marker', 'Text', '• ')])]),
            ('p::before', 'Block', [
                ('p::before', 'Line', [
                    ('p::before', 'Text', 'a')])])])])])


@assert_no_logs
def test_counter_styles_1():
    assert_tree(parse_all('''
      <style>
        body { --var: 'Counter'; counter-reset: p -12 }
        p { counter-increment: p }
        p:nth-child(1):before { content: '-' counter(p, none) '-'; }
        p:nth-child(2):before { content: counter(p, disc); }
        p:nth-child(3):before { content: counter(p, circle); }
        p:nth-child(4):before { content: counter(p, square); }
        p:nth-child(5):before { content: counter(p); }
        p:nth-child(6):before { content: var(--var) ':' counter(p); }
        p:nth-child(7):before { content: counter(p) ':' var(--var); }
      </style>
      <p></p>
      <p></p>
      <p></p>
      <p></p>
      <p></p>
      <p></p>
      <p></p>
    '''), [
        ('p', 'Block', [
            ('p', 'Line', [
                ('p::before', 'Inline', [
                    ('p::before', 'Text', counter)])])])
        for counter in '--  •  ◦  ▪  -7 Counter:-6 -5:Counter'.split()])


@assert_no_logs
def test_counter_styles_2():
    assert_tree(parse_all('''
      <style>
        p { counter-increment: p }
        p::before { content: counter(p, decimal-leading-zero); }
      </style>
      <p style="counter-reset: p -1987"></p>
      <p></p>
      <p style="counter-reset: p -12"></p>
      <p></p>
      <p></p>
      <p></p>
      <p style="counter-reset: p -2"></p>
      <p></p>
      <p></p>
      <p></p>
      <p style="counter-reset: p 8"></p>
      <p></p>
      <p></p>
      <p style="counter-reset: p 98"></p>
      <p></p>
      <p></p>
      <p style="counter-reset: p 4134"></p>
      <p></p>
    '''), [
        ('p', 'Block', [
            ('p', 'Line', [
                ('p::before', 'Inline', [
                    ('p::before', 'Text', counter)])])])
        for counter in '''-1986 -1985  -11 -10 -9 -8  -1 00 01 02  09 10 11
                            99 100 101  4135 4136'''.split()])


@assert_no_logs
def test_counter_styles_3():
    render = HTML(string='')._ua_counter_style()[0].render_value
    assert [render(value, 'decimal-leading-zero') for value in [
        -1986, -1985,
        -11, -10, -9, -8,
        -1, 0, 1, 2,
        9, 10, 11,
        99, 100, 101,
        4135, 4136
    ]] == '''
        -1986 -1985  -11 -10 -9 -8  -1 00 01 02  09 10 11
        99 100 101  4135 4136
    '''.split()


@assert_no_logs
def test_counter_styles_4():
    render = HTML(string='')._ua_counter_style()[0].render_value
    assert [render(value, 'lower-roman') for value in [
        -1986, -1985,
        -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
        49, 50,
        389, 390,
        3489, 3490, 3491,
        4999, 5000, 5001
     ]] == '''
        -1986 -1985  -1 0 i ii iii iv v vi vii viii ix x xi xii
        xlix l  ccclxxxix cccxc  mmmcdlxxxix mmmcdxc mmmcdxci
        4999 5000 5001
    '''.split()


@assert_no_logs
def test_counter_styles_5():
    render = HTML(string='')._ua_counter_style()[0].render_value
    assert [render(value, 'upper-roman') for value in [
         -1986, -1985,
         -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
         49, 50,
         389, 390,
         3489, 3490, 3491,
         4999, 5000, 5001
    ]] == '''
        -1986 -1985  -1 0 I II III IV V VI VII VIII IX X XI XII
        XLIX L  CCCLXXXIX CCCXC  MMMCDLXXXIX MMMCDXC MMMCDXCI
        4999 5000 5001
    '''.split()


@assert_no_logs
def test_counter_styles_6():
    render = HTML(string='')._ua_counter_style()[0].render_value
    assert [render(value, 'lower-alpha') for value in [
        -1986, -1985,
        -1, 0, 1, 2, 3, 4,
        25, 26, 27, 28, 29,
        2002, 2003
    ]] == '''
        -1986 -1985  -1 0 a b c d  y z aa ab ac bxz bya
    '''.split()


@assert_no_logs
def test_counter_styles_7():
    render = HTML(string='')._ua_counter_style()[0].render_value
    assert [render(value, 'upper-alpha') for value in [
        -1986, -1985,
        -1, 0, 1, 2, 3, 4,
        25, 26, 27, 28, 29,
        2002, 2003
    ]] == '''
        -1986 -1985  -1 0 A B C D  Y Z AA AB AC BXZ BYA
    '''.split()


@assert_no_logs
def test_counter_styles_8():
    render = HTML(string='')._ua_counter_style()[0].render_value
    assert [render(value, 'lower-latin') for value in [
        -1986, -1985,
        -1, 0, 1, 2, 3, 4,
        25, 26, 27, 28, 29,
        2002, 2003
    ]] == '''
        -1986 -1985  -1 0 a b c d  y z aa ab ac bxz bya
    '''.split()


@assert_no_logs
def test_counter_styles_9():
    render = HTML(string='')._ua_counter_style()[0].render_value
    assert [render(value, 'upper-latin') for value in [
        -1986, -1985,
        -1, 0, 1, 2, 3, 4,
        25, 26, 27, 28, 29,
        2002, 2003
    ]] == '''
        -1986 -1985  -1 0 A B C D  Y Z AA AB AC BXZ BYA
    '''.split()


@assert_no_logs
def test_counter_styles_10():
    render = HTML(string='')._ua_counter_style()[0].render_value
    assert [render(value, 'georgian') for value in [
        -1986, -1985,
        -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
        20, 30, 40, 50, 60, 70, 80, 90, 100,
        200, 300, 400, 500, 600, 700, 800, 900, 1000,
        2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000,
        19999, 20000, 20001
    ]] == '''
        -1986 -1985  -1 0 ა
        ბ გ დ ე ვ ზ ჱ თ ი ია იბ
        კ ლ მ ნ ჲ ო პ ჟ რ
        ს ტ ჳ ფ ქ ღ ყ შ ჩ
        ც ძ წ ჭ ხ ჴ ჯ ჰ ჵ
        ჵჰშჟთ 20000 20001
    '''.split()


@assert_no_logs
def test_counter_styles_11():
    render = HTML(string='')._ua_counter_style()[0].render_value
    assert [render(value, 'armenian') for value in [
        -1986, -1985,
        -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
        20, 30, 40, 50, 60, 70, 80, 90, 100,
        200, 300, 400, 500, 600, 700, 800, 900, 1000,
        2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000,
        9999, 10000, 10001
    ]] == '''
        -1986 -1985  -1 0 Ա
        Բ Գ Դ Ե Զ Է Ը Թ Ժ ԺԱ ԺԲ
        Ի Լ Խ Ծ Կ Հ Ձ Ղ Ճ
        Մ Յ Ն Շ Ո Չ Պ Ջ Ռ
        Ս Վ Տ Ր Ց Ւ Փ Ք
        ՔՋՂԹ 10000 10001
    '''.split()


@assert_no_logs
@pytest.mark.parametrize('arguments, values', (
    ('cyclic "a" "b" "c"', ('a ', 'b ', 'c ', 'a ')),
    ('symbolic "a" "b"', ('a ', 'b ', 'aa ', 'bb ')),
    ('"a" "b"', ('a ', 'b ', 'aa ', 'bb ')),
    ('alphabetic "a" "b"', ('a ', 'b ', 'aa ', 'ab ')),
    ('fixed "a" "b"', ('a ', 'b ', '3 ', '4 ')),
    ('numeric "0" "1" "2"', ('1 ', '2 ', '10 ', '11 ')),
))
def test_counter_symbols(arguments, values):
    page, = render_pages('''
      <style>
        ol { list-style-type: symbols(%s) }
      </style>
      <ol>
        <li>abc</li>
        <li>abc</li>
        <li>abc</li>
        <li>abc</li>
      </ol>
    ''' % arguments)
    html, = page.children
    body, = html.children
    ol, = body.children
    li_1, li_2, li_3, li_4 = ol.children
    assert li_1.children[0].children[0].children[0].text == values[0]
    assert li_2.children[0].children[0].children[0].text == values[1]
    assert li_3.children[0].children[0].children[0].text == values[2]
    assert li_4.children[0].children[0].children[0].text == values[3]


@assert_no_logs
@pytest.mark.parametrize('style_type, values', (
    ('decimal', ('1. ', '2. ', '3. ', '4. ')),
    ('"/"', ('/', '/', '/', '/')),
))
def test_list_style_types(style_type, values):
    page, = render_pages('''
      <style>
        ol { list-style-type: %s }
      </style>
      <ol>
        <li>abc</li>
        <li>abc</li>
        <li>abc</li>
        <li>abc</li>
      </ol>
    ''' % style_type)
    html, = page.children
    body, = html.children
    ol, = body.children
    li_1, li_2, li_3, li_4 = ol.children
    assert li_1.children[0].children[0].children[0].text == values[0]
    assert li_2.children[0].children[0].children[0].text == values[1]
    assert li_3.children[0].children[0].children[0].text == values[2]
    assert li_4.children[0].children[0].children[0].text == values[3]


def test_counter_set():
    page, = render_pages('''
      <style>
        body { counter-reset: h2 0 h3 4; font-size: 1px }
        article { counter-reset: h2 2 }
        h1 { counter-increment: h1 }
        h1::before { content: counter(h1) }
        h2 { counter-increment: h2; counter-set: h3 3 }
        h2::before { content: counter(h2) }
        h3 { counter-increment: h3 }
        h3::before { content: counter(h3) }
      </style>
      <article>
        <h1></h1>
      </article>
      <article>
        <h2></h2>
        <h3></h3>
      </article>
      <article>
        <h3></h3>
      </article>
      <article>
        <h2></h2>
      </article>
      <article>
        <h3></h3>
        <h3></h3>
      </article>
      <article>
        <h1></h1>
        <h2></h2>
        <h3></h3>
      </article>
    ''')
    html, = page.children
    body, = html.children
    art_1, art_2, art_3, art_4, art_5, art_6 = body.children

    h1, = art_1.children
    assert h1.children[0].children[0].children[0].text == '1'

    h2, h3, = art_2.children
    assert h2.children[0].children[0].children[0].text == '3'
    assert h3.children[0].children[0].children[0].text == '4'

    h3, = art_3.children
    assert h3.children[0].children[0].children[0].text == '5'

    h2, = art_4.children
    assert h2.children[0].children[0].children[0].text == '3'

    h3_1, h3_2 = art_5.children
    assert h3_1.children[0].children[0].children[0].text == '4'
    assert h3_2.children[0].children[0].children[0].text == '5'

    h1, h2, h3 = art_6.children
    assert h1.children[0].children[0].children[0].text == '1'
    assert h2.children[0].children[0].children[0].text == '3'
    assert h3.children[0].children[0].children[0].text == '4'


def test_counter_multiple_extends():
    # Inspired by W3C failing test system-extends-invalid
    page, = render_pages('''
      <style>
        @counter-style a {
          system: extends b;
          prefix: a;
        }
        @counter-style b {
          system: extends c;
          suffix: b;
        }
        @counter-style c {
          system: extends b;
          pad: 2 c;
        }
        @counter-style d {
          system: extends d;
          prefix: d;
        }
        @counter-style e {
          system: extends unknown;
          prefix: e;
        }
        @counter-style f {
          system: extends decimal;
          symbols: a;
        }
        @counter-style g {
          system: extends decimal;
          additive-symbols: 1 a;
        }
      </style>
      <ol>
        <li style="list-style-type: a"></li>
        <li style="list-style-type: b"></li>
        <li style="list-style-type: c"></li>
        <li style="list-style-type: d"></li>
        <li style="list-style-type: e"></li>
        <li style="list-style-type: f"></li>
        <li style="list-style-type: g"></li>
        <li style="list-style-type: h"></li>
      </ol>
    ''')
    html, = page.children
    body, = html.children
    ol, = body.children
    li_1, li_2, li_3, li_4, li_5, li_6, li_7, li_8 = ol.children
    assert li_1.children[0].children[0].children[0].text == 'a1b'
    assert li_2.children[0].children[0].children[0].text == '2b'
    assert li_3.children[0].children[0].children[0].text == 'c3. '
    assert li_4.children[0].children[0].children[0].text == 'd4. '
    assert li_5.children[0].children[0].children[0].text == 'e5. '
    assert li_6.children[0].children[0].children[0].text == '6. '
    assert li_7.children[0].children[0].children[0].text == '7. '
    assert li_8.children[0].children[0].children[0].text == '8. '
