"""I2C servo controller platform."""
import asyncio
import logging
import time

from mpf.exceptions.ConfigFileError import ConfigFileError
from mpf.platforms.interfaces.servo_platform_interface import ServoPlatformInterface

from mpf.core.platform import ServoPlatform


class I2CServoControllerHardwarePlatform(ServoPlatform):

    """Supports the PCA9685/PCA9635 chip via I2C."""

    def __init__(self, machine):
        """Initialise I2C servo platform."""
        super().__init__(machine)
        self.log = logging.getLogger("I2C Servo Controller Platform")
        self.log.debug("Configuring template hardware interface.")
        self.config = self.machine.config.get('servo_controllers', {})
        self.platform = None
        self.i2c_devices = {}
        self.features['tickless'] = True

    def __repr__(self):
        """Return string representation."""
        return '<Platform.I2C_Servo_Controller_Platform>'

    @asyncio.coroutine
    def initialize(self):
        """Initialise platform."""
        yield from super().initialize()

        # validate our config (has to be in intialize since config_processor
        # is not read in __init__)
        self.config = self.machine.config_validator.validate_config("servo_controllers", self.config)

        # load i2c platform
        self.platform = self.machine.get_platform_sections(
            "i2c", self.config['platform'])

    def _initialize_controller(self, address):
        # check if controller is already initialized
        if address in self.i2c_devices:
            return self.i2c_devices[address]

        i2c_device = yield from self.platform.configure_i2c(address)
        self.i2c_devices[address] = i2c_device

        # initialise PCA9685/PCA9635
        i2c_device.i2c_write8(0x00, 0x11)  # set sleep
        i2c_device.i2c_write8(0x01, 0x04)  # configure output
        i2c_device.i2c_write8(0xFE, 130)   # set approx 50Hz
        yield from asyncio.sleep(.01, loop=self.machine.clock.loop)     # needed according to datasheet to sync PLL
        i2c_device.i2c_write8(0x00, 0x01)  # no more sleep
        yield from asyncio.sleep(.01, loop=self.machine.clock.loop)     # needed to end sleep according to datasheet
        return i2c_device

    @asyncio.coroutine
    def configure_servo(self, number: str):
        """Configure servo."""
        try:
            i2c_address, servo_number = number.rsplit("-", 1)
        except ValueError:
            servo_number = number
            i2c_address = 0x40
        try:
            number_int = int(servo_number)
        except ValueError:
            raise ConfigFileError("Invalid servo number {} in {}.".format(servo_number, number),
                                  2, self.log.name)

        i2c_device = yield from self._initialize_controller(i2c_address)

        # check bounds
        if number_int < 0 or number_int > 15:
            raise ConfigFileError("Invalid number {} in {}. The controller only supports servos 0 to 15.".format(
                number_int, number), 1, self.log.name)

        return I2cServo(number_int, self.config, i2c_device)

    def stop(self):
        """Stop platform."""
        pass


class I2cServo(ServoPlatformInterface):

    """A servo hw device."""

    def __init__(self, number, config, i2c_device):
        """Initialise I2C hw servo."""
        self.log = logging.getLogger('I2cServo')
        self.number = number
        self.config = config
        self.i2c_device = i2c_device

    def go_to_position(self, position):
        """Move servo to position.

        Args:
            position: Position to set the servo. 0 to 1

        """
        # check bounds
        if position < 0 or position > 1:
            raise AssertionError("Position has to be between 0 and 1")

        # actual values depend on the controller. usually 150 to 600.
        # interpolate
        servo_min = self.config['servo_min']
        servo_max = self.config['servo_max']
        value = int(servo_min + position * (servo_max - servo_min))

        # set servo via i2c
        self.i2c_device.i2c_write8(0x06 + self.number * 4, 0)
        self.i2c_device.i2c_write8(0x07 + self.number * 4, 0)
        self.i2c_device.i2c_write8(0x08 + self.number * 4, value & 0xFF)
        self.i2c_device.i2c_write8(0x09 + self.number * 4, value >> 8)

    @classmethod
    def set_speed_limit(cls, speed_limit):
        """Todo emulate speed parameter."""
        pass

    @classmethod
    def set_acceleration_limit(cls, acceleration_limit):
        """Todo emulate acceleration parameter."""
        pass

@@ -63,20 +63,8 @@
 ging
-%0Aimport time
 %0A%0Afr

remove unused import