'''Pachube updater for SNAP

This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
Contributor: Synapse Wireless Inc., Huntsville, Alabama, 35806, USA
'''

import asyncore, socket
from StringIO import StringIO
from httplib import HTTPResponse
import logging

log = logging.getLogger('pachUpdater')

class FakeSocket(StringIO):
    '''Used to parse http response, since httplib lacks parse-from-string capability'''
    def makefile(self, *args, **kw):
        return self

def parse_http_response(resp_str):
    socket = FakeSocket(resp_str)
    response = HTTPResponse(socket)
    response.begin()

    return response

class pach_update_feed(asyncore.dispatcher):

    def __init__(self, key, feed_id, streams):
        '''Update the specified feed with 'streams' - a dict of {stream_id:value} pairs'''
        
        # Prep HTTP client data for pachube
        data = self.csv_str(streams)
        host = 'api.pachube.com'
        path = '/v2/feeds/%s' % feed_id
        
        log.debug("pach_update: feed %s %s" % (feed_id, str(streams)))

        try:
            asyncore.dispatcher.__init__(self)
            self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
            self.connect( (host, 80) )
        except:
            log.exception("Error connecting to pachube")
            self.close()
            return
        
        self.buffer = 'PUT %s HTTP/1.1\r\n'\
                      'Host: %s\r\n'\
                      'Accept-Encoding: identity\r\n'\
                      'Content-Length: %d\r\n'\
                      'Content-Type: text/plain\r\n'\
                      'X-PachubeApiKey: %s\r\n'\
                      '\r\n'\
                      '%s'  % (path, host, len(data), key, data)

    def csv_str(self, keyvals):
        s = ''
        for kv in keyvals.iteritems():
            s += '%s,%d\n' % kv

        return s        
            
    def handle_connect(self):
        pass

    def handle_close(self):
        self.close()

    def handle_read(self):
        resp_buf = self.recv(8192)
        try:
            resp = parse_http_response(resp_buf)
            if resp.status == 200:
                log.debug("Update successful")
            else:
                log.debug("Update failed with response code: %d" % resp.status)
        except:
            pass
        
        self.close()

    def writable(self):
        return (len(self.buffer) > 0)

    def handle_write(self):
        sent = self.send(self.buffer)
        #print "**Sent %d bytes: %s" % (len(self.buffer), self.buffer)
        self.buffer = self.buffer[sent:]

def test():
    print "Pachube Test!"
    key = '**** your key here ****'
    feed_id = '12345'  # Your Feed ID here
    pach_update_feed(key, feed_id, {'BeerFridge':40, 'Subzero':30} )

    asyncore.loop()
    
        
if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG, format='%(asctime)s:%(msecs)03d %(levelname)-8s %(name)-8s %(message)s', datefmt='%H:%M:%S')
    test()


