# -*- python -*-

# This example graciously fades out the screen on start and
# in on exit. It is a nice alternative to turning off the
# monitor, just press Control+c when you wake up.


# Copyright © 2014  Mattias Andrée (maandree@member.fsf.org)
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


# The (zero-based) index of the monitors (CRTC:s) to apply
# settings to. An empty list means that all monitors are used,
# but all monitors will have the same settings.
monitors = []


# These settings are lists. This is to allow you to use different
# settings on different monitors. For example, `gamma_red = [1]`,
# this means that the red gamma is 1 on all monitors. But if we
# change this to `gamma_red = [1.0, 1.1]`, the first monitor will
# have the red gamma set to 1,0 and the second monitor will have
# the red gamma set to 1,1. If you have more monitors than used
# in the settings modulo division will be used. For instance, if
# you have four monitors, the third monitor will have the same
# settings as the first monitor, and the fourth monitor will have
# the same settings as the second monitor.

# Gamma correction for the red, green and blue components, respectively.
gamma_red, gamma_green, gamma_blue = [1], [1], [1]

# The red, green and blue brightness, respectively.
# If you zero out green and blue and leave only red, you
# will be able to see what is on the as long as their is
# a difference in the red channel, and it will not affect
# your night vision. This is perfect if want to be able
# able read something on the screen during night (perhaps
# a clock) or directly when you wake up.
redness, greenness, blueness = [0.25], [0], [0]


# Set fade time at start to 15 seconds.
fadein_time = 15
# Do 10 changes per second at start.
fadein_steps = fadein_time * 10

# Set fade time at exit to 30 seconds.
fadeout_time = 30
# Do 10 changes per second at end.
fadeout_steps = fadeout_time * 10


# During sleep mode the changes will occur so we update one every hour.
wait_period = 60 * 60


def periodically(year, month, day, hour, minute, second, weekday, fade):
    '''
    Invoked periodically
    
    If you want to control at what to invoke this function next time
    you can set the value of the global variable `wait_period` to the
    number of seconds to wait before invoking this function again.
    The value does not need to be an integer.
    
    @param  year:int     The year
    @param  month:int    The month, 1 = January, 12 = December
    @param  day:int      The day, minimum value is 1, probable maximum value is 31 (*)
    @param  hour:int     The hour, minimum value is 0, maximum value is 23
    @param  minute:int   The minute, minimum value is 0, maximum value is 59
    @param  second:int   The second, minimum value is 0, probable maximum value is 60 (**)
    @param  weekday:int  The weekday, 1 = Monday, 7 = Sunday
    @param  fade:float?  Blueshift can use this function to fade into a state when it start
                         or exits. `fade` can either be negative, zero or positive or `None`,
                         but the magnitude of value cannot exceed 1. When Blueshift starts,
                         this function will be invoked multiple with the time parameters
                         of the time it is invoked and each time `fade` will increase towards
                         1, starting at 0, when the value is 1, the settings should be applied
                         to 100 %. After this this function will be invoked once again with
                         `fade` being `None`. When Blueshift exits the same behaviour is used
                         except, `fade` decrease towards -1 but start slightly below 0, when
                         -1 is reached all settings should be normal. Then Blueshift will NOT
                         invoke this function with `fade` being `None`, instead it will by
                         itself revert all settings and quit.
    
    (*)  Can be exceeded if the calendar system is changed, like in 1712-(02)Feb-30
    (**) See https://en.wikipedia.org/wiki/Leap_second
    '''
    purity = 0 if fade is None else 1 - abs(fade)
    for m in range(max(1, len(monitors))):
        # Remove settings from last run.
        start_over()
        
        # Fade out the blue colours component, then the green
        # colours component and lastly the blue colours component.
        r = min(max(0, purity * 3 - 0), 1)
        g = min(max(0, purity * 3 - 1), 1)
        b = min(max(0, purity * 3 - 2), 1)
        r = redness  [m % len(redness)]   * (1 - r) + r
        g = greenness[m % len(greenness)] * (1 - g) + g
        b = blueness [m % len(blueness)]  * (1 - b) + b
        rgb_brightness(r, g, b)
        
        # Flush settings to monitor.
        r = gamma_red  [m % len(gamma_red)]
        g = gamma_green[m % len(gamma_green)]
        b = gamma_blue [m % len(gamma_blue)]
        gamma(r, g, b)
        
        # Flush settings to monitor.
        if len(monitors) == 0:
            (drm if ttymode else randr)()
        else:
            (drm if ttymode else randr)(monitors[m % len(monitors)])


def reset():
    '''
    Invoked to reset the displays
    '''
    for m in range(max(1, len(monitors))):
        # Remove settings from last run.
        start_over()
        
        # Apply gamma correction to monitor.
        r = gamma_red  [m % len(gamma_red)]
        g = gamma_green[m % len(gamma_green)]
        b = gamma_blue [m % len(gamma_blue)]
        gamma(r, g, b)
        
        # Flush settings to monitor.
        if len(monitors) == 0:
            (drm if ttymode else randr)()
        else:
            (drm if ttymode else randr)(monitors[m % len(monitors)])