#------------------------------------------------------------------------------
# Copyright (c) 2018-2019, Nucleic Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file LICENSE, distributed with this software.
#------------------------------------------------------------------------------
"""Test the typed dictionary.


"""
import sys
import pytest

from atom.api import Atom, Dict, Int, atomdict


@pytest.fixture
def atom_dict():
    """Atom with different Dict members.

    """
    class DictAtom(Atom):
        untyped = Dict()
        keytyped = Dict(Int())
        valuetyped = Dict(value=Int())
        fullytyped = Dict(Int(), Int())
        untyped_default = Dict(default={1: 1})
        keytyped_default = Dict(Int(), default={1: 1})
        valuetyped_default = Dict(value=Int(), default={1: 1})
        fullytyped_default = Dict(Int(), Int(), default={1: 1})

    return DictAtom()


MEMBERS = ['untyped', 'keytyped', 'valuetyped', 'fullytyped',
           'untyped_default', 'keytyped_default', 'valuetyped_default',
           'fullytyped_default']


@pytest.mark.parametrize('member', MEMBERS)
def test_instance(atom_dict, member):
    """Test the repr.

    """
    assert isinstance(getattr(atom_dict, member), atomdict)


@pytest.mark.parametrize('member', MEMBERS)
def test_repr(atom_dict, member):
    """Test the repr.

    """
    d = getattr(atom_dict.__class__, member).default_value_mode[1]
    if not d:
        d = {i: i**2 for i in range(10)}
        setattr(atom_dict, member, d)
    assert repr(getattr(atom_dict, member)) == repr(d)


@pytest.mark.parametrize('member', MEMBERS)
def test_len(atom_dict, member):
    """Test the len.

    """
    d = getattr(atom_dict.__class__, member).default_value_mode[1]
    if not d:
        d = {i: i**2 for i in range(10)}
        setattr(atom_dict, member, d)
    assert len(getattr(atom_dict, member)) == len(d)


@pytest.mark.parametrize('member', MEMBERS)
def test_contains(atom_dict, member):
    """Test __contains__.

    """
    d = {i: i**2 for i in range(10)}
    setattr(atom_dict, member, d)
    assert 5 in getattr(atom_dict, member)
    del getattr(atom_dict, member)[5]
    assert 5 not in getattr(atom_dict, member)

@pytest.mark.parametrize('member', MEMBERS)
def test_keys(atom_dict, member):
    """Test the keys.

    """
    d = getattr(atom_dict.__class__, member).default_value_mode[1]
    if not d:
        d = {i: i**2 for i in range(10)}
        setattr(atom_dict, member, d)
    assert getattr(atom_dict, member).keys() == d.keys()


@pytest.mark.parametrize('member', MEMBERS)
def test_copy(atom_dict, member):
    """Test copy.

    """
    d = getattr(atom_dict.__class__, member).default_value_mode[1]
    if not d:
        d = {i: i**2 for i in range(10)}
        setattr(atom_dict, member, d)
    assert getattr(atom_dict, member).copy() == d


def test_setitem(atom_dict):
    """Test setting items.

    """
    atom_dict.untyped[''] = 1
    assert atom_dict.untyped[''] == 1

    atom_dict.keytyped[1] = ''
    assert atom_dict.keytyped[1] == ''
    with pytest.raises(TypeError):
        atom_dict.keytyped[''] = 1

    atom_dict.valuetyped[1] = 1
    assert atom_dict.valuetyped[1] == 1
    with pytest.raises(TypeError):
        atom_dict.valuetyped[''] = ''

    atom_dict.fullytyped[1] = 1
    assert atom_dict.fullytyped[1] == 1
    with pytest.raises(TypeError):
        atom_dict.fullytyped[''] = 1
    with pytest.raises(TypeError):
        atom_dict.fullytyped[1] = ''


def test_setdefault(atom_dict):
    """Test using setdefault.

    """

    assert atom_dict.untyped.setdefault('',  1) == 1
    assert atom_dict.untyped.setdefault('',  2) == 1
    assert atom_dict.untyped[''] == 1

    assert atom_dict.keytyped.setdefault(1, '') == ''
    assert atom_dict.keytyped[1] == ''
    with pytest.raises(TypeError):
        atom_dict.keytyped.setdefault('', 1)

    assert atom_dict.valuetyped.setdefault(1, 1) == 1
    assert atom_dict.valuetyped.setdefault(1, '') == 1
    assert atom_dict.valuetyped[1] == 1
    with pytest.raises(TypeError):
        atom_dict.valuetyped.setdefault(2, '')

    assert atom_dict.fullytyped.setdefault(1, 1) == 1
    assert atom_dict.fullytyped.setdefault(1, '') == 1
    assert atom_dict.fullytyped[1] == 1
    with pytest.raises(TypeError):
        atom_dict.fullytyped.setdefault('', 1)
    with pytest.raises(TypeError):
        atom_dict.fullytyped.setdefault(2, '')


def test_update(atom_dict):
    """Test update a dict.

    """
    atom_dict.untyped.update({'': 1})
    assert atom_dict.untyped[''] == 1
    atom_dict.untyped.update([('1', 1)])
    assert atom_dict.untyped['1'] == 1

    atom_dict.keytyped.update({1: 1})
    assert atom_dict.keytyped[1] == 1
    atom_dict.keytyped.update([(2, 1)])
    assert atom_dict.keytyped[1] == 1
    with pytest.raises(TypeError):
        atom_dict.keytyped.update({'': 1})

    atom_dict.valuetyped.update({1: 1})
    assert atom_dict.valuetyped[1] == 1
    atom_dict.valuetyped.update([(2, 1)])
    assert atom_dict.valuetyped[1] == 1
    with pytest.raises(TypeError):
        atom_dict.valuetyped.update({'': ''})

    atom_dict.fullytyped.update({1: 1})
    assert atom_dict.fullytyped[1] == 1
    atom_dict.fullytyped.update([(2, 1)])
    assert atom_dict.fullytyped[1] == 1
    with pytest.raises(TypeError):
        atom_dict.fullytyped.update({'': 1})
    with pytest.raises(TypeError):
        atom_dict.fullytyped.update({'': ''})

[((41, 1, 41, 43), 'pytest.mark.parametrize', 'pytest.mark.parametrize', ({(41, 25, 41, 33): '"""member"""', (41, 35, 41, 42): 'MEMBERS'}, {}), "('member', MEMBERS)", False, 'import pytest\n'), ((49, 1, 49, 43), 'pytest.mark.parametrize', 'pytest.mark.parametrize', ({(49, 25, 49, 33): '"""member"""', (49, 35, 49, 42): 'MEMBERS'}, {}), "('member', MEMBERS)", False, 'import pytest\n'), ((61, 1, 61, 43), 'pytest.mark.parametrize', 'pytest.mark.parametrize', ({(61, 25, 61, 33): '"""member"""', (61, 35, 61, 42): 'MEMBERS'}, {}), "('member', MEMBERS)", False, 'import pytest\n'), ((73, 1, 73, 43), 'pytest.mark.parametrize', 'pytest.mark.parametrize', ({(73, 25, 73, 33): '"""member"""', (73, 35, 73, 42): 'MEMBERS'}, {}), "('member', MEMBERS)", False, 'import pytest\n'), ((84, 1, 84, 43), 'pytest.mark.parametrize', 'pytest.mark.parametrize', ({(84, 25, 84, 33): '"""member"""', (84, 35, 84, 42): 'MEMBERS'}, {}), "('member', MEMBERS)", False, 'import pytest\n'), ((96, 1, 96, 43), 'pytest.mark.parametrize', 'pytest.mark.parametrize', ({(96, 25, 96, 33): '"""member"""', (96, 35, 96, 42): 'MEMBERS'}, {}), "('member', MEMBERS)", False, 'import pytest\n'), ((24, 18, 24, 24), 'atom.api.Dict', 'Dict', ({}, {}), '()', False, 'from atom.api import Atom, Dict, Int, atomdict\n'), ((28, 26, 28, 46), 'atom.api.Dict', 'Dict', (), '', False, 'from atom.api import Atom, Dict, Int, atomdict\n'), ((117, 9, 117, 33), 'pytest.raises', 'pytest.raises', ({(117, 23, 117, 32): 'TypeError'}, {}), '(TypeError)', False, 'import pytest\n'), ((122, 9, 122, 33), 'pytest.raises', 'pytest.raises', ({(122, 23, 122, 32): 'TypeError'}, {}), '(TypeError)', False, 'import pytest\n'), ((127, 9, 127, 33), 'pytest.raises', 'pytest.raises', ({(127, 23, 127, 32): 'TypeError'}, {}), '(TypeError)', False, 'import pytest\n'), ((129, 9, 129, 33), 'pytest.raises', 'pytest.raises', ({(129, 23, 129, 32): 'TypeError'}, {}), '(TypeError)', False, 'import pytest\n'), ((144, 9, 144, 33), 'pytest.raises', 'pytest.raises', ({(144, 23, 144, 32): 'TypeError'}, {}), '(TypeError)', False, 'import pytest\n'), ((150, 9, 150, 33), 'pytest.raises', 'pytest.raises', ({(150, 23, 150, 32): 'TypeError'}, {}), '(TypeError)', False, 'import pytest\n'), ((156, 9, 156, 33), 'pytest.raises', 'pytest.raises', ({(156, 23, 156, 32): 'TypeError'}, {}), '(TypeError)', False, 'import pytest\n'), ((158, 9, 158, 33), 'pytest.raises', 'pytest.raises', ({(158, 23, 158, 32): 'TypeError'}, {}), '(TypeError)', False, 'import pytest\n'), ((175, 9, 175, 33), 'pytest.raises', 'pytest.raises', ({(175, 23, 175, 32): 'TypeError'}, {}), '(TypeError)', False, 'import pytest\n'), ((182, 9, 182, 33), 'pytest.raises', 'pytest.raises', ({(182, 23, 182, 32): 'TypeError'}, {}), '(TypeError)', False, 'import pytest\n'), ((189, 9, 189, 33), 'pytest.raises', 'pytest.raises', ({(189, 23, 189, 32): 'TypeError'}, {}), '(TypeError)', False, 'import pytest\n'), ((191, 9, 191, 33), 'pytest.raises', 'pytest.raises', ({(191, 23, 191, 32): 'TypeError'}, {}), '(TypeError)', False, 'import pytest\n'), ((25, 24, 25, 29), 'atom.api.Int', 'Int', ({}, {}), '()', False, 'from atom.api import Atom, Dict, Int, atomdict\n'), ((27, 26, 27, 31), 'atom.api.Int', 'Int', ({}, {}), '()', False, 'from atom.api import Atom, Dict, Int, atomdict\n'), ((27, 33, 27, 38), 'atom.api.Int', 'Int', ({}, {}), '()', False, 'from atom.api import Atom, Dict, Int, atomdict\n'), ((29, 32, 29, 37), 'atom.api.Int', 'Int', ({}, {}), '()', False, 'from atom.api import Atom, Dict, Int, atomdict\n'), ((31, 34, 31, 39), 'atom.api.Int', 'Int', ({}, {}), '()', False, 'from atom.api import Atom, Dict, Int, atomdict\n'), ((31, 41, 31, 46), 'atom.api.Int', 'Int', ({}, {}), '()', False, 'from atom.api import Atom, Dict, Int, atomdict\n'), ((26, 32, 26, 37), 'atom.api.Int', 'Int', ({}, {}), '()', False, 'from atom.api import Atom, Dict, Int, atomdict\n'), ((30, 40, 30, 45), 'atom.api.Int', 'Int', ({}, {}), '()', False, 'from atom.api import Atom, Dict, Int, atomdict\n')]