from __future__ import print_function

from lxml import etree
import requests
import re
from urlparse import urlparse
from pprint import pprint

from utils.xml import xml_to_dict, search_xml

from state import StateVariable
from action import Action

class Service(object):
    def __init__(self, device, svc_data):
        self.device = device
        for key in svc_data:
            setattr(self, key, svc_data[key])
        self.variables = {}
        self.actions = {}
        self.get_info()

    def host(self):
        return self.device.host

    def url(self):
        return self.device.url(self.controlURL)

    def make_action(self, action):
        return "{}#{}".format(self.serviceType, action)

    def get_info(self):
        req = requests.get(self.device.url(self.SCPDURL))
        if req.status_code != 200:
            return
        self.info = etree.fromstring(req.content)
#        print(etree.tostring(self.info, pretty_print=True))

        for state in search_xml(self.info, "serviceStateTable/stateVariable", raw=True):
            var = StateVariable(xml_to_dict(state))
            self.variables[var.name] = var
        for act in search_xml(self.info, 'actionList/action', raw=True):
            action = Action(self, xml_to_dict(act))
            action.resolve_arguments(self.variables)
            self.actions[action.name] = action
            setattr(self, action.name, action)

#        print(self.variables.keys())
#        print(self.actions.keys())



    def dump(self):
        """ Return a formatted string suitable for displaying on stdout. """
        svc_str = """
    Service ID:           {}
            Type:         {}
            control URL:  {}
            eventSubURL:  {}

    Actions
""".format(self.serviceId, self.serviceType, 
                   self.controlURL, self.eventSubURL)

        for act in sorted(self.actions.keys()):
            svc_str += self.actions[act].full_str()

        return svc_str

"""
<scpd xmlns="urn:schemas-upnp-org:service-1-0">
  <specVersion>
    <major>1</major>
    <minor>0</minor>
  </specVersion>

  <serviceStateTable>
    <stateVariable sendEvents="yes">
      <name>SourceProtocolInfo</name>
      <dataType>string</dataType>
    </stateVariable>
    <stateVariable sendEvents="yes">
      <name>SinkProtocolInfo</name>
      <dataType>string</dataType>
    </stateVariable>
    <stateVariable sendEvents="yes">
      <name>CurrentConnectionIDs</name>
      <dataType>string</dataType>
    </stateVariable>
    <stateVariable sendEvents="no">
      <name>A_ARG_TYPE_ConnectionStatus</name>
      <dataType>string</dataType>
      <allowedValueList>
        <allowedValue>OK</allowedValue>
        <allowedValue>ContentFormatMismatch</allowedValue>
        <allowedValue>InsufficientBandwidth</allowedValue>
        <allowedValue>UnreliableChannel</allowedValue>
        <allowedValue>Unknown</allowedValue>
      </allowedValueList>
    </stateVariable>
    <stateVariable sendEvents="no">
      <name>A_ARG_TYPE_ConnectionManager</name>
      <dataType>string</dataType>
    </stateVariable>
    <stateVariable sendEvents="no">
      <name>A_ARG_TYPE_Direction</name>
      <dataType>string</dataType>
      <allowedValueList>
        <allowedValue>Input</allowedValue>
        <allowedValue>Output</allowedValue>
      </allowedValueList>
    </stateVariable>
    <stateVariable sendEvents="no">
      <name>A_ARG_TYPE_ProtocolInfo</name>
      <dataType>string</dataType>
    </stateVariable>
    <stateVariable sendEvents="no">
      <name>A_ARG_TYPE_ConnectionID</name>
      <dataType>i4</dataType>
    </stateVariable>
    <stateVariable sendEvents="no">
      <name>A_ARG_TYPE_AVTransportID</name>
      <dataType>i4</dataType>
    </stateVariable>
    <stateVariable sendEvents="no">
      <name>A_ARG_TYPE_RcsID</name>
      <dataType>i4</dataType>
    </stateVariable>
  </serviceStateTable>
  <actionList>
    <action>
      <name>GetProtocolInfo</name>
      <argumentList>
        <argument>
          <name>Source</name>
          <direction>out</direction>
          <relatedStateVariable>SourceProtocolInfo</relatedStateVariable>
        </argument>
        <argument>
          <name>Sink</name>
          <direction>out</direction>
          <relatedStateVariable>SinkProtocolInfo</relatedStateVariable>
        </argument>
      </argumentList>
    </action>
    <action>
      <name>GetCurrentConnectionIDs</name>
      <argumentList>
        <argument>
          <name>ConnectionIDs</name>
          <direction>out</direction>
          <relatedStateVariable>CurrentConnectionIDs</relatedStateVariable>
        </argument>
      </argumentList>
    </action>
    <action>
      <name>GetCurrentConnectionInfo</name>
      <argumentList>
        <argument>
          <name>ConnectionID</name>
          <direction>in</direction>
          <relatedStateVariable>A_ARG_TYPE_ConnectionID</relatedStateVariable>
        </argument>
        <argument>
          <name>RcsID</name>
          <direction>out</direction>
          <relatedStateVariable>A_ARG_TYPE_RcsID</relatedStateVariable>
        </argument>
        <argument>
          <name>AVTransportID</name>
          <direction>out</direction>
          <relatedStateVariable>A_ARG_TYPE_AVTransportID</relatedStateVariable>
        </argument>
        <argument>
          <name>ProtocolInfo</name>
          <direction>out</direction>
          <relatedStateVariable>A_ARG_TYPE_ProtocolInfo</relatedStateVariable>
        </argument>
        <argument>
          <name>PeerConnectionManager</name>
          <direction>out</direction>
          <relatedStateVariable>A_ARG_TYPE_ConnectionManager</relatedStateVariable>
        </argument>
        <argument>
          <name>PeerConnectionID</name>
          <direction>out</direction>
          <relatedStateVariable>A_ARG_TYPE_ConnectionID</relatedStateVariable>
        </argument>
        <argument>
          <name>Direction</name>
          <direction>out</direction>
          <relatedStateVariable>A_ARG_TYPE_Direction</relatedStateVariable>
        </argument>
        <argument>
          <name>Status</name>
          <direction>out</direction>
          <relatedStateVariable>A_ARG_TYPE_ConnectionStatus</relatedStateVariable>
        </argument>
      </argumentList>
    </action>
  </actionList>
</scpd>
"""
from __future__ import print_function

from lxml import etree
import requests
import re
from urlparse import urlparse
from pprint import pprint

from utils.xml import xml_to_dict, search_xml

from state import StateVariable
from action import Action

class Service(object):
    def __init__(self, device, svc_data):
        self.device = device
        for key in svc_data:
            setattr(self, key, svc_data[key])
        self.variables = {}
        self.actions = {}
        self.get_info()

    def host(self):
        return self.device.host

    def url(self):
        return self.device.url(self.controlURL)

    def make_action(self, action):
        return "{}#{}".format(self.serviceType, action)

    def get_info(self):
        req = requests.get(self.device.url(self.SCPDURL))
        if req.status_code != 200:
            return
        self.info = etree.fromstring(req.content)
#        print(etree.tostring(self.info, pretty_print=True))

        for state in search_xml(self.info, "serviceStateTable/stateVariable", raw=True):
            var = StateVariable(xml_to_dict(state))
            self.variables[var.name] = var
        for act in search_xml(self.info, 'actionList/action', raw=True):
            action = Action(self, xml_to_dict(act))
            action.resolve_arguments(self.variables)
            self.actions[action.name] = action
            setattr(self, action.name, action)

#        print(self.variables.keys())
#        print(self.actions.keys())



    def dump(self):
        """ Return a formatted string suitable for displaying on stdout. """
        svc_str = """
    Service ID:           {}
            Type:         {}
            control URL:  {}
            eventSubURL:  {}

    Actions
""".format(self.serviceId, self.serviceType, 
                   self.controlURL, self.eventSubURL)

        for act in sorted(self.actions.keys()):
            svc_str += self.actions[act].full_str()

        return svc_str

"""
<scpd xmlns="urn:schemas-upnp-org:service-1-0">
  <specVersion>
    <major>1</major>
    <minor>0</minor>
  </specVersion>

  <serviceStateTable>
    <stateVariable sendEvents="yes">
      <name>SourceProtocolInfo</name>
      <dataType>string</dataType>
    </stateVariable>
    <stateVariable sendEvents="yes">
      <name>SinkProtocolInfo</name>
      <dataType>string</dataType>
    </stateVariable>
    <stateVariable sendEvents="yes">
      <name>CurrentConnectionIDs</name>
      <dataType>string</dataType>
    </stateVariable>
    <stateVariable sendEvents="no">
      <name>A_ARG_TYPE_ConnectionStatus</name>
      <dataType>string</dataType>
      <allowedValueList>
        <allowedValue>OK</allowedValue>
        <allowedValue>ContentFormatMismatch</allowedValue>
        <allowedValue>InsufficientBandwidth</allowedValue>
        <allowedValue>UnreliableChannel</allowedValue>
        <allowedValue>Unknown</allowedValue>
      </allowedValueList>
    </stateVariable>
    <stateVariable sendEvents="no">
      <name>A_ARG_TYPE_ConnectionManager</name>
      <dataType>string</dataType>
    </stateVariable>
    <stateVariable sendEvents="no">
      <name>A_ARG_TYPE_Direction</name>
      <dataType>string</dataType>
      <allowedValueList>
        <allowedValue>Input</allowedValue>
        <allowedValue>Output</allowedValue>
      </allowedValueList>
    </stateVariable>
    <stateVariable sendEvents="no">
      <name>A_ARG_TYPE_ProtocolInfo</name>
      <dataType>string</dataType>
    </stateVariable>
    <stateVariable sendEvents="no">
      <name>A_ARG_TYPE_ConnectionID</name>
      <dataType>i4</dataType>
    </stateVariable>
    <stateVariable sendEvents="no">
      <name>A_ARG_TYPE_AVTransportID</name>
      <dataType>i4</dataType>
    </stateVariable>
    <stateVariable sendEvents="no">
      <name>A_ARG_TYPE_RcsID</name>
      <dataType>i4</dataType>
    </stateVariable>
  </serviceStateTable>
  <actionList>
    <action>
      <name>GetProtocolInfo</name>
      <argumentList>
        <argument>
          <name>Source</name>
          <direction>out</direction>
          <relatedStateVariable>SourceProtocolInfo</relatedStateVariable>
        </argument>
        <argument>
          <name>Sink</name>
          <direction>out</direction>
          <relatedStateVariable>SinkProtocolInfo</relatedStateVariable>
        </argument>
      </argumentList>
    </action>
    <action>
      <name>GetCurrentConnectionIDs</name>
      <argumentList>
        <argument>
          <name>ConnectionIDs</name>
          <direction>out</direction>
          <relatedStateVariable>CurrentConnectionIDs</relatedStateVariable>
        </argument>
      </argumentList>
    </action>
    <action>
      <name>GetCurrentConnectionInfo</name>
      <argumentList>
        <argument>
          <name>ConnectionID</name>
          <direction>in</direction>
          <relatedStateVariable>A_ARG_TYPE_ConnectionID</relatedStateVariable>
        </argument>
        <argument>
          <name>RcsID</name>
          <direction>out</direction>
          <relatedStateVariable>A_ARG_TYPE_RcsID</relatedStateVariable>
        </argument>
        <argument>
          <name>AVTransportID</name>
          <direction>out</direction>
          <relatedStateVariable>A_ARG_TYPE_AVTransportID</relatedStateVariable>
        </argument>
        <argument>
          <name>ProtocolInfo</name>
          <direction>out</direction>
          <relatedStateVariable>A_ARG_TYPE_ProtocolInfo</relatedStateVariable>
        </argument>
        <argument>
          <name>PeerConnectionManager</name>
          <direction>out</direction>
          <relatedStateVariable>A_ARG_TYPE_ConnectionManager</relatedStateVariable>
        </argument>
        <argument>
          <name>PeerConnectionID</name>
          <direction>out</direction>
          <relatedStateVariable>A_ARG_TYPE_ConnectionID</relatedStateVariable>
        </argument>
        <argument>
          <name>Direction</name>
          <direction>out</direction>
          <relatedStateVariable>A_ARG_TYPE_Direction</relatedStateVariable>
        </argument>
        <argument>
          <name>Status</name>
          <direction>out</direction>
          <relatedStateVariable>A_ARG_TYPE_ConnectionStatus</relatedStateVariable>
        </argument>
      </argumentList>
    </action>
  </actionList>
</scpd>
"""
#{}".format(self.serviceType, action) #        print(etree.tostring(self.info, pretty_print=True)) #        print(self.variables.keys()) #        print(self.actions.keys()) Return a formatted string suitable for displaying on stdout. Service ID:           {}             Type:         {}             control URL:  {}             eventSubURL:  {}      Actions <scpd xmlns="urn:schemas-upnp-org:service-1-0">   <specVersion>     <major>1</major>     <minor>0</minor>   </specVersion>    <serviceStateTable>     <stateVariable sendEvents="yes">       <name>SourceProtocolInfo</name>       <dataType>string</dataType>     </stateVariable>     <stateVariable sendEvents="yes">       <name>SinkProtocolInfo</name>       <dataType>string</dataType>     </stateVariable>     <stateVariable sendEvents="yes">       <name>CurrentConnectionIDs</name>       <dataType>string</dataType>     </stateVariable>     <stateVariable sendEvents="no">       <name>A_ARG_TYPE_ConnectionStatus</name>       <dataType>string</dataType>       <allowedValueList>         <allowedValue>OK</allowedValue>         <allowedValue>ContentFormatMismatch</allowedValue>         <allowedValue>InsufficientBandwidth</allowedValue>         <allowedValue>UnreliableChannel</allowedValue>         <allowedValue>Unknown</allowedValue>       </allowedValueList>     </stateVariable>     <stateVariable sendEvents="no">       <name>A_ARG_TYPE_ConnectionManager</name>       <dataType>string</dataType>     </stateVariable>     <stateVariable sendEvents="no">       <name>A_ARG_TYPE_Direction</name>       <dataType>string</dataType>       <allowedValueList>         <allowedValue>Input</allowedValue>         <allowedValue>Output</allowedValue>       </allowedValueList>     </stateVariable>     <stateVariable sendEvents="no">       <name>A_ARG_TYPE_ProtocolInfo</name>       <dataType>string</dataType>     </stateVariable>     <stateVariable sendEvents="no">       <name>A_ARG_TYPE_ConnectionID</name>       <dataType>i4</dataType>     </stateVariable>     <stateVariable sendEvents="no">       <name>A_ARG_TYPE_AVTransportID</name>       <dataType>i4</dataType>     </stateVariable>     <stateVariable sendEvents="no">       <name>A_ARG_TYPE_RcsID</name>       <dataType>i4</dataType>     </stateVariable>   </serviceStateTable>   <actionList>     <action>       <name>GetProtocolInfo</name>       <argumentList>         <argument>           <name>Source</name>           <direction>out</direction>           <relatedStateVariable>SourceProtocolInfo</relatedStateVariable>         </argument>         <argument>           <name>Sink</name>           <direction>out</direction>           <relatedStateVariable>SinkProtocolInfo</relatedStateVariable>         </argument>       </argumentList>     </action>     <action>       <name>GetCurrentConnectionIDs</name>       <argumentList>         <argument>           <name>ConnectionIDs</name>           <direction>out</direction>           <relatedStateVariable>CurrentConnectionIDs</relatedStateVariable>         </argument>       </argumentList>     </action>     <action>       <name>GetCurrentConnectionInfo</name>       <argumentList>         <argument>           <name>ConnectionID</name>           <direction>in</direction>           <relatedStateVariable>A_ARG_TYPE_ConnectionID</relatedStateVariable>         </argument>         <argument>           <name>RcsID</name>           <direction>out</direction>           <relatedStateVariable>A_ARG_TYPE_RcsID</relatedStateVariable>         </argument>         <argument>           <name>AVTransportID</name>           <direction>out</direction>           <relatedStateVariable>A_ARG_TYPE_AVTransportID</relatedStateVariable>         </argument>         <argument>           <name>ProtocolInfo</name>           <direction>out</direction>           <relatedStateVariable>A_ARG_TYPE_ProtocolInfo</relatedStateVariable>         </argument>         <argument>           <name>PeerConnectionManager</name>           <direction>out</direction>           <relatedStateVariable>A_ARG_TYPE_ConnectionManager</relatedStateVariable>         </argument>         <argument>           <name>PeerConnectionID</name>           <direction>out</direction>           <relatedStateVariable>A_ARG_TYPE_ConnectionID</relatedStateVariable>         </argument>         <argument>           <name>Direction</name>           <direction>out</direction>           <relatedStateVariable>A_ARG_TYPE_Direction</relatedStateVariable>         </argument>         <argument>           <name>Status</name>           <direction>out</direction>           <relatedStateVariable>A_ARG_TYPE_ConnectionStatus</relatedStateVariable>         </argument>       </argumentList>     </action>   </actionList> </scpd>