# idigi_comm.py
# Nathan Fritsche
#
import os
import sys
import string
import httplib
import time
import base64
#import idigi_parse
import xml.sax
from xml.sax import handler, make_parser, parseString
# TODO: delete from debug version...
from msvcrt import getch

class WebServiceComm:

    #sci_sm_header = "<sci_request version=\"1.0\"><send_message><targets>"
    sci_sm_header_refresh = "<sci_request version=\"1.0\">\
                    <send_message cache=\"false\"><targets>"
    sci_sm_header_cached = "<sci_request version=\"1.0\">\
                    <send_message cache=\"true\"><targets>"
    sci_sm_tail = "</send_message></sci_request>"

    rci_query_cb = "<rci_request version=\"1.1\">" + \
                    "<do_command target=\"rci_callback_example\">" + \
                    "Hello,NWF</do_command></rci_request>"

    def __init__(self, idigiInfo):
        self.lastStatusCode = 0
        self.lastStatusMsg = ""
        self.idigiInfo = idigiInfo
        
    def _make_target_string(self, targetList):
        try:
            if ((type(targetList) == list)):
                iNumTargets = len(targetList)
                targetString = "<targets>"
                if (iNumTargets > 0):
                    for devstr in targetList:
                        tstr = "<device id=\"" + "%s" + "\"/>"
                        targetString += tstr
                retString = targetString + "</targets>"
            else:
                retString = ("<device id=\"" + "%s" + "\"/></targets>") % \
                                                                targetList
        except Exception, ex:
            return "ERROR"
        else:
            return retString

    def send_msg(self, destUrl, method, msg=""):
        try:
            idigiaddr = self.idigiInfo[0]
            port = int(self.idigiInfo[1])
            uname = self.idigiInfo[2]
            pword = self.idigiInfo[3]

            print idigiaddr
            auth = base64.encodestring("%s:%s" % (uname, pword))[:-1]
            idigi_conn = httplib.HTTP(idigiaddr.strip("http://"), port)

            idigi_conn.putrequest(method, destUrl)

            # add the authorization string into the HTTP header
            idigi_conn.putheader("Authorization", "Basic %s" % auth)
            idigi_conn.putheader("Content-type", "text/xml; \
                                            charset=\"UTF-8\"")
            idigi_conn.putheader("Content-length", "%d" % len(msg))
            idigi_conn.endheaders()

            idigi_conn.send(msg)

            # get the response
            statuscode, statusmessage, header = idigi_conn.getreply()
            self.lastStatusCode = statuscode
            self.lastStatusMsg = statusmessage
            idigiresp = idigi_conn.getfile().read()
            #print (statuscode, statusmessage, header)
        except Exception, ex:
            print "send_msg: exception= ", ex
            return "ERROR"
        else:
            #print "send_msg: exiting, returning: ", idigiresp
            return idigiresp

    # REQUIRED: "target in targetList MUST be in the form:
    # [cwid, cwid, cwid, ...]
    # If sending to one target, pass in [cwid]
    # Builds rci message, sends and returns the XML response
    def query_state(self, targetList, refresh=True, stategroup=""):
        try:
            targetStr = self._make_target_string(targetList)
            if (targetStr != "ERROR"):
                if stategroup == "":
                    rciXml = \
                        "<rci_request version=\"1.1\">\
                        <query_state></query_state></rci_request>"
                else:
                    rciXml = \
                        "<rci_request version=\"1.1\">\
                        <query_state>%s</query_state></rci_request>" % \
                        (stategroup)

                if (refresh):
                    scimsg = "%s%s%s%s" % \
                             (WebServiceComm.sci_sm_header_refresh, \
                                     targetStr, rciXml, \
                                       WebServiceComm.sci_sm_tail)
                else:
                    scimsg = "%s%s%s%s" % \
                             (WebServiceComm.sci_sm_header_cached, \
                                     targetStr, rciXml, \
                                       WebServiceComm.sci_sm_tail)

                resp = self.send_msg("/ws/sci", "POST", str(scimsg))
        except Exception, ex:
            print "query_state: exception= ", ex
            return "ERROR"
        else:
            return resp

    # build the rci message, sends and returns the XML response       
    # request= "UploadFw", "SendUpdateCmd", "DeleteFwFile"
    def send_rci_request(self, targetList, request, fileName="", encFile=""):
        print "send_rci_request: enter"
        try:
            if (request == "GetDir"):
                rciString = "<rci_request version=\"1.1\">"\
                            "<do_command target=\"file_system\">"\
                            "<ls dir=\"/WEB/mesh/\"/>"\
                            "</do_command>"\
                            "</rci_request>"
            if (request == "UploadFw"):
                rciString = "<rci_request version=\"1.1\">"\
                            "<do_command target=\"file_system\">"\
                            "<put_file encode=\"base64\" name=\"/WEB/mesh/"\
                                + fileName + "\">"\
                            "<data encode=\"base64\">" + encFile + \
                                                            "</data>"\
                            "</put_file>"\
                            "</do_command>"\
                            "</rci_request>"
            elif (request == "SendUpdateCmd"):
                rciString = "<rci_request version=\"1.1\">"\
                            "<do_command target=\"zigbee\">"\
                            "<fw_update file=\"WEB/mesh/" + fileName + "\"/>"\
                            "</do_command>"\
                            "</rci_request>"
            elif (request == "DeleteFile"):
                rciString = "<rci_request version=\"1.1\">"\
                            "<do_command target=\"file_system\">"\
                            "<rm name=\"/WEB/mesh/" + fileName + "\"/>"\
                            "</do_command>"\
                            "</rci_request>"
            elif (request == "SendToCallback"):
                rciString = WebServiceComm.rci_query_cb
            elif (request == "UploadFile"):
                rciString = "<rci_request version=\"1.1\">"\
                            "<do_command target=\"file_system\">"\
                            "<put_file encode=\"base64\" name=\"/WEB/python/"\
                                + fileName + "\">"\
                            "<data encode=\"base64\">" + encFile + \
                                                            "</data>"\
                            "</put_file>"\
                            "</do_command>"\
                            "</rci_request>"
                
            sci_data = "<sci_request version=\"1.1\">"\
                        "<send_message cache=\"false\">"\
                        "<targets>"\
                        "<device id=\"%s\"/>"\
                        "</targets>"\
                        "%s"\
                        "</send_message>"\
                        "</sci_request>" % (targetList, rciString)
            
            resp = self.send_msg("/ws/sci", "POST", sci_data)
            #resp = self.send_msg("10.50.1.1
            print "\n"
            print resp
        except Exception, ex:
            print "send_rci_request: exception= ", ex
            return "ERROR"
        else:
            return resp

    # Note: this function uses the SAX parser CwidListBuilder_FromXml
    def _get_cwid_list_from_device_core(self):
        try:
            print "_get_cwid_list_from_device_core: enter "
            # GET DeviceCore to get list of all devices
            xmldata = self.iDigiCom.send_msg("/ws/DeviceCore", "GET")
            print "_get_cwid_list_from_device_core: xmldata = ", xmldata
            # parse xml to give me a list with only cwids 
            retParsed = idigi_parse.parse_cwid_from_xml(xmldata)
            for dev in retParsed:
                print "retParsed: ", dev
        except:
            return False
        else:
            return retParsed

# past this list to string builder to make an SCI/RCI
# formatted target string
#targetString = self.iDigiCom.build_target_str_from_list(cwidList)

    def build_target_str_from_list(self, cwidList):
        try:
            print "build_target_str_from_list: enter"
            tString = self._make_target_string(cwidList)
        except:
            tString = "ERROR"
        print "build_target_str_from_list: returning ", tString
        return tString
