import logging
from datetime import timedelta
import json

def is_hass_component():
    try:
        import homeasssistant
        return True
    except ImportError:
        return False

if is_hass_component():
    from homeassistant.helpers.entity import Entity
    from homeassistant.util import Throttle
    from homeassistant.components.sensor import PLATFORM_SCHEMA
    from homeassistant.const import CONF_USERNAME, CONF_PASSWORD
    import homeassistant.helpers.config_validation as cv

    from deps.sure_petcare import SurePetFlap
    from deps.sure_petcare.utils import gen_device_id

    import voluptuous as vol

    PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
        vol.Required(CONF_USERNAME): cv.string,
        vol.Required(CONF_PASSWORD): cv.string,
    })
else:
    # Assume not running within home assistant.  This *does* mean that you
    # won't be able to run this test script if you have homeassistant
    # installed but, if you do, you're probably running (or can run) this
    # component from within hass anyway.
    from sure_petcare import SurePetFlap
    from sure_petcare.utils import gen_device_id

    # dummy dependencies
    class Entity( object ):
        pass

    def Throttle( *args, **kwargs ):
        def decorator( f ):
            return f
        return decorator


#REQUIREMENTS = ['sure_petcare']


_LOGGER = logging.getLogger(__name__)

CONF_device_id = 'device_id'

SCAN_INTERVAL = timedelta(seconds=300)
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=600)
MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(seconds=120)

def setup_platform(hass, config, add_devices, discovery_info=None):
    """Setup the sensor platform."""
    username = config.get(CONF_USERNAME)
    password = config.get(CONF_PASSWORD)
    add_devices([SurePetConnect(username, password)])


class SurePetConnect(Entity):
    """Representation of a Sensor."""

    def __init__(self, username, password, **kwargs):
        """Initialize the sensor."""
        _LOGGER.debug('Initializing...')
        # 1.25V is a fairly conservative guess for alkalines.  If you use
        # rechargeables, you may need to change this.
        self.FULL_BATTERY_VOLTAGE = 1.6 # volts
        self.LOW_BATTERY_VOLTAGE = 1.25 # volts
        self.battery = [-1] *60
        self.battery[0] = 1 # Initialize average so we have a mean
        self.battery_pos = -1
        self.sure = SurePetFlap(email_address=username, password=password, device_id=gen_device_id(), **kwargs)
        self._state = None
        self._attributes = []
        self.update()

    @property
    def name(self):
        """Return the name of the sensor."""
        return 'SurePet Connect'

    @property
    def state(self):
        """Return the state of the sensor."""
        return self._state

    @property
    def unit_of_measurement(self):
        """Return the unit of measurement."""
        return ''
    
    @Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS)
    def update(self):
        """Fetch new state data for the sensor.

        This is the only method that should fetch new data for Home Assistant.
        """
        _LOGGER.debug('Returning current state...')
        flap_status = {}
        with self.sure:
            # Update only data required
            self.sure.update_authtoken()
            self.sure.update_households()
            self.sure.update_device_ids()
            self.sure.update_pet_info()
            self.sure.update_pet_status()
            self.sure.update_flap_status()
            self.sure.update_router_status()
        for pet in self.sure.pets:
            pet_status = self.sure.get_current_status(pet)
            flap_status[str(self.sure.pets[pet]['name'])]  = pet_status
        self.battery_pos = (self.battery_pos + 1) % len(self.battery) #Loop around
        # NB: Units have changed.  Earlier versions reported the raw voltage
        #     direct from the Sure backend which was the sum of the four
        #     batteries.  The current API reports voltage per battery, making
        #     it easier to set thresholds based on battery chemistry.
        bat_left = self.sure.battery - self.LOW_BATTERY_VOLTAGE
        bat_full = self.FULL_BATTERY_VOLTAGE - self.LOW_BATTERY_VOLTAGE
        self.battery[self.battery_pos] = int(bat_left/bat_full*100)
        flap_status['avg_battery'] = int(self.mean([ i for i in self.battery if i > 0]))
        flap_status['battery'] = self.battery[self.battery_pos]
        flap_status['flap_online']  = self.sure.flap_status[self.sure.default_flap]['online']
        flap_status['hub_online'] =  self.sure.router_status[self.sure.default_router]['online']
        flap_status['lock_status'] = self.sure.lock_mode()
        flap_status['locked'] = self.sure.locked()
        _LOGGER.debug('State: ' + str(flap_status))
        self._state = json.dumps(flap_status)
        self._attributes = flap_status

    @property
    def state_attributes(self):
        """Return the attributes of the entity.

           Provide the parsed JSON data (if any).
        """

        return self._attributes
    
    def mean(self, numbers):
        return float(sum(numbers)) / max(len(numbers), 1)