import sys
import time

import settings
from support.hue import COMMAND_FULL_ON, COMMAND_OFF
from support.lock import is_locked, lock, unlock
from support.logger import get_logger

'''
Handle 'Arriving home' action.
Turn on stairwell for 30m, then turn off
'''

logger = get_logger("arrive")

ON_TIME_S = 60 * 20  # 30m

PROCESS_NAME = 'arrive'  # For use with lockfile to prevent multiple simultaneous operations


def perform_arrival():

    stairway = settings.ROOMS[4]

    stairway.update(COMMAND_FULL_ON)

    time.sleep(ON_TIME_S)

    stairway.update(COMMAND_OFF)

import time

from support.color import get_next_circadian_color
from support.hue import command_all_lights, hue
from support.logger import get_logger
from support.room import LightsOnDuringDayRoom
from support.time_utils import get_local_time
from settings import ROOMS

# Logging
logger = get_logger("circadian")

while 1:
    now = get_local_time()
    next_color_date, next_color = get_next_circadian_color(date=now)

    sleep_time_s = (next_color_date - now).seconds
    logger.info("Sleeping until %s at %s", next_color.name, next_color_date.strftime('%Y/%m/%d %I:%M:%S %p'))
    time.sleep(sleep_time_s + 30)  # Add padding to compensate for sleep inaccuracy
    logger.info("Adjusting hue for %s", next_color.name)
    command = next_color.apply_to_command({'transitiontime': 60 * 10})  # 60 s transition

    if next_color.name == 'Day':
        lights = []
        for room in ROOMS:
            if not isinstance(room, LightsOnDuringDayRoom):
                lights += room.lights
        hue.set_light(lights, command)
    else:
        command_all_lights(command)
import datetime

import copy
from astral import SUN_RISING

from support.hue import COMMAND_OFF
from support.logger import get_logger
from support.time_utils import get_local_sunrise, get_local_sunset, LOCAL_TIMEZONE, get_time_at_elevation
from support.weather_utils import is_cloudy

LIGHT_DAYTIME_XY = [0.4506, 0.4081]
LIGHT_EVENING_XY = [0.4904, 0.4075]
LIGHT_NIGHT_XY = [0.5304, 0.4068]
LIGHT_LATENIGHT_XY = [0.6185, 0.363]

logger = get_logger("color")


class CircadianColor:
    def __init__(self, name: str, color_xy: list, brightness: int, trigger_date_function: callable):
        """
        A light setting that depends only on the circadian cycle.

        :param name: human-readable name
        :param color_xy: the hue accompanying this circadian event. See http://www.developers.meethue.com/documentation/hue-xy-values
        :param brightness: the brightness from 0 to 255. If zero, will be treated as switch-off command
        :param trigger_date_function: a function returning the start time for the day the function is called.
        :return:
        """
        self.name = name
        self.color_xy = color_xy
from support.logger import get_logger

FRAME_TIME_S = 10

COLORS = [
    [0.1772, 0.0592],  # Blue
    [0.4882, 0.2286],  # Pink
    [0.6043, 0.3728],  # Sun Amber
    [0.6736, 0.3221],  # Red
    [0.6043, 0.3728],  # Sun Amber
    [0.4882, 0.2286],  # Pink
]

PROCESS_NAME = 'animate'

logger = get_logger("animate")

command = {'on': True,
           'bri': 254,
           'transitiontime': 10 * FRAME_TIME_S}

LIGHT_TO_COLOR_IDX = {}
counter = 0


def assign_colors(offset: int = 0):
    colors_idx = offset
    for light in hue.get_light_objects(mode='id'):

        LIGHT_TO_COLOR_IDX[light] = colors_idx
        #logger.info("Light %d will have color %d :  %s" % (light, colors_idx, COLORS[colors_idx]))
import copy
import flask
import re

from SECRETS import HTTPS_API_KEY, SSL_CERT_PEM, SSL_KEY_PEM
from arrive import unlock
from settings import ROOMS
from support import env
from support.color import get_current_circadian_color
from support.hue import command_all_lights, COMMAND_FULL_ON
from support.logger import get_logger
from support.time_utils import get_local_time

app = flask.Flask(__name__)

logger = get_logger("web_server")

party_process = None  # Party mode process


def is_local_request(request):
    request_remote_addr = request.environ["REMOTE_ADDR"]
    return request_remote_addr.startswith("192.168.1.")


def get_home_status(template_friendly_dict: bool) -> dict:
    """
    :param template_friendly_dict: whether to create a template friendly cict. This involves representing booleans
    as "true"/"false" strings and stripping spaces from keys. For template dicts,
    we need to use string values, for json return we can use bool
    """
import time

import settings
from support.color import LIGHT_DAYTIME_XY, LIGHT_EVENING_XY

# Start at evening hue, min brightness. Fade to daytime hue, full brightness
# over 30m
from support.logger import get_logger

logger = get_logger('wakeup')

living_room = settings.ROOMS[0]
hall = settings.ROOMS[1]
kitchen = settings.ROOMS[2]
bedroom = settings.ROOMS[3]

if bedroom.is_lit() or living_room.is_lit() or kitchen.is_lit() or hall.is_lit():
    logger.info('Aborting wakeup, room is already lit. Bed %r, Living %r, Kitchen %r, Hall %r' %
                (bedroom.is_lit(), living_room.is_lit(), kitchen.is_lit(), hall.is_lit()))
    quit()

command = {'xy': LIGHT_EVENING_XY, 'bri': 1, 'on': True}

bedroom.update(command)
time.sleep(5)

command['bri'] = 254
command['xy'] = LIGHT_DAYTIME_XY
command['transitiontime'] = 10 * 60 * 30

bedroom.update(command)
import time

import RPi.GPIO as GPIO
import settings

from support.logger import get_logger
from support.room import PIN_NO_PIN
from support.time_utils import get_local_time

# Logging
logger = get_logger("motion")

# Motion sensor pin -> Room
PIN_TO_ROOM = {}

for room in settings.ROOMS:
    pin = room.motion_pin
    if pin != PIN_NO_PIN:
        PIN_TO_ROOM[room.motion_pin] = room


def on_motion(triggered_pin: int):
    now = get_local_time()

    is_motion_start = GPIO.input(triggered_pin)

    room = PIN_TO_ROOM[triggered_pin]
    logger.info("Motion %s in %s" %
                (("started" if is_motion_start else "stopped"), room.name))

    # Ignore repeat motion stop events