import datetime as dt

import pytest


def test_datetime_without_timezone():
    from pseud.packer import Packer

    date = dt.datetime(2003, 9, 27, 9, 40, 1, 521290)
    assert Packer().unpackb(Packer().packb(date)) == date


def test_datetime_with_timezone():
    from pseud.packer import Packer

    date = dt.datetime(2003, 9, 27, 9, 40, 1, 521290, tzinfo=dt.timezone.utc)
    assert Packer().unpackb(Packer().packb(date)) == date


def test_packer_normal():
    from pseud.packer import Packer

    packer = Packer()
    assert packer.unpackb(packer.packb('data')) == 'data'


def test_packer_failure():
    import msgpack

    from pseud.packer import Packer

    packer = Packer()
    with pytest.raises(msgpack.ExtraData):
        packer.unpackb(b'--')


def test_packer_translation():
    import msgpack

    from pseud.packer import Packer

    class A:
        def __init__(self, arg):
            self.arg = arg

        def __eq__(self, other):
            return self.arg == other.arg

    table = {
        5: (A, lambda obj: msgpack.packb(obj.arg), lambda data: A(msgpack.unpackb(data)))
    }
    packer = Packer(translation_table=table)
    assert isinstance(packer.packb({b'key': A(b'--')}), bytes)
    assert packer.unpackb(packer.packb({'key': A(b'arg')})) == {'key': A(b'arg')}

    packer.register_ext_handler(
        0, A, lambda obj: b'overidden', lambda data: A(b'arbitrary')
    )
    # Checks pack_cache is valid
    assert packer.unpackb(packer.packb({'key': A(b'arg')})) != {'key': A(b'arg')}

    # Mostly for coverage of error paths.
    class B:
        pass

    # Two different error paths.
    with pytest.raises(TypeError):
        packer.packb(B())
    with pytest.raises(TypeError):
        packer.packb(B())

    dumb_packer = Packer()
    dumb_packer.unpackb(packer.packb(A('')))
