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


'''

kaleidoscop
v0.1.0

A simple effect : mirror a quadrant of the input

LICENCE : CC

by Sam Neurohack


'''
from __future__ import print_function
import sys
import ast
import os
import argparse
ljpath = r'%s' % os.getcwd().replace('\\','/')
sys.path.append(ljpath +'/../libs/')
sys.path.append(ljpath +'/libs/')

import time 
name = "filters::kaleidoscope"

argsparser = argparse.ArgumentParser(description="Redis exporter LJ")
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("-f","--fps",help="Frame Per Second",default=30,type=int)
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose")

args    = argsparser.parse_args()
fps     = args.fps
centerX = args.centerX
centerY = args.centerY
verbose = args.verbose

optimal_looptime = 1 / fps

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

def kaleidoscope( pl ):

    # Stage 1: Crop points in single quadrant
    quad1 = []
    # Iterate trough the segments 
    for i in range( 0, len(pl) ):
            
        #debug(name+" point #", i)
        currentpoint = cp = pl[i]
        cx,cy,cc = [cp[0],cp[1],cp[2]]

        # Exception: escape early if last point
        if i == len(pl) - 1:
            if cx >= centerX and cy >= centerY :
                quad1.append( currentpoint )
            break 

        # Search for the couple of points
        nextpoint = pl[i+1]
        nx,ny,nc = [nextpoint[0],nextpoint[1],nextpoint[2]]
        rect=[[cx,cy],[cx,ny],[nx,ny],[nx,cy]]
        
        right = wrong = 0
        #debug(name+" rect: ", rect,"curr",currentpoint,"next",nextpoint )

        # Enumerate the points in rectangle to see 
        # how many right / wrong there are 
        # either to add or skip early
        for iterator, p in enumerate(rect):
            if p[0] >= centerX and p[1] >= centerY:
                right += 1
            else:
                #if p[0] <= centerX and p[1] <= centerY:
                wrong += 1 
        # If all rectangle points are in the right quadrant, Add and Skip  
        if right == 4:
            quad1.append(pl[i])
            #debug(name+" found valid point", pl[i])
            continue
        # If all rectangle points in wrong quadrant, Skip
        if wrong == 4:
            #debug(name+" found bad point", pl[i])
            continue

        # Find the (x,y) intersections
        # 
        #debug(name+" Looking for crossing point between ("+str(cx)+","+str(cy)+") and ("+str(nx)+","+str(ny)+")") 
        delta=[ nx - cx, ny - cy ]
        #debug(name+" delta:",delta)
        crossX = None
        crossY = None
        absnewX = 0
        absnewY = 0
        # If one point has negative x, search y axis crossing
        if cx < centerX or nx < centerX:
            if delta[0] == 0 :
                delta[0] = 0.0000001
            v=[ delta[0]/abs(delta[0]), delta[1]/abs(delta[0]) ]
            absnewX = abs( centerX - cx )
            #print("on y axis, v=",str(v)," and absnewX=",str(absnewX))
            crossX = [( absnewX*v[0] + cx ),( absnewX*v[1]+cy ), nc]
        # If one point has negative y, search x axis crossing
        if cy < centerY or ny < centerY:
            if delta[1] == 0 :
                delta[1] = 0.0000001
            v=[ delta[0]/abs(delta[1]), delta[1]/abs(delta[1])]
            absnewY = abs( centerY - cy )
            #print("on x axis, v=",str(v)," and absnewY=",str(absnewY))
            crossY = [( absnewY*v[0] + cy ),( absnewY*v[1]+cy ), nc]
        # Inject in order
        # If current point is the quadrant, add it 
        if cx >= centerX and cy >= centerY :
            quad1.append( currentpoint )
        # If absnewX smaller, it is closest to currentPoint
        if absnewX < absnewY:
            if None != crossX : quad1.append( crossX )
            if None != crossY : quad1.append( crossY )
        else : 
            if None != crossY : quad1.append( crossY ) 
            if None != crossX : quad1.append( crossX )
        # Add a black point at the end
        #lastQuad1Point = quad1[-1]
        #quad1.append( [lastQuad1Point[0],lastQuad1Point[1],0] )

    ## Stage 2 : Mirror points
    #
    quad2 = []
    # quad2 = vertical symetric of quad1 
    for iterator in range( len(quad1) -1 , -1, -1):
        point = quad1[iterator]
        quad2.append([ point[0], 2*centerY - point[1], point[2] ])
    # quad3 is the merge of 1 and 2
    quad3 = quad1 + quad2
    # quad4 is the horizontal symetric of quad3
    quad4 = []
    for iterator in range( len(quad3) -1, -1, -1):
        point = quad3[iterator]
        quad4.append([ 2*centerX - point[0], point[1], point[2] ])

    #debug(name+" quad1:",quad1)
    #debug(name+" quad2:", quad2 )
    #debug(name+" quad3:", quad3 )
    #debug(name+" quad4:", quad4 )
    return quad3+quad4
  
try:
    while True:
      start = time.time()
      line = sys.stdin.readline()
      if line == "":
         time.sleep(0.01)
      line = line.rstrip('\n')
      pointsList = ast.literal_eval(line)
      # Do the filter
      result = kaleidoscope( pointsList ) 
      print( result, 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

