# -*- coding: utf-8 -*-
# (c) 2020 Matt Martz <matt@sivel.net>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import annotations

import pytest
from yaml import MappingNode, Mark, ScalarNode
from yaml.constructor import ConstructorError

import ansible.constants as C
from ansible.utils.display import Display
from ansible.parsing.yaml.constructor import AnsibleConstructor


@pytest.fixture
def dupe_node():
    tag = 'tag:yaml.org,2002:map'
    scalar_tag = 'tag:yaml.org,2002:str'
    mark = Mark(tag, 0, 0, 0, None, None)
    node = MappingNode(
        tag,
        [
            (
                ScalarNode(tag=scalar_tag, value='bar', start_mark=mark),
                ScalarNode(tag=scalar_tag, value='baz', start_mark=mark)
            ),
            (
                ScalarNode(tag=scalar_tag, value='bar', start_mark=mark),
                ScalarNode(tag=scalar_tag, value='qux', start_mark=mark)
            ),
        ],
        start_mark=mark
    )

    return node


class Capture:
    def __init__(self):
        self.called = False
        self.calls = []

    def __call__(self, *args, **kwargs):
        self.called = True
        self.calls.append((
            args,
            kwargs
        ))


def test_duplicate_yaml_dict_key_ignore(dupe_node, monkeypatch):
    monkeypatch.setattr(C, 'DUPLICATE_YAML_DICT_KEY', 'ignore')
    cap = Capture()
    monkeypatch.setattr(Display(), 'warning', cap)
    ac = AnsibleConstructor()
    ac.construct_mapping(dupe_node)
    assert not cap.called


def test_duplicate_yaml_dict_key_warn(dupe_node, monkeypatch):
    monkeypatch.setattr(C, 'DUPLICATE_YAML_DICT_KEY', 'warn')
    cap = Capture()
    monkeypatch.setattr(Display(), 'warning', cap)
    ac = AnsibleConstructor()
    ac.construct_mapping(dupe_node)
    assert cap.called
    expected = [
        (
            (
                'While constructing a mapping from tag:yaml.org,2002:map, line 1, column 1, '
                'found a duplicate dict key (bar). Using last defined value only.',
            ),
            {}
        )
    ]
    assert cap.calls == expected


def test_duplicate_yaml_dict_key_error(dupe_node, monkeypatch, mocker):
    monkeypatch.setattr(C, 'DUPLICATE_YAML_DICT_KEY', 'error')
    ac = AnsibleConstructor()
    pytest.raises(ConstructorError, ac.construct_mapping, dupe_node)
