import nilmdb

from nose.tools import *
from nose.tools import assert_raises
import distutils.version
import json
import itertools 
import os
import shutil
import sys
import cherrypy
import threading
import urllib2
from urllib2 import urlopen, HTTPError
import Queue
import cStringIO

from test_helpers import *

from nilmdb.layout import *

class TestLayouts(object):
    # Some nilmdb.layout tests.  Not complete, just fills in missing
    # coverage.
    def test_layouts(self):
        x = nilmdb.layout.named["PrepData"].description()

    def test_parsing(self):
        # invalid layout
        with assert_raises(TypeError) as e:
            parser = Parser("NoSuchLayout")

        # too little data
        parser = Parser("PrepData")
        data = ( "1234567890.000000 1.1 2.2 3.3 4.4 5.5\n" +
                 "1234567890.100000 1.1 2.2 3.3 4.4 5.5\n")
        with assert_raises(ParserError) as e:
            parser.parse(data)
        in_("index error", str(e.exception))

        # too much data
        parser = Parser("PrepData")
        data = ( "1234567890.000000 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9\n" +
                 "1234567890.100000 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9\n")
        with assert_raises(ParserError) as e:
            parser.parse(data)
        in_("index error", str(e.exception))

        # just right
        parser = Parser("PrepData")
        data = ( "1234567890.000000 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8\n" +
                 "1234567890.100000 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8\n")
        parser.parse(data)
        eq_(parser.min_timestamp, 1234567890000000)
        eq_(parser.max_timestamp, 1234567890100000)
        
        # try RawData too, with clamping
        parser = Parser("RawData")
        data = ( "1234567890.000000 1 2 3 4 5 6\n" +
                 "1234567890.100000 1 2 3 4 5 6\n" )
        parser.parse(data)

        # pass an instantiated class
        parser = Parser(RawNotchedData())
        data = ( "1234567890.000000 1 2 3 4 5 6 7 8 9\n" +
                 "1234567890.100000 1 2 3 4 5 6 7 8 9\n" )
        parser.parse(data)

        # using generic parse function, rawdata
        class CrappyLayout(RawData):
            pass
        x = CrappyLayout()
        x.fields = x.fields + [("foo", "float32")]
        x.parse = super(RawData, x).parse
        parser = Parser(x)
        data = ( "1234567890.000000 1 2 3 4 5 6 1.1\n" +
                 "1234567890.100000 1 2 3 4 5 6 2.2\n" )
        parser.parse(data)

        # some invalid type
        x.fields = x.fields + [("faketype", "faketype")]
        parser = Parser(x)
        data = ( "1234567890.000000 1 2 3 4 5 6 1.1 fake\n" +
                 "1234567890.100000 1 2 3 4 5 6 2.2 fake\n" )
        with assert_raises(ParserError) as e:
            parser.parse(data)
        in_("can't parse type", str(e.exception))

        # non-monotonic
        parser = Parser("RawData")
        data = ( "1234567890.100000 1 2 3 4 5 6\n" +
                 "1234567890.000000 1 2 3 4 5 6\n" )
        with assert_raises(ParserError) as e:
            parser.parse(data)
        in_("not monotonically increasing", str(e.exception))

        # RawData with values out of bounds
        parser = Parser("RawData")
        data = ( "1234567890.000000 1 2 3 4 500000 6\n" +
                 "1234567890.100000 1 2 3 4 5 6\n" )
        with assert_raises(ParserError) as e:
            parser.parse(data)
        in_("data out of range", str(e.exception))

        # Empty data should work but is useless
        parser = Parser("RawData")
        data = ""
        parser.parse(data)
        assert(parser.min_timestamp is None)
        assert(parser.max_timestamp is None)
