import RPi.GPIO as GPIO
import config
from drivers.camera import make_transfer_picture

class Changer(object):

    def __init__(self, local_state, remote_state):
        self.local_state = local_state
        self.remote_state = remote_state
        GPIO.setmode(GPIO.BCM) # Broadcom pin-numbering scheme
        GPIO.setup(config.GPIO_PIN_OUT_VALVE, GPIO.OUT)
        GPIO.setup(config.GPIO_PIN_IN_VALVE, GPIO.OUT)

        self.out_valve_states = {
            'opening': self.open_out_valve,
            'closing': self.close_out_valve,
            'open': self.open_out_valve,
            'closed': self.close_out_valve
        }

        self.in_valve_states = {
            'opening': self.open_in_valve,
            'closing': self.close_in_valve,
            'open': self.open_in_valve,
            'closed': self.close_in_valve
        }

    def stop_everything(self):
        self.close_in_valve()
        self.close_out_valve()

    def safe_remote_state(self, key):
        if key in ['out_valve', 'in_valve']:
            return self.remote_state.get(key, 'closed')
        else:
            return self.remote_state.get(key,'');

    def process_change(self):
        self.validate_states()

        out_valve_change = self.out_valve_states.get(self.safe_remote_state('out_valve'), None )
        if out_valve_change is not None:
            out_valve_change()

        in_valve_change = self.in_valve_states.get(self.safe_remote_state('in_valve'), None )
        if in_valve_change is not None:
            in_valve_change()

        self.fulfill_picture_request()

        return self.local_state

    def open_in_valve(self):
        GPIO.output(config.GPIO_PIN_IN_VALVE, GPIO.HIGH)
        self.local_state['in_valve'] = 'open'

    def close_in_valve(self):
        GPIO.output(config.GPIO_PIN_IN_VALVE, GPIO.LOW)
        self.local_state['in_valve'] = 'closed'

    def open_out_valve(self):
        GPIO.output(config.GPIO_PIN_OUT_VALVE, GPIO.HIGH)
        self.local_state['out_valve'] = 'open'

    def close_out_valve(self):
        GPIO.output(config.GPIO_PIN_OUT_VALVE, GPIO.LOW)
        self.local_state['out_valve'] = 'closed'

    def fulfill_picture_request(self):
        if self.remote_state['picture_requested'] == 'true':
            make_transfer_picture()
        self.local_state['picture_requested'] = 'false'


    def validate_states(self):
        if self.local_state is None or self.remote_state is None:
            raise ClassNotReadyException("Both local and remote states must be present!")
        # TODO: add detailed validation
