#!/usr/bin/python3
# -*- coding: utf-8 -*-
# -*- mode: Python -*-


'''

redilysis_lines
v0.1.0

Add a line on every frame and scroll  

see https://git.interhacker.space/teamlaser/redilysis for more informations
about the redilysis project

LICENCE : CC

by cocoa


'''
from __future__ import print_function
import argparse
import ast
import os
import math
import random
import redis
import sys
import time 
name = "generator::redilysis_lines"

def debug(*args, **kwargs):
    if( verbose == False ):
        return
    print(*args, file=sys.stderr, **kwargs)
def msNow():
    return time.time()

CHAOS       = 1
REDIS_FREQ  = 33

# General Args
argsparser = argparse.ArgumentParser(description="Redilysis filter")
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose")
# Redis Args
argsparser.add_argument("-i","--ip",help="IP address of the Redis server ",default="127.0.0.1",type=str)
argsparser.add_argument("-p","--port",help="Port of the Redis server ",default="6379",type=str)
argsparser.add_argument("-F","--redis-freq",help="Query Redis every x (in milliseconds). Default:{}".format(REDIS_FREQ),default=REDIS_FREQ,type=int)
# General args
argsparser.add_argument("-n","--nlines",help="number of lines on screen",default=60,type=int)
argsparser.add_argument("-x","--centerX",help="geometrical center X position",default=400,type=int)
argsparser.add_argument("-y","--centerY",help="geometrical center Y position",default=400,type=int)
argsparser.add_argument("-W","--max-width",help="geometrical max width",default=800,type=int)
argsparser.add_argument("-H","--max-height",help="geometrical max height",default=800,type=int)
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)

args        = argsparser.parse_args()
verbose     = args.verbose
ip          = args.ip
port        = args.port
fps         = args.fps
centerX     = args.centerX
centerY     = args.centerY
redisFreq   = args.redis_freq / 1000
maxWidth    = args.max_width
maxHeight   = args.max_height
nlines      = args.nlines
optimal_looptime = 1 / fps

redisKeys   = ["spectrum_120","spectrum_10"] 
debug(name,"Redis Keys:{}".format(redisKeys))
redisData = {}
redisLastHit = msNow() - 99999
r = redis.Redis(
        host=ip,
        port=port)

white = 16777215
lineList = []

scroll_speed = int(maxHeight / nlines )
line_length = int(maxWidth / 10)
line_pattern = []

def rgb2int(rgb):
    #debug(name,"::rgb2int rbg:{}".format(rgb))
    return int('0x%02x%02x%02x' % tuple(rgb),0)

def spectrum_10( ):
    delList = []
    spectrum = ast.literal_eval(redisData["spectrum_10"])
    debug( name, "spectrum:{}".format(spectrum))
    # scroll lines
    for i,line in enumerate(lineList):
        skip_line = False
        new_y = int(line[0][1] + scroll_speed)
        if( new_y >= maxHeight ):
            debug(name,"{} > {}".format(new_y,maxHeight))
            debug(name,"delete:{}".format(i))
            delList.append(i)
            continue 

        for j,point in enumerate(line):
            line[j][1] = new_y
        lineList[i] = line

    for i in delList:
        del lineList[i]

    # new line
    currentLine = []
    for i in range(0,10):
        x = int(i * line_length)
        y = 0
        # get frequency level
        level = spectrum[i]
        # get color
        comp = int(255*level)
        color = rgb2int( (comp,comp,comp))
        # new point
        currentLine.append( [x,y,color] )

    # add line to list
    lineList.append( currentLine)


def refreshRedis():
    global redisLastHit
    global redisData
    # Skip if cache is sufficent
    diff = msNow() - redisLastHit
    if diff < redisFreq : 
        #debug(name, "refreshRedis not updating redis, {} < {}".format(diff, redisFreq))
        pass 
    else:
        #debug(name, "refreshRedis updating redis, {} > {}".format(diff, redisFreq))
        redisLastHit = msNow() 
        for key in redisKeys:
            redisData[key] = r.get(key).decode('ascii')
            #debug(name,"refreshRedis key:{} value:{}".format(key,redisData[key]))
    # Only update the TTLs 
    if 'bpm' in redisKeys:
        redisData['bpm_pttl'] = r.pttl('bpm')
        #debug(name,"refreshRedis key:bpm_ttl value:{}".format(redisData["bpm_pttl"]))
    #debug(name,"redisData:{}".format(redisData))
    return True

def linelistToPoints( lineList ):
    pl = []
    for i,line in enumerate(lineList):
        # add a blank point
        pl.append([ line[0][0], line[0][1], 0 ])
        # append all the points of the line
        pl += line
    #debug(name,"pl:{}".format(pl))
    debug(name,"pl length:{}".format(len(pl)))
    return pl

try:
    while True:
      refreshRedis()
      start = time.time()
      # Do the thing 
      pointsList =  spectrum_10()
      print( linelistToPoints(lineList), flush=True )
      looptime = time.time() - start
      # debug(name+" looptime:"+str(looptime))
      if( looptime < optimal_looptime ):
        time.sleep( optimal_looptime - looptime)
        # debug(name+" micro sleep:"+str( optimal_looptime - looptime))
except EOFError:
    debug(name+" break")# no more information

