#! /usr/local/bin/python3
from io import BytesIO
from numpy import asarray
from PIL import Image
from redis import Redis
import base64
import json
import os
import potrace
import re
import time

color = 65280
environ = os.environ
host = environ['DB_HOST'] if 'DB_HOST' in os.environ else "localhost"
port = environ['DB_PORT'] if 'DB_PORT' in os.environ else 6379
r         = Redis(host=host, port=port)


def convertImg(src, image_path="/tmp/"):
    base64_data = re.sub('^data:image/.+;base64,', '', src)
    byte_data = base64.b64decode(base64_data)
    image_data = BytesIO(byte_data)
    img = Image.open(image_data).convert("1")
    return img

# Read results from redis
data = r.lpop('image-convert')
while data :
  try:
    item = json.loads(data)
    image_data    = item["image_data"]
    text          = item["text"]
    hash_name     = item["hash_name"]

    # Vectorize the image
    image         = convertImg( image_data )
    bmp           = potrace.Bitmap( asarray( image ) )

    # Trace the bitmap to a path
    path          = bmp.trace(turdsize=16,alphamax=0.0, opticurve=0, opttolerance=1.0)


    # Record the min/max coordinates and a list of points 
    min_x         = 0
    min_y         = 0
    max_x         = -9999
    max_y         = -9999

    pl            = []
    pl_index      = 0
    odd_indices   = []
    def plappend( point ):
      global pl, pl_index, odd_indices, min_x, min_y, max_x, max_y
      pl.append(point)
      pl_index    += 1
      suspect     = False
      
      if point[0] <= min_x : 
        min_x     = point[0]
        suspect   = True 
      if point[0] >= max_x : 
        max_x     = point[0]
        suspect   = True 
      if point[1] <= min_y : 
        min_y     = point[1]
        suspect   = True 
      if point[1] >= max_y : 
        max_y     = point[1]
        suspect   = True 
      if suspect == True:   
        odd_indices.append(pl_index)
        return True
      return False


    for curve in path:
      start     = curve.start_point
      plappend([int(start[0]),int(start[1]),0])
      plappend([int(start[0]),int(start[1]),color])
      for segment in curve:
        end_point_x, end_point_y = segment.end_point
        if segment.is_corner:
          c_x, c_y = segment.c
          plappend([int(c_x),int(c_y),color])
          pass
        #
        else:
          c1_x, c1_y = segment.c1
          x, y = segment.c2
          plappend([int(x),int(y),color])
          plappend([int(c1_x),int(c1_y),color])
      #
      plappend([int(start[0]),int(start[1]),0])

    # Run the border detection
    def isBorder( pt ):
      result = []
      # calculate the distance to min/max
      min_x_dst = abs(min_x - pt[0])
      max_x_dst = abs(max_x - pt[0])
      min_y_dst = abs(min_y - pt[1])
      max_y_dst = abs(max_y - pt[1])
      if min_x_dst <= 1 :
        result.append("min_x")
      if max_x_dst <= 1 :
        result.append("max_x")
      if min_y_dst <= 1 :
        result.append("min_y")
      if max_y_dst <= 1 :
        result.append("max_y")
      return result

    deleteList = []
    for i in range(len(odd_indices) - 1) :
        ind             = odd_indices[i]
        pt              = pl[ind]
        nextpt          = pl[ind+1]
        # Early skip black points
        if 0 == pt[2] or 0 == nextpt[2]:
            continue
        pt_is_bord      = isBorder(pt)
        nextpt_is_bord  = isBorder(nextpt)
        if 0 == len(pt_is_bord) or 0 == len(nextpt_is_bord):
            continue
        #print( "{} and {} are border.".format(pt,nextpt))
        deleteList.append(ind)
        deleteList.append(ind+1)

    deleteList = sorted(set(deleteList), reverse=True)
    for i in deleteList:
        pl[i] = [pl[i][0],pl[i][1],0]
    item["points_list"] = pl
    item["created_at"]  = time.time()
    r.hset("images",hash_name, json.dumps(item))
    print("Handled image {}".format(hash_name))
    data = r.lpop('image-convert')

  except Exception as e:
    print("woops",e)
    break
