from ln.backend.sql import SQLBackend
from ln.backend.exception import SeriesDoesNotExistError, SeriesTimeOrderError
from datetime import datetime, timedelta
import pytest
import numpy as np


@pytest.fixture
def backend():
    b = SQLBackend('sqlite://')
    int_config = dict(
        name='int',
        type='int32',
        reduction='sum',
        interpolation='linear',
        description='Integer counter',
        unit='',
        metadata=''
    )
    b.create_series(**int_config)
    float_config = dict(
        name='float',
        type='float32',
        reduction='mean',
        interpolation='linear',
        description='Float counter',
        unit='',
        metadata=''
    )
    b.create_series(**float_config)
    array_config = dict(
        name='array',
        type='float32[4]',
        reduction='mean',
        interpolation='linear',
        description='Array',
        unit='',
        metadata=''
    )
    b.create_series(**array_config)
    blob_config = dict(
        name='blob',
        type='blob:text/plain',
        reduction='closest',
        interpolation='none',
        description='BLOB',
        unit='',
        metadata=''
    )
    b.create_series(**blob_config)
    return b


def test_add_doesnotexist(backend):
    b = backend
    with pytest.raises(SeriesDoesNotExistError):
        b.add_data('doesnotexist', datetime.now(), 1)


def test_get_doesnotexist(backend):
    b = backend
    with pytest.raises(SeriesDoesNotExistError):
        b.get_data('doesnotexist')


def test_get_last(backend):
    b = backend
    times = []
    for i in range(10):
        times.append(datetime.now())
        b.add_data('int', times[-1], i)

    db_times, db_values, next_seq = b.get_data('int')
    assert len(db_times) == 1
    assert len(db_values) == 1
    assert times[-1] == db_times[0]
    assert 9 == db_values[0]
    assert next_seq is None


def test_get_limit(backend):
    b = backend
    times = []
    for i in range(10):
        times.append(datetime.now())
        b.add_data('int', times[-1], i)

    db_times, db_values, next_seq = b.get_data('int', 1, 2)
    assert len(db_times) == 2
    assert len(db_values) == 2
    assert next_seq == 3
    assert times[1:3] == db_times
    assert [1, 2] == db_values

    db_times, db_values, next_seq = b.get_data('int', 9, 2)
    assert len(db_times) == 1
    assert len(db_values) == 1
    assert next_seq is None
    assert times[-1] == db_times[0]
    assert [9] == db_values


def test_add_int(backend):
    b = backend
    times = []
    for i in range(10):
        times.append(datetime.now())
        b.add_data('int', times[-1], i)

    db_times, db_values, next_seq = b.get_data('int', 0)
    assert times == db_times
    assert list(range(10)) == db_values
    assert next_seq is None


def test_add_float(backend):
    b = backend
    times = []
    for i in range(10):
        times.append(datetime.now())
        b.add_data('float', times[-1], i + 0.5)

    db_times, db_values, next_seq = b.get_data('float', 0)
    assert times == db_times
    assert [i + 0.5 for i in range(10)] == db_values
    assert next_seq is None


def test_add_array(backend):
    b = backend
    times = []
    values = []
    for i in range(10):
        times.append(datetime.now())
        values.append(np.array(range(4)) * i)
        b.add_data('array', times[-1], values[-1])

    db_times, db_values, next_seq = b.get_data('array', 0)
    assert times == db_times
    assert np.array_equal(np.array(values), np.array(db_values))
    assert next_seq is None


def test_add_blob(backend):
    b = backend
    times = []
    values = []
    for i in range(10):
        times.append(datetime.now())
        values.append(b'-' * 10)
        b.add_data('blob', times[-1], values[-1])

    db_times, db_values, next_seq = b.get_data('blob', 0)
    assert times == db_times
    assert values == db_values
    assert next_seq is None


def test_add_wrong_order(backend):
    b = backend

    now = datetime.now()
    b.add_data('int', now, 1)
    with pytest.raises(SeriesTimeOrderError):
        b.add_data('int', now - timedelta(hours=1), 2)

@@ -63,16 +63,30 @@
 n import
+ BadTypeError,
  SeriesD
@@ -98,24 +98,30 @@
 tExistError,
+ %5C%0A   
  SeriesTimeO
@@ -2622,32 +2622,40 @@
 e.now())%0A       
+ index =
  b.add_data('int
@@ -2662,32 +2662,58 @@
 ', times%5B-1%5D, i)
+%0A        assert index == i
 %0A%0A    db_times, 
@@ -2974,32 +2974,40 @@
 e.now())%0A       
+ index =
  b.add_data('flo
@@ -3030,16 +3030,42 @@
 i + 0.5)
+%0A        assert index == i
 %0A%0A    db
@@ -3411,32 +3411,40 @@
 4)) * i)%0A       
+ index =
  b.add_data('arr
@@ -3462,32 +3462,58 @@
 -1%5D, values%5B-1%5D)
+%0A        assert index == i
 %0A%0A    db_times, 
@@ -3849,32 +3849,40 @@
 -' * 10)%0A       
+ index =
  b.add_data('blo
@@ -3907,16 +3907,42 @@
 ues%5B-1%5D)
+%0A        assert index == i
 %0A%0A    db
@@ -4228,32 +4228,32 @@
 imeOrderError):%0A
-
         b.add_da
@@ -4287,12 +4287,148 @@
 ours=1), 2)%0A
+%0A%0Adef test_add_bad_type(backend):%0A    b = backend%0A    with pytest.raises(BadTypeError):%0A        b.add_data('int', datetime.now, %5B1, 2%5D)%0A

Test the return value of add_data() and test detection of bad types.