'''Devices
===========

Defines some of the devices that are used in the experiment.
'''


__all__ = (
    'FTDIOdorsBase', 'FTDIOdorsSim', 'FTDIOdors', 'DAQInDeviceBase',
    'DAQInDeviceSim', 'DAQInDevice', 'DAQOutDeviceBase', 'DAQOutDeviceSim',
    'DAQOutDevice')

from weakref import ref

from moa.device.digital import ButtonChannel, ButtonPort
from moa.device.analog import NumericPropertyChannel

from ffpyplayer.player import MediaPlayer

from kivy.properties import (
    ConfigParserProperty, BooleanProperty, ListProperty, ObjectProperty,
    NumericProperty)
from kivy.app import App
from kivy import resources

from cplcom.moa.device.ftdi import FTDISerializerDevice
from cplcom.moa.device.mcdaq import MCDAQDevice



class FTDIOdorsBase(object):
    '''Base class for the FTDI odor device.
    '''

    def __init__(self, **kwargs):
        n_valve_boards = kwargs.get('n_valve_boards', self.n_valve_boards)
        # we don't know ahead of time how many valves, so we need to create
        # the bool prop for each valve dynamically
        for i in range(8 * n_valve_boards):
            self.create_property('p{}'.format(i), value=False, allownone=True)

        super(FTDIOdorsBase, self).__init__(direction='o', **kwargs)

    n_valve_boards = NumericProperty(2)
    '''The number of valve boards that are connected to the FTDI controller.
    Each board can typically control 8 valves.

    Defaults to 2.
    '''


class FTDIOdorsSim(FTDIOdorsBase, ButtonPort):
    '''Device used when simulating the odor device.
    '''
    pass


class FTDIOdors(FTDIOdorsBase, FTDISerializerDevice):
    '''Device used when using the barst ftdi odor device.
    '''

    def __init__(self, **kwargs):
        super(FTDIOdors, self).__init__(**kwargs)
        self.dev_map = {'p{}'.format(i): i
                        for i in range(self.n_valve_boards * 8)}


class DAQInDeviceBase(object):
    '''Base class for the Switch & Sense 8/8 input ports.
    '''

    nose_beam = BooleanProperty(False, allownone=True)
    '''Reads / controls the nose port photobeam.
    '''

    reward_beam_r = BooleanProperty(False, allownone=True)
    '''Reads / controls the right reward port photobeam.
    '''

    reward_beam_l = BooleanProperty(False, allownone=True)
    '''Reads / controls the left reward port photobeam.
    '''


class DAQInDeviceSim(DAQInDeviceBase, ButtonPort):
    '''Device used when simulating the Switch & Sense 8/8 input device.
    '''
    pass


class DAQInDevice(DAQInDeviceBase, MCDAQDevice):
    '''Device used when using the barst Switch & Sense 8/8 input device.
    '''

    __settings_attrs__ = (
        'nose_beam_pin', 'reward_beam_r_pin', 'reward_beam_l_pin')

    def __init__(self, **kwargs):
        super(DAQInDevice, self).__init__(direction='i', **kwargs)
        self.dev_map = {
        'nose_beam': self.nose_beam_pin,
        'reward_beam_r': self.reward_beam_r_pin,
        'reward_beam_l': self.reward_beam_l_pin}

    nose_beam_pin = NumericProperty(1)
    '''The port in the Switch & Sense to which the nose port photobeam is
    connected to.

    Defaults to 1.
    '''

    reward_beam_r_pin = NumericProperty(3)
    '''The port in the Switch & Sense to which the right reward port photobeam
    is connected to.

    Defaults to 3.
    '''

    reward_beam_l_pin = NumericProperty(2)
    '''The port in the Switch & Sense to which the left reward port photobeam
    is connected to.

    Defaults to 2.
    '''


class DAQOutDeviceBase(object):
    '''Base class for the Switch & Sense 8/8 output ports.
    '''

    house_light = BooleanProperty(False, allownone=True)
    '''Controls the house light.
    '''

    ir_leds = BooleanProperty(False, allownone=True)
    '''Controls the IR light.
    '''

    fans = BooleanProperty(False, allownone=True)
    '''Controls the fans.
    '''

    feeder_r = BooleanProperty(False, allownone=True)
    '''Controls the right feeder.
    '''

    feeder_l = BooleanProperty(False, allownone=True)
    '''Controls the left feeder.
    '''


class DAQOutDeviceSim(DAQOutDeviceBase, ButtonPort):
    '''Device used when simulating the Switch & Sense 8/8 output device.
    '''
    pass


class DAQOutDevice(DAQOutDeviceBase, MCDAQDevice):
    '''Device used when using the barst Switch & Sense 8/8 output device.
    '''

    __settings_attrs__ = (
        'house_light_pin', 'ir_leds_pin', 'fans_pin', 'feeder_r_pin',
        'feeder_l_pin')

    def __init__(self, **kwargs):
        super(DAQOutDevice, self).__init__(direction='o', **kwargs)
        self.dev_map = {'house_light': self.house_light_pin,
                   'ir_leds': self.ir_leds_pin,
                   'fans': self.fans_pin,
                   'feeder_r': self.feeder_r_pin,
                   'feeder_l': self.feeder_l_pin}

    house_light_pin = NumericProperty(4)
    '''The port in the Switch & Sense that controls the house light.

    Defaults to 4.
    '''

    ir_leds_pin = NumericProperty(6)
    '''The port in the Switch & Sense that controls the IR lights.

    Defaults to 6.
    '''

    fans_pin = NumericProperty(5)
    '''The port in the Switch & Sense that controls the fans.

    Defaults to 5.
    '''

    feeder_r_pin = NumericProperty(2)
    '''The port in the Switch & Sense that controls the right feeder.

    Defaults to 2.
    '''

    feeder_l_pin = NumericProperty(0)
    '''The port in the Switch & Sense that controls the left feeder.

    Defaults to 0.
    '''

'''Devices
===========

Defines some of the devices that are used in the experiment.
'''


__all__ = (
    'FTDIOdorsBase', 'FTDIOdorsSim', 'FTDIOdors', 'DAQInDeviceBase',
    'DAQInDeviceSim', 'DAQInDevice', 'DAQOutDeviceBase', 'DAQOutDeviceSim',
    'DAQOutDevice')

from weakref import ref

from moa.device.digital import ButtonChannel, ButtonPort
from moa.device.analog import NumericPropertyChannel

from ffpyplayer.player import MediaPlayer

from kivy.properties import (
    ConfigParserProperty, BooleanProperty, ListProperty, ObjectProperty,
    NumericProperty)
from kivy.app import App
from kivy import resources

from cplcom.moa.device.ftdi import FTDISerializerDevice
from cplcom.moa.device.mcdaq import MCDAQDevice



class FTDIOdorsBase(object):
    '''Base class for the FTDI odor device.
    '''

    def __init__(self, **kwargs):
        n_valve_boards = kwargs.get('n_valve_boards', self.n_valve_boards)
        # we don't know ahead of time how many valves, so we need to create
        # the bool prop for each valve dynamically
        for i in range(8 * n_valve_boards):
            self.create_property('p{}'.format(i), value=False, allownone=True)

        super(FTDIOdorsBase, self).__init__(direction='o', **kwargs)

    n_valve_boards = NumericProperty(2)
    '''The number of valve boards that are connected to the FTDI controller.
    Each board can typically control 8 valves.

    Defaults to 2.
    '''


class FTDIOdorsSim(FTDIOdorsBase, ButtonPort):
    '''Device used when simulating the odor device.
    '''
    pass


class FTDIOdors(FTDIOdorsBase, FTDISerializerDevice):
    '''Device used when using the barst ftdi odor device.
    '''

    def __init__(self, **kwargs):
        super(FTDIOdors, self).__init__(**kwargs)
        self.dev_map = {'p{}'.format(i): i
                        for i in range(self.n_valve_boards * 8)}


class DAQInDeviceBase(object):
    '''Base class for the Switch & Sense 8/8 input ports.
    '''

    nose_beam = BooleanProperty(False, allownone=True)
    '''Reads / controls the nose port photobeam.
    '''

    reward_beam_r = BooleanProperty(False, allownone=True)
    '''Reads / controls the right reward port photobeam.
    '''

    reward_beam_l = BooleanProperty(False, allownone=True)
    '''Reads / controls the left reward port photobeam.
    '''


class DAQInDeviceSim(DAQInDeviceBase, ButtonPort):
    '''Device used when simulating the Switch & Sense 8/8 input device.
    '''
    pass


class DAQInDevice(DAQInDeviceBase, MCDAQDevice):
    '''Device used when using the barst Switch & Sense 8/8 input device.
    '''

    __settings_attrs__ = (
        'nose_beam_pin', 'reward_beam_r_pin', 'reward_beam_l_pin')

    def __init__(self, **kwargs):
        super(DAQInDevice, self).__init__(direction='i', **kwargs)
        self.dev_map = {
        'nose_beam': self.nose_beam_pin,
        'reward_beam_r': self.reward_beam_r_pin,
        'reward_beam_l': self.reward_beam_l_pin}

    nose_beam_pin = NumericProperty(1)
    '''The port in the Switch & Sense to which the nose port photobeam is
    connected to.

    Defaults to 1.
    '''

    reward_beam_r_pin = NumericProperty(3)
    '''The port in the Switch & Sense to which the right reward port photobeam
    is connected to.

    Defaults to 3.
    '''

    reward_beam_l_pin = NumericProperty(2)
    '''The port in the Switch & Sense to which the left reward port photobeam
    is connected to.

    Defaults to 2.
    '''


class DAQOutDeviceBase(object):
    '''Base class for the Switch & Sense 8/8 output ports.
    '''

    house_light = BooleanProperty(False, allownone=True)
    '''Controls the house light.
    '''

    ir_leds = BooleanProperty(False, allownone=True)
    '''Controls the IR light.
    '''

    fans = BooleanProperty(False, allownone=True)
    '''Controls the fans.
    '''

    feeder_r = BooleanProperty(False, allownone=True)
    '''Controls the right feeder.
    '''

    feeder_l = BooleanProperty(False, allownone=True)
    '''Controls the left feeder.
    '''


class DAQOutDeviceSim(DAQOutDeviceBase, ButtonPort):
    '''Device used when simulating the Switch & Sense 8/8 output device.
    '''
    pass


class DAQOutDevice(DAQOutDeviceBase, MCDAQDevice):
    '''Device used when using the barst Switch & Sense 8/8 output device.
    '''

    __settings_attrs__ = (
        'house_light_pin', 'ir_leds_pin', 'fans_pin', 'feeder_r_pin',
        'feeder_l_pin')

    def __init__(self, **kwargs):
        super(DAQOutDevice, self).__init__(direction='o', **kwargs)
        self.dev_map = {'house_light': self.house_light_pin,
                   'ir_leds': self.ir_leds_pin,
                   'fans': self.fans_pin,
                   'feeder_r': self.feeder_r_pin,
                   'feeder_l': self.feeder_l_pin}

    house_light_pin = NumericProperty(4)
    '''The port in the Switch & Sense that controls the house light.

    Defaults to 4.
    '''

    ir_leds_pin = NumericProperty(6)
    '''The port in the Switch & Sense that controls the IR lights.

    Defaults to 6.
    '''

    fans_pin = NumericProperty(5)
    '''The port in the Switch & Sense that controls the fans.

    Defaults to 5.
    '''

    feeder_r_pin = NumericProperty(2)
    '''The port in the Switch & Sense that controls the right feeder.

    Defaults to 2.
    '''

    feeder_l_pin = NumericProperty(0)
    '''The port in the Switch & Sense that controls the left feeder.

    Defaults to 0.
    '''

Devices ===========  Defines some of the devices that are used in the experiment. Base class for the FTDI odor device. # we don't know ahead of time how many valves, so we need to create # the bool prop for each valve dynamically The number of valve boards that are connected to the FTDI controller.     Each board can typically control 8 valves.      Defaults to 2. Device used when simulating the odor device. Device used when using the barst ftdi odor device. Base class for the Switch & Sense 8/8 input ports. Reads / controls the nose port photobeam. Reads / controls the right reward port photobeam. Reads / controls the left reward port photobeam. Device used when simulating the Switch & Sense 8/8 input device. Device used when using the barst Switch & Sense 8/8 input device. The port in the Switch & Sense to which the nose port photobeam is     connected to.      Defaults to 1. The port in the Switch & Sense to which the right reward port photobeam     is connected to.      Defaults to 3. The port in the Switch & Sense to which the left reward port photobeam     is connected to.      Defaults to 2. Base class for the Switch & Sense 8/8 output ports. Controls the house light. Controls the IR light. Controls the fans. Controls the right feeder. Controls the left feeder. Device used when simulating the Switch & Sense 8/8 output device. Device used when using the barst Switch & Sense 8/8 output device. The port in the Switch & Sense that controls the house light.      Defaults to 4. The port in the Switch & Sense that controls the IR lights.      Defaults to 6. The port in the Switch & Sense that controls the fans.      Defaults to 5. The port in the Switch & Sense that controls the right feeder.      Defaults to 2. The port in the Switch & Sense that controls the left feeder.      Defaults to 0.