#!/usr/bin/env python

# Demo showing the effect of frame update duration (stagetime).
#
# Shortest update duration in the demo is 50 msec, but ghosting is evident.
# Larger update duration gives a blacker update, with less ghosting.
# A normal update duration when using partial update is 500 msec.
#
# This demo is based on David Lowe's original demo (https://github.com/campag/eink-demo),
# but uses the fast update mode where you can set the stagetime directly.

from __future__ import (print_function, division)

import os
import sys

from datetime import datetime, timedelta
from PIL import Image
from PIL import ImageDraw, ImageFont
from papirus import Papirus

if sys.version_info < (3,):
    def b(x):
        return x
else:
    def b(x):
        return x.encode('ISO-8859-1')

# Check EPD_SIZE is defined
EPD_SIZE=0.0
if os.path.exists('/etc/default/epd-fuse'):
    exec(open('/etc/default/epd-fuse').read())
if EPD_SIZE == 0.0:
    print("Please select your screen size by running 'papirus-config'.")
    sys.exit()

# Running as root only needed for older Raspbians without /dev/gpiomem
if not (os.path.exists('/dev/gpiomem') and os.access('/dev/gpiomem', os.R_OK | os.W_OK)):
    user = os.getuid()
    if user != 0:
        print("Please run script as root")
        sys.exit()

epd = Papirus()

SCREEN_WIDTH  = epd.size[0]
SCREEN_HEIGHT = epd.size[1]

SCREEN_WIDTH-=1
SCREEN_HEIGHT-=1

FONTFILE = '/usr/share/fonts/truetype/freefont/FreeSans.ttf'

SIZE_MED = int(SCREEN_HEIGHT/4)
FONT_MED = ImageFont.truetype(FONTFILE, SIZE_MED)
CHRW_MED = FONT_MED.getsize("0")[0]

WHITE = 1
BLACK = 0

DURATION = 15 # seconds

image = Image.new('1', epd.size, WHITE)
draw = ImageDraw.Draw(image)

def epd_draw(starttime, cycletime, packet_num):

    # Clear drawing
    draw.rectangle([(0,0), (SCREEN_WIDTH, SCREEN_HEIGHT)], fill=WHITE, outline=WHITE)

    # Draw radar
    draw.ellipse([((SCREEN_WIDTH-SCREEN_HEIGHT)/2,0),(SCREEN_HEIGHT+(SCREEN_WIDTH-SCREEN_HEIGHT)/2, SCREEN_HEIGHT)], outline=BLACK)
    draw.pieslice([((SCREEN_WIDTH-SCREEN_HEIGHT)/2,0),(SCREEN_HEIGHT+(SCREEN_WIDTH-SCREEN_HEIGHT)/2, SCREEN_HEIGHT)], 10*packet_num-2, 10*packet_num+2, fill=BLACK)

    # Stagetime & seconds counter
    with open('/dev/epd/pu_stagetime','r') as f:
        stagetime = f.read().rstrip('\n')
    now = datetime.today()
    seconds = (now - starttime).total_seconds()
    draw.text((SCREEN_WIDTH/2-4.0*CHRW_MED, SCREEN_HEIGHT/2-1.5*SIZE_MED), "%s  %02ds" %(stagetime, seconds), fill=BLACK, font=FONT_MED)

    # fps
    fpsint = 1000//cycletime
    fpsfract = 10000//cycletime - fpsint*10
    draw.text((SCREEN_WIDTH/2-3.0*CHRW_MED, SCREEN_HEIGHT/2-0.5*SIZE_MED), "%02d.%1dfps" %(fpsint, fpsfract), fill=BLACK, font=FONT_MED)

    # Cycle time
    draw.text((SCREEN_WIDTH/2-2.5*CHRW_MED, SCREEN_HEIGHT/2+0.5*SIZE_MED), "%03dms" %cycletime, fill=BLACK, font=FONT_MED)

    # Swap rendered image to epd image buffer
    epd.display(image)
    if cycletime > 0:
        epd.fast_update()

    return

# Main entry

times = [500, 200, 100, 75, 50] # stagetimes in msec
for time in times:

    epd.use_lm75b = True
    epd.clear()

    epd.use_lm75b = False
    # Set stagetime
    with open('/dev/epd/pu_stagetime', 'wb') as f:
        f.write(b(str(time)))

    counter=0
    frametime=-1  # No screen update for first frame

    try:
        starttime = datetime.now()
        delta = timedelta(seconds = DURATION)
        while (True):
            prev=datetime.now()
            epd_draw(starttime,frametime,counter)
            curr=datetime.now()
            if (curr - starttime) > delta:
                break
            frametime=(curr-prev).seconds*1000 + (curr - prev).microseconds/1000
            counter += 1
    except KeyboardInterrupt:
        print("\nClearing panel for long term storage")
        break;

epd.use_lm75b = True
epd.clear()
epd.clear()
