"""Test the new matching."""

from pytest import raises
from db import SpacialObject
from match import match

q = SpacialObject.objects()
objects = 12

for x in range(objects):
    SpacialObject(name='Object %d' % x).save()


class NotifyException(Exception):
    pass


class TestPlayer:
    def notify(self, string):
        self.string = string
        raise NotifyException()


def test_all():
    m = match()
    assert m.query.all() == q.all()


def test_name():
    m = match('Object')
    assert len(m.query.all()) == objects


def test_with_indices():
    m = match('2.obj')
    assert len(m) == 1
    assert m.query.first().id == 3  # Chargen has id 0.
    assert not len(match('.'))
    m = match('-.obj')
    assert m.query.first() is q[-1]


def test_empty():
    assert not len(match('asdf.obj'))
    assert not len(match(':'))
    assert not len(match('#5'))


def test_numerical_match():
    m = match('#4', allow_ids=True)
    assert len(m) == 1
    assert m.query.first() == q.get(4)


def test_localise():
    l = SpacialObject(name='location')
    p = SpacialObject(name='player', location=l)
    t = SpacialObject(name='thing', location=l)
    l.save()
    p.save()
    t.save()
    m = match('thing', localise=p)
    assert len(m) == 1
    assert m.query.first() is t
    m = match('#%d' % t.id, localise=p, allow_ids=True)
    assert len(m) == 1
    assert m.query.first() is t


def test_get_single_match():
    m = match('obj')
    p = TestPlayer()
    expected = (
        'Multiple objects were found matching {0.string}. Please '
        'be more specific.'
    )
    expected = expected.format(m)
    with raises(NotifyException):
        m.get_single_match(p)
    assert p.string == expected
    m = match('fails')
    with raises(NotifyException):
        m.get_single_match(p)
    assert p.string == 'Nothing found matching {0.string}.'.format(m)
