"""
The base class for io services.
"""
import logging
from select import select

from bridge.service import BridgeService

class IOService(BridgeService):
    """
    An abstraction of a BridgeService, meant to run IO
    on a paticular interface.
    """

    def __init__(self, name, file_name, hub_connection):
        super().__init__(name, hub_connection)
        self.io_fd = self._create_fd(file_name)

        self.read_list = [self.hub_connection]
        self.pending = []

    def run(self):
        self.mask_signals()
        self.spinning = True

        if self.io_fd is None:
            self.notify_not_connected()

        else:
            self.notify_connected()

            self.read_list.append(self.io_fd)

        while self.spinning:
            (read, _, _) = select(self.read_list, [], [])
            if self.hub_connection in read:
                self.read_and_do_remote_request()
            if self.io_fd in read:
                self.read_io()

    def update_model(self, real_id, update):
        """Send an upate to model, it will be decoded by an idiom."""
        logging.debug("Updating model with {0}".format(update))
        self.remote_async_service_method('model', 'io_update', self.name, real_id, update)

    def _create_fd(self, file_name):
        raise NotImplementedError

    def write_io(self, buf):
        logging.debug("Writing command {0}.".format(str(buf)))
        if self.io_fd:
            self.io_fd.write(buf)
        else:
            self.pending.append(buf)

    def read_io(self):
        """Read the interface, each IO service must implmeenet this."""
        raise NotImplementedError

    def asset_info(self, real_id):
        """Get more info about device."""
        raise NotImplementedError

    def notify_not_connected(self):
        self.remote_async_service_method('model', 'io_service_offline', self.name)

    def notify_connected(self):
        self.remote_async_service_method('model', 'io_service_online', self.name)

@@ -180,16 +180,20 @@
 ion of a
+n IO
  BridgeS
@@ -244,17 +244,251 @@
 nterface
-.
+ module/device.%0A%0A    :param name: Name of the IO service.%0A    :type name: str%0A%0A    :param name: Path of the file used for I/O.%0A    :type file_name: str%0A%0A    :param hub_connection: Connection to BridgeHub.%0A    :type hub_connection: Pipe
 %0A    %22%22%22
@@ -716,16 +716,452 @@
 g = %5B%5D%0A%0A
+    def asset_info(self, real_id):%0A        %22%22%22%0A        Get more info about device (by querying the IO).%0A        Must be implemented by each IO service.%0A%0A        :param real_id: Real ID to get asset information about.%0A        :type real_id: object%0A        %22%22%22%0A        raise NotImplementedError%0A%0A    def read_io(self):%0A        %22%22%22%0A        Read the file, each IO service must implement this.%0A        %22%22%22%0A        raise NotImplementedError%0A%0A
     def 
@@ -1703,16 +1703,25 @@
      %22%22%22
+%0A        
 Send an 
@@ -1748,31 +1748,219 @@
 ill 
-be decoded by an idiom.
+changed to a asset transition(s) by an idiom.%0A%0A        :param real_id: ID used by the the I/O.%0A        :type real_id: object%0A%0A        :param update: Update to send to model.%0A        :type update: object%0A        
 %22%22%22%0A
@@ -2127,34 +2127,26 @@
 def 
-_create_fd
+write_io
 (self, 
-file_name
+buf
 ):%0A 
@@ -2156,63 +2156,133 @@
     
-raise NotImplementedErr
+%22%22%22%0A        Write a buffer to the file descript
 or
+.
 %0A%0A    
-def write_io(self, buf):
+    :param buf: Buffer to write.%0A        :type buf: bytes%0A        %22%22%22
 %0A   
@@ -2462,277 +2462,324 @@
 def 
-read_io(self):%0A        %22%22%22Read the interface, each IO service must implmeenet this.%22%22%22%0A        raise NotImplementedError%0A%0A    def asset_info(self, real_id):%0A        %22%22%22Get more info about device.%22%22%22%0A        raise NotImplementedError%0A%0A    def notify_not_connected(self):
+notify_not_connected(self):%0A        %22%22%22%0A        Notify the model that the this service isn't connected.%0A        %22%22%22%0A        self.remote_async_service_method('model', 'io_service_offline', self.name)%0A%0A    def notify_connected(self):%0A        %22%22%22%0A        Notify the model that the this service is connected.%0A        %22%22%22
 %0A   
@@ -2830,34 +2830,33 @@
 ', 'io_service_o
-ff
+n
 line', self.name
@@ -2870,110 +2870,193 @@
 def 
-notify_connected(self):%0A        self.remote_async_service_method('model', 'io_service_online', self.name)
+_create_fd(self, file_name):%0A        %22%22%22%0A        Create the file descriptor from the file name,%0A        each IO service should implement this.%0A        %22%22%22%0A        raise NotImplementedError
 %0A

Update base class for IO services.