from tg import jsonify
from datetime import datetime
from decimal import Decimal
from nose.tools import raises
from nose import SkipTest
from webob.multidict import MultiDict
import json

class Foo(object):
    def __init__(self, bar):
        self.bar = bar

class Bar(object):
    def __init__(self, bar):
        self.bar = bar
    def __json__(self):
        return 'bar-%s' % self.bar

class Baz(object):
    pass

def test_string():
    d = "string"
    encoded = jsonify.encode(d)
    assert encoded == '"string"'

@raises(jsonify.JsonEncodeError)
def test_list():
    d = ['a', 1, 'b', 2]
    encoded = jsonify.encode(d)
    assert encoded == '["a", 1, "b", 2]'

@raises(jsonify.JsonEncodeError)
def test_list_iter():
    d = list(range(3))
    encoded = jsonify.encode_iter(d)
    assert ''.join(jsonify.encode_iter(d)) == jsonify.encode(d)

def test_dictionary():
    d = {'a': 1, 'b': 2}
    encoded = jsonify.encode(d)
    expected = json.dumps(json.loads('{"a": 1, "b": 2}'))
    assert encoded == expected

@raises(jsonify.JsonEncodeError)
def test_nospecificjson():
    b = Baz()
    try:
        encoded = jsonify.encode(b)
    except TypeError as e:
        pass
    assert  "is not JSON serializable" in e.message 

def test_exlicitjson():
    b = Bar("bq")
    encoded = jsonify.encode(b)
    assert encoded == '"bar-bq"'

@raises(jsonify.JsonEncodeError)
def test_exlicitjson_in_list():
    b = Bar("bq")
    d = [b]
    encoded = jsonify.encode(d)
    assert encoded == '["bar-bq"]'

def test_exlicitjson_in_dict():
    b = Bar("bq")
    d = {"b": b}
    encoded = jsonify.encode(d)
    assert encoded == '{"b": "bar-bq"}'

def test_datetime():
    d = datetime.utcnow()
    encoded = jsonify.encode({'date':d})
    assert str(d.year) in encoded, (str(d), encoded)

def test_decimal():
    d = Decimal('3.14')
    encoded = jsonify.encode({'dec':d})
    assert '3.14' in encoded

def test_objectid():
    try:
        from bson import ObjectId
    except:
        raise SkipTest()

    d = ObjectId('507f1f77bcf86cd799439011')
    encoded = jsonify.encode({'oid':d})
    assert encoded == '{"oid": "%s"}' % d, encoded

def test_multidict():
    d = MultiDict({'v':1})
    encoded = jsonify.encode({'md':d})
    assert encoded == '{"md": {"v": 1}}', encoded

