import sys
sys.path.append('../lsmaker')
import os
import numpy as np
import pandas as pd
from shapely.geometry import LineString
#from GISio import df2shp

def get_ls_skiprows_nrows(xtr):
    with open(xtr) as f:
        knt = 0
        while True:
            line = next(f)
            knt += 1
            if '! head specified line sinks' in line:
                skiprows = knt + 1
            if '! stream linkages' in line:
                nrows = knt - skiprows -1
                break
    return skiprows, nrows

def get_linesink_results(xtr):
    """Read linesink results from GFLOW extract (.xtr) file into dataframe.
    """
    names = ['x1',
             'y1',
             'x2',
             'y2',
             'spec_head',
             'calc_head',
             'discharge',
             'width',
             'resistance',
             'depth',
             'baseflow',
             'overlandflow',
             'BC_pct_err',
             'label']
    ls_skiprows, nrows = get_ls_skiprows_nrows(xtr)

    return pd.read_csv(xtr, skiprows=ls_skiprows, nrows=nrows, header=None, names=names)

def plot_flooding_arcpy(grdfile, dem,
                        outpath='flooding',
                        solver_x0=0, solver_y0=0, scale_xy=0.3048, epsg=None,
                        dem_mult=0.3048, nearfield=None,
                        resample_heads=True, resample_cellsize=10):
    """Subtract gridded heads from GFLOW from DEM; save results as raster.
    (requires arcpy and rasterio)

    gridfile: str
        Gridded heads file output from GFLOW (*.GRD)
    dem:
        DEM for model area.
    outpath :
        Folder for writing output raster(s) to.
    solver_x0 : float
    solver_y0 : float
        To get the solve origin (solver_x0, solver_y0), in GFLOW choose Tools > GFLOW Database Viewer,
        then View > Base Tables > Model.
    scale_xy : float
        Multiplier to convert GFLOW coordinates to GIS coordinates.
    epsg : int
        EPSG code for GIS projected coordinate system (e.g. 26715 for NAD27 UTM zone 15)
    dem_mult : float
        Multiplier from DEM elevation units to GFLOW units.
    nearfield : str
        Shapefile of model nearfield.
    resample_heads : boolean
        Resample gridded GFLOW heads (typically coarse) to finer resolution using bilinear interpolation).
    resample_cellsize : float
        Cellsize for resampled heads (typically same as DEM resolution).

    Notes
    =====

    """
    try:
        import arcpy
    except:
        print('Method requires arcpy.')
        return

    if not os.path.isdir(outpath):
        os.makedirs(outpath)
    arcpy.env.workspace = outpath
    #arcpy.Delete_management('*')
    arcpy.env.overwriteOutput = True
    arcpy.CheckOutExtension('Spatial')

    print('reading {}...'.format(dem))
    demft = arcpy.Raster(dem) * dem_mult
    solver_x0 = solver_x0
    solver_y0 = solver_y0
    wtfile = os.path.join(outpath,'heads_prj.tiff')
    print('reading {}...'.format(grdfile))
    hds = surferGrid(grdfile)
    hds.scale_xy(scale_xy)
    hds.offset_xy(solver_x0, solver_y0)
    hds.write_raster(wtfile, epsg=epsg)

    arcpy.Resample_management(wtfile, 'wtfile_rs', resample_cellsize, "BILINEAR")
    flooding = arcpy.sa.Minus(demft, 'wtfile_rs')
    arcpy.MakeFeatureLayer_management(nearfield, 'nf')
    arcpy.Clip_management(flooding,'#', 'fldcp', nearfield, "#", "ClippingGeometry")
    flooding = arcpy.sa.SetNull('fldcp', 'fldcp', "VALUE > 0")
    print('writing {}/flooding...'.format(outpath))
    flooding.save('flooding')

def write_streamflow_shapefile(xtr, outshp=None, solver_x0=0, solver_y0=0,
                               coords_mult=0.3048, epsg=None):
    """Read linesink results from GFLOW extract (.xtr) file and write to shapefile.
    To get the solve origin (solver_x0, solver_y0), in GFLOW choose Tools > GFLOW Database Viewer,
    then View > Base Tables > Model.
    """
    if outshp is None:
        outshp = '{}_streamflow.shp'.format(xtr[:-4])
    df = get_linesink_results(xtr)
    df = df[df.resistance.values > 0].copy() # only include
    df[['x1', 'x2']] = df[['x1', 'x2']] * coords_mult + solver_x0
    df[['y1', 'y2']] = df[['y1', 'y2']] * coords_mult + solver_y0
    df['geometry'] = [LineString([(r.x1, r.y1), (r.x2, r.y2)]) for i, r in df.iterrows()]
    GISio.df2shp(df, outshp, epsg=epsg)

class surferGrid:
    def __init__(self, grdfile=None, data=None):
        self.header = None
        self.nrow = None
        self.ncol = None
        self.xmin = None
        self.xmax = None
        self.ymin = None
        self.ymax = None
        self.zmax = None
        self.zmin = None
        self.data = data
        if grdfile is not None:
            self.read_grd(grdfile)

    def _read_grd_header(self, grdfile):
        with open(grdfile) as input:
            self.header = input.next()
            self.nrow, self.ncol = map(int, input.next().strip().split())
            self.xmin, self.xmax = map(float, input.next().strip().split())
            self.ymin, self.ymax = map(float, input.next().strip().split())
            self.zmin, self.zmax = map(float, input.next().strip().split())

    def scale_xy(self, mult=1):
        self.xmin *= mult
        self.xmax *= mult
        self.ymin *= mult
        self.ymax *= mult

    def scale_z(self, mult=1):
        self.zmin *= mult
        self.zmax *= mult

    def offset_xy(self, x0=0, y0=0):
        self.xmin += x0
        self.xmax += x0
        self.ymin += y0
        self.ymax += y0

    def read_grd(self, grdfile):
        self._read_grd_header(grdfile)
        data = np.loadtxt(grdfile, skiprows=5)
        self.data = np.reshape(data, (self.ncol, self.nrow))

    def write_grd(self, fname='output.grd'):

        with open(fname, 'w') as output:
            header = self.header.strip() + '\n'
            header += '{:.0f} {:.0f}\n'.format(self.nrow, self.ncol)
            header += '{:.2f} {:.2f}\n'.format(self.xmin, self.xmax)
            header += '{:.2f} {:.2f}\n'.format(self.ymin, self.ymax)
            header += '{:.2f} {:.2f}'.format(self.zmin, self.zmax)
            np.savetxt(output, self.data, fmt='%.2f', delimiter=' ', header=header, comments='')

    def write_raster(self, fname='output', epsg=None):
        try:
            import rasterio
            from rasterio import transform
        except ImportError:
            print('This method requires Rasterio')
            return

        tfm = transform.from_bounds(self.xmin, self.ymin, self.xmax, self.ymax, self.ncol, self.nrow)
        if epsg is not None:
            crs = {'init': 'epsg:{}'.format(epsg)}
        else:
            crs = None

        with rasterio.drivers():
            with rasterio.open(fname,
                               'w',
                               driver='GTiff',
                               width=self.ncol,
                               height=self.nrow,
                               count=1,
                               dtype=np.float64,
                               nodata=0,
                               transform=tfm,
                               crs=crs) as dst:
                dst.write_band(1, np.flipud(self.data))


import os
import io,zipfile,tarfile
from pyspark import SparkContext
from pprint import pprint
import numpy as np
from numpy import genfromtxt
from pyspark.sql import SparkSession
import tensorflow as tf
from sklearn.datasets import load_boston
from sklearn.utils import shuffle
from sklearn.metrics import mean_absolute_error
from scipy.stats import pearsonr, zscore
import matplotlib.pyplot as plt
def get_np_csv(zfBytes):
 #given a zipfile as bytes (i.e. from reading from a binary file),
# return a np array of rgbx values for each pixel
     name = zfBytes[0]
     zfBytes = zfBytes[1]
     d =dict()
     bytesio = io.BytesIO(zfBytes)
     tfiles = tarfile.open(fileobj=bytesio,mode="r")
     #find tif:
     pprint("control here")
     for fn in tfiles.getnames():

            if fn[-4:] == '.csv':#found it, turn into array:
                    #pprint(name + "/" + fn)
                    #tif = TiffFile(io.BytesIO(zfiles.open(fn).read()))
                    obj=tfiles.extractfile(fn)
                    #pprint(obj)
                    my_data = genfromtxt(obj, delimiter=',',skip_header=True)
                    #pprint(my_data.shape)
                    my_data = my_data[:8736, :3]
                    pprint(my_data.shape)
                    my_data = np.split(my_data, 52)
                    for i, x in enumerate(my_data):
                         my_data[i] = np.sum(my_data[i], axis=0)
                    my_data = np.array(my_data)
                    #pprint(fn)
                    fn1= "".join(fn.split("/")[1].split('_')[:-1])
                    fn1=fn1[:fn1.find("2004")]
                    fn2 = fn.split("/")[0][0:6]
                    fn=fn1+fn2
                    #pprint(fn)
                    d[fn]=my_data

     return list(d.items())
def map1(kv):
    l=[]
    pprint(kv)
    for x in kv[1]:
        l.append(x)
    return l
sc=SparkContext("local[*]","aa")
path="C:/Users/esais/Desktop/big_data/project/21/"
path1="C:/Users/esais/Desktop/big_data/project/2/"
#rdd1=sc.pickleFile(path1+"temp").union(sc.pickleFile(path1+"temp2")).union(sc.pickleFile(path1+"temp3")).union(sc.pickleFile(path1+"temp4")).union(sc.pickleFile(path1+"temp5")).union(sc.pickleFile(path1+"temp6")).union(sc.pickleFile(path1+"temp7")).union(sc.pickleFile(path1+"temp8")).union(sc.pickleFile(path1+"temp9")).union(sc.pickleFile(path1+"temp10"))
#final_rdd=rdd1.reduceByKey(lambda x,y : np.add(x,y))
def evaluateBetasOverTest(betas, X_test, y_test):
 y_pred = np.matmul(X_test, betas)[:,0]
 print(len(y_pred))
 plt.plot(range(41,51),y_pred.tolist())
 plt.show()
 print("Mean Absolute Error:", mean_absolute_error(y_test, y_pred))
 print("Pearson Correlation:", pearsonr(y_test, y_pred))

rdd1=sc.pickleFile(path1+"part10")
kv = rdd1.collect()
kv1=[]
for i,x in enumerate(kv):

    kv1.append([kv[i][0],kv[i][1].tolist()])
#pprint(kv1)
data = kv1[0][1]

data = np.asarray(data)
data=data[0:,1]
price=data[3:]
plt.plot(range(52),data.tolist())
xt1=data[2:-1]
xt2=data[1:-2]
xt3=data[0:-3]
print(xt1.shape,xt2.shape,xt3.shape)
features = np.vstack((xt1,xt2,xt3)).transpose()
#print(features)
featuresZ = zscore(features)
#pprint(featuresZ[:5])
featuresZ_pBias = np.c_[np.ones((featuresZ.shape[0], 1)), featuresZ]
offset = int(featuresZ_pBias.shape[0] * 0.8)
featuresZ_pBias_test, price_test = featuresZ_pBias[offset:], price[offset:]
featuresZ_pBias, price = featuresZ_pBias[:offset], price[:offset]
#X = tf.constant(featuresZ_pBias, dtype=tf.float32, name="X")
#y = tf.constant(price.reshape(-1,1), dtype=tf.float32, name="y")

#Xt = tf.transpose(X)
#penalty = tf.constant(1.0, dtype=tf.float32, name="penalty")
#I = tf.constant(np.identity(featuresZ_pBias.shape[1]), dtype=tf.float32, name="I")

#beta = tf.matmul(tf.matmul(tf.matrix_inverse(tf.matmul(Xt, X) + penalty*I), Xt), y)

### everything above is just definitions of operations to carry out over tensors
### now let's create a session to run the operations
#with tf.Session() as sess:
#  beta_value = beta.eval()

#print(beta_value)
#evaluateBetasOverTest(beta_value, featuresZ_pBias_test, price_test)
finaly = []
def testL2Reg(penalty_value = 1000, learning_rate = 0.001, n_epochs = 300):
 X = tf.constant(featuresZ_pBias, dtype=tf.float32, name="X")
 y = tf.constant(price.reshape(-1,1), dtype=tf.float32, name="y")
 Xt = tf.transpose(X)
 penalty = tf.constant(penalty_value, dtype=tf.float32, name="penalty")
# I = tf.constant(np.identity(featuresZ_pBias.shape[1]), dtype=tf.float32, name="I")
 beta = tf.Variable(tf.random_uniform([featuresZ_pBias.shape[1], 1], -1., 1.), name = "beta")
 y_pred = tf.matmul(X, beta, name="predictions")
 penalizedCost = tf.reduce_sum(tf.square(y - y_pred)) #+ penalty * tf.reduce_sum(tf.square(beta))
 optimizer = tf.train.GradientDescentOptimizer(learning_rate = learning_rate)
 training_op = optimizer.minimize(penalizedCost)
 init = tf.global_variables_initializer()
 with tf.Session() as sess:
  sess.run(init)
  for epoch in range(n_epochs):
   if epoch %10 == 0: #print debugging output
    print("Epoch", epoch, "; penalizedCost =", penalizedCost.eval())
   sess.run(training_op)
  #done training, get final beta:
  best_beta = beta.eval()
  pred = y_pred.eval()
  plt.plot(range(3,42),pred)

 print(best_beta)
 evaluateBetasOverTest(best_beta, featuresZ_pBias_test, price_test)
testL2Reg(1)
#pprint(featuresZ_pBias[:5])
#pprint(data)

#values=np.asarray(values)
#np.savetxt(path1+"foo.csv", values,fmt='%.64f', delimiter=",")
#spark = SparkSession(sc).getOrCreate()
#df = spark.createDataframe(rdd1)

#df.write.csv(path1+"file.csv", sep=',', header=False)
#rdd1.collect()
#zip_rdd = sc.binaryFiles(path+"*")
#np_rdd=zip_rdd.flatMap(get_np_csv)
##countywise weekly data
#np_rdd = np_rdd.map(lambda x : ["".join(x[0].split("/")[1].split('_')[:-1]),x[1]])
#state_rdd = np_rdd.reduceByKey(lambda x,y : np.add(x,y))
#state_rdd.saveAsPickleFile(path1+"part2")
#with open("temp.txt","w") as f:
    #print(state_rdd.collect(),file=f)


#!/usr/bin/env python3
import pygame
import pygame.camera
import time
import os
import PIL.Image
import cups
import RPi.GPIO as GPIO
import subprocess

from shutil import copyfile
from threading import Thread
from pygame.locals import *
from time import sleep
from PIL import Image, ImageDraw
from subprocess import *

# initialise global variables
Numeral = ""  # Numeral is the number display
Message = ""  # Message is a fullscreen message
SubMessage = ""
LongMessage = ""
BackgroundColor = ""
CountDownPhoto = ""
CountPhotoOnCart = ""
SmallMessage = ""  # SmallMessage is a lower banner message
TotalImageCount = 0  # Counter for Display and to monitor paper usage
PhotosPerCart = 30  # Selphy takes 16 sheets per tray
imagecounter = 0
imagefolder = 'Photos'
backupfolder = '/media/pi/90B6-124C/trouw'
templatePath = os.path.join('Photos', 'Template', "template.png") #Path of template image
ImageShowed = False
Printing = False
BUTTON_PIN = 25
IMAGE_WIDTH = 594
IMAGE_HEIGHT = 445
image_size = (IMAGE_WIDTH, IMAGE_HEIGHT)
os.environ["SDL_AUDIODRIVER"] = "dsp"

# Load the background template
bgimage = PIL.Image.open(templatePath)

#Setup GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# initialise pygame
pygame.init()  # Initialise pygame
pygame.font.init()
pygame.camera.init()
pygame.mouse.set_visible(False)
# pygame.mouse.set_visible(False) #hide the mouse cursor
infoObject = pygame.display.Info()
screen_size = (infoObject.current_w,infoObject.current_h)
screen = pygame.display.set_mode(screen_size, pygame.FULLSCREEN)  # Full screen  , pygame.FULLSCREEN
background = pygame.Surface(screen_size)  # Create the background object
background = background.convert()  # Convert it to a background

screenPicture = pygame.display.set_mode(screen_size, pygame.FULLSCREEN)  # Full screen
backgroundPicture = pygame.Surface(screen_size)  # Create the background object
backgroundPicture = background.convert()  # Convert it to a background

transform_x = infoObject.current_w # how wide to scale the jpg when replaying
transfrom_y = infoObject.current_h # how high to scale the jpg when replaying

# Initialise the camera object
# camera.resolution = (infoObject.current_w, infoObject.current_h)
camera_resolution = (IMAGE_WIDTH, IMAGE_HEIGHT)
#(infoObject.current_w, infoObject.current_h)
camera_devices = pygame.camera.list_cameras()
camera = pygame.camera.Camera(camera_devices[0],camera_resolution)
# camera.set_controls(True, False, 50)

# A function to handle keyboard/mouse/device input events
def input(events):
    for event in events:  # Hit the ESC key to quit the slideshow.
        if (event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE)):
            pygame.quit()

# set variables to properly display the image on screen at right ratio
def set_demensions(img_w, img_h):
    # Note this only works when in booting in desktop mode.
    # When running in terminal, the size is not correct (it displays small). Why?

    # connect to global vars
    global transform_y, transform_x, offset_y, offset_x

    # based on output screen resolution, calculate how to display
    ratio_h = (infoObject.current_w * img_h) / img_w

    if (ratio_h < infoObject.current_h):
        #Use horizontal black bars
        #print "horizontal black bars"
        transform_y = ratio_h
        transform_x = infoObject.current_w
        offset_y = (infoObject.current_h - ratio_h) / 2
        offset_x = 0
    elif (ratio_h > infoObject.current_h):
        #Use vertical black bars
        #print "vertical black bars"
        transform_x = (infoObject.current_h * img_w) / img_h
        transform_y = infoObject.current_h
        offset_x = (infoObject.current_w - transform_x) / 2
        offset_y = 0
    else:
        #No need for black bars as photo ratio equals screen ratio
        #print "no black bars"
        transform_x = infoObject.current_w
        transform_y = infoObject.current_h
        offset_y = offset_x = 0

def InitFolder():
    global imagefolder
    global Message
    global LongMessage
    global SubMessage

    Message = 'Folder Check...'
    UpdateDisplay()
    Message = ''

    #check image folder existing, create if not exists
    if not os.path.isdir(imagefolder):
        os.makedirs(imagefolder)

    imagefolder2 = os.path.join(imagefolder, 'images')
    if not os.path.isdir(imagefolder2):
        os.makedirs(imagefolder2)

def DisplayText(fontSize, textToDisplay):
    global Numeral
    global Message
    global LongMessage
    global SubMessage
    global screen
    global background
    global pygame
    global ImageShowed
    global screenPicture
    global backgroundPicture
    global CountDownPhoto

    if (BackgroundColor != ""):
        background.fill(pygame.Color("black"))
    if (textToDisplay != ""):
        font = pygame.font.Font(None, fontSize)
        text = font.render(textToDisplay, 1, (227, 157, 200))
        textpos = text.get_rect()
        textpos.centerx = background.get_rect().centerx
        textpos.centery = background.get_rect().centery
        if(ImageShowed):
            backgroundPicture.blit(text, textpos)
        else:
            background.blit(text, textpos)

def UpdateDisplay():
    # init global variables from main thread
    global Numeral
    global Message
    global SubMessage
    global LongMessage
    global screen
    global background
    global pygame
    global ImageShowed
    global screenPicture
    global backgroundPicture
    global CountDownPhoto

    background.fill(pygame.Color("white"))  # White background

    if (BackgroundColor != ""):
        background.fill(pygame.Color("black"))

    if (Message != ""):
        font = pygame.font.SysFont("Brandon Grotesque Bold", 100)
        text = font.render(Message, True, (0, 0, 0))
        textpos = text.get_rect()
        textpos.centerx = background.get_rect().centerx
        textpos.centery = background.get_rect().centery
        if(ImageShowed):
            backgroundPicture.blit(text, textpos)
        else:
            background.blit(text, textpos)

    if(LongMessage != ""):
        font = pygame.font.SysFont("Brandon Grotesque Bold", 80)
        text = font.render(LongMessage, True, (0, 0, 0))
        textpos = text.get_rect()
        textpos.centerx = background.get_rect().centerx
        textpos.centery = background.get_rect().centery - 40
        if(ImageShowed):
            backgroundPicture.blit(text, textpos)
        else:
            background.blit(text, textpos)
        font = pygame.font.SysFont("Brandon Grotesque Bold", 100)
        text = font.render(SubMessage, True, (0, 0, 0))
        textpos = text.get_rect()
        textpos.centerx = background.get_rect().centerx
        textpos.centery = background.get_rect().centery + 40
        if(ImageShowed):
            backgroundPicture.blit(text, textpos)
        else:
            background.blit(text, textpos)

    if (Numeral != ""):
        font = pygame.font.SysFont("Brandon Grotesque Bold", 200)
        text = font.render(Numeral, True, (255, 255, 255))
        textpos = text.get_rect()
        textpos.centerx = background.get_rect().centerx
        textpos.centery = background.get_rect().centery
        if(ImageShowed):
            backgroundPicture.blit(text, textpos)
        else:
            background.blit(text, textpos)

    if (CountDownPhoto != ""):
        #print(displaytext)
        font = pygame.font.SysFont("Brandon Grotesque Bold", 200)
        text = font.render(CountDownPhoto, True, (0, 0, 0))
        textpos = text.get_rect()
        textpos.centerx = background.get_rect().centerx
        textpos.centery = background.get_rect().centery
        if(ImageShowed):
            backgroundPicture.blit(text, textpos)
        else:
            background.blit(text, textpos)

    if(ImageShowed == True):
        screenPicture.blit(backgroundPicture, (0, 0))
    else:
        screen.blit(background, (0, 0))

    pygame.display.flip()
    return

def ShowPicture(file, delay):
    global pygame
    global screenPicture
    global backgroundPicture
    global ImageShowed
    backgroundPicture.fill((0, 0, 0))
    img = pygame.image.load(file)
    img = pygame.transform.scale(img, (1020,780))  # Make the image full screen
    #backgroundPicture.set_alpha(200)
    backgroundPicture.blit(img, (120,0))
    screen.blit(backgroundPicture, (0, 0))
    pygame.display.flip()  # update the display
    ImageShowed = True
    time.sleep(delay)

def ShowResult(file, delay):
    global pygame
    global screenPicture
    global backgroundPicture
    global ImageShowed
    backgroundPicture.fill((255, 255, 255))
    img = pygame.image.load(file)
    img = pygame.transform.scale(img, (320,720))  # Make the image fit screen
    #backgroundPicture.set_alpha(200)
    backgroundPicture.blit(img, (480,0))
    screen.blit(backgroundPicture, (0, 0))
    pygame.display.flip()  # update the display
    ImageShowed = True
    time.sleep(delay)

# display one image on screen
def show_image(image_path):
    screen.fill(pygame.Color("white")) # clear the screen
    img = pygame.image.load(image_path) # load the image
    img = img.convert()
    set_demensions(img.get_width(), img.get_height()) # set pixel dimensions based on image
    x = (infoObject.current_w / 2) - (img.get_width() / 2)
    y = (infoObject.current_h / 2) - (img.get_height() / 2)
    screen.blit(img,(x,y))
    pygame.display.flip()

def CapturePicture():
    global imagecounter
    global imagefolder
    global Numeral
    global Message
    global LongMessage
    global SubMessage
    global screen
    global background
    global screenPicture
    global backgroundPicture
    global pygame
    global ImageShowed
    global CountDownPhoto
    global BackgroundColor

    image = None

    BackgroundColor = ""
    Numeral = ""
    Message = ""
    UpdateDisplay()
    time.sleep(1)
    CountDownPhoto = ""
    UpdateDisplay()
    background.fill(pygame.Color("black"))
    screen.blit(background, (0, 0))
    pygame.display.flip()
    BackgroundColor = "black"

    streaming = True
    countdown = 0
    x = 3
    Numeral = str(x)
    Message = ""

    while streaming:
        if image:
            if camera.query_image():
                image = camera.get_image(image)
        else:
            image = camera.get_image()

        image = pygame.transform.flip(image, True, False)
        image2 = pygame.transform.scale(image, screen_size)
        background.blit(image2, (0, 0))
        font = pygame.font.SysFont("Brandon Grotesque Bold", 200)
        text = font.render(str(x), True, (255, 255, 255))
        textpos = text.get_rect()
        textpos.centerx = background.get_rect().centerx
        textpos.centery = background.get_rect().centery
        background.blit(text, textpos)
        screen.blit(background, (0,0))
        pygame.display.flip()  # update the display
        countdown = countdown + 1
        if countdown == 10:
            x = x - 1
            if x == 0:
                streaming = False
            else:
                countdown = 0
    BackgroundColor = ""
    Numeral = ""
    LongMessage = ""
    Message = ""
    UpdateDisplay()
    photo_ready = camera.query_image()
    time.sleep(0.5)
    while not photo_ready:
        photo_ready = camera.query_image()
    image = camera.get_image(image)
    image = pygame.transform.flip(image, True, False)
    image2 = pygame.transform.scale(image,screen_size)
    image = pygame.transform.scale(image,camera_resolution)
    background.blit(image2, (0, 0))
    screen.blit(background, (0,0))
    imagecounter = imagecounter + 1
    ts = time.time()
    filename = os.path.join(imagefolder, 'images', str(imagecounter)+"_"+str(ts) + '.png')
    pygame.image.save(image, filename)
    #time.sleep(1)
    ShowPicture(filename, 1)
    ImageShowed = False
    return filename

def TakePictures():
    global imagecounter
    global imagefolder
    global backupfolder
    global Numeral
    global Message
    global LongMessage
    global SubMessage
    global screen
    global background
    global pygame
    global ImageShowed
    global CountDownPhoto
    global BackgroundColor
    global Printing
    global PhotosPerCart
    global TotalImageCount

    LongMessage = ""

    input(pygame.event.get())

    camera.start()

    CountDownPhoto = "Foto 1/3"
    filename1 = CapturePicture()

    CountDownPhoto = "Foto 2/3"
    filename2 = CapturePicture()

    CountDownPhoto = "Foto 3/3"
    filename3 = CapturePicture()

    camera.stop()

    CountDownPhoto = ""
    Message = "Even geduld..."
    UpdateDisplay()

    image1 = PIL.Image.open(filename1)
    image2 = PIL.Image.open(filename2)
    image3 = PIL.Image.open(filename3)
    TotalImageCount = TotalImageCount + 1

    bgimage.paste(image1, (57, 194))
    bgimage.paste(image2, (57, 664))
    bgimage.paste(image3, (57, 1137))

    # Create the final filename
    ts = time.time()
    Final_Image_Name = os.path.join(imagefolder, "Final_" + str(TotalImageCount)+"_"+str(ts) + ".png")
    Backup_Image_Name = os.path.join(backupfolder, "Final_" + str(TotalImageCount)+"_"+str(ts) + ".png")
    # Save it to the raspberry SD card and backup to usb drive
    bgimage.save(Final_Image_Name)
    try:
        copyfile(Final_Image_Name, Backup_Image_Name)
    except Exception as filex:
        print("USB not found")
    # Save a temp file, its faster to print from the pi than usb
    temppath = os.path.join('Temp', 'tempprint.png')
    bgimage.save(temppath)
    ShowResult(temppath,3)
    #bgimage2 = bgimage.rotate(90)
    #bgimage2.save(temppath)
    ImageShowed = False
    Message = ""
    Printing = False
    WaitForPrintingEvent()
    Numeral = ""
    Message = ""
    SubMessage = ""
    LongMessage = ""
    if Printing:
        if os.path.isfile(temppath):
            # Open a connection to cups
            conn = cups.Connection()
            # get a list of printers
            # printers = conn.getPrinters()
            # select printer 0
            printer_name = "Canon_MP250_series"
            Message = "Aan het printen..."
            UpdateDisplay()
            time.sleep(1)
            # print the buffer file
            printqueuelength = len(conn.getJobs())
            if printqueuelength > 1:
                ShowPicture(temppath,3)
                conn.enablePrinter(printer_name)
                Message = "Probleem met de printer... :("
                UpdateDisplay()
                time.sleep(1)
            else:
                conn.printFile(printer_name, temppath, "PhotoBooth", {})
                time.sleep(40)
    Message = ""
    Numeral = ""
    ImageShowed = False
    UpdateDisplay()
    os.remove(filename1)
    os.remove(filename2)
    os.remove(filename3)

def MyCallback(channel):
    global Printing
    GPIO.remove_event_detect(BUTTON_PIN)
    pygame.event.clear()
    Printing=True

def WaitForPrintingEvent():
    global BackgroundColor
    global Numeral
    global Message
    global LongMessage
    global SubMessage
    global Printing
    global pygame
    countDown = 5
    GPIO.add_event_detect(BUTTON_PIN, GPIO.RISING)
    GPIO.add_event_callback(BUTTON_PIN, MyCallback)

    while Printing == False and countDown > 0:
        if(Printing == True):
            return
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_DOWN:
                    GPIO.remove_event_detect(BUTTON_PIN)
                    Printing = True
                    return
        BackgroundColor = ""
        Numeral = ""
        SubMessage = str(countDown)
        LongMessage = "Druk op de knop om je foto af te drukken"
        UpdateDisplay()
        countDown = countDown - 1
        time.sleep(1)

    GPIO.remove_event_detect(BUTTON_PIN)
    pygame.event.clear()

def uploadToGP(filename):
    p = Popen(['/usr/bin/share/gpup','-a "trouw"', filename], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)

def WaitForEvent():
    global pygame
    NotEvent = True
    while NotEvent:
            input_state = GPIO.input(BUTTON_PIN)
            if input_state == False:
                    NotEvent = False
                    return

            try:
                for event in pygame.event.get():
                    if event.type == pygame.KEYDOWN:
                        if event.key == pygame.K_ESCAPE:
                            pygame.quit()
                        if event.key == pygame.K_DOWN:
                            NotEvent = False
                            return
                    if event.type == QUIT:
                        pygame.quit()
            except:
                pygame.quit()

            time.sleep(0.2)
    pygame.event.clear()

def main(threadName, *args):
    InitFolder()

    try:
        while True:
            show_image('images/start_camera.jpg')
            WaitForEvent()
            time.sleep(0.2)
            TakePictures()
    except Exception as e:
        print(e)
        GPIO.cleanup()
        pygame.quit()

# launch the main thread
Thread(target=main, args=('Main', 1)).start()


from flask import Blueprint, request

from utils import tojson, hash_user
from db.connection import DBConnection
import db.config as db_config

users_bp = Blueprint('users_bp', __name__)
endpoint = 'users'

@users_bp.route(f'/{endpoint}', methods=['GET', 'POST'])
def users():
    with DBConnection() as conn:
        col = conn.db.get_collection(db_config.USER_COL)

        if request.method == 'GET':
            return tojson(list(col.find({})))

        # Post data
        data = dict(request.get_json())
        hash_user(data)
        response = conn.validate_unique(db_config.USER_COL, data)
        if not response['valid']:
            response = tojson(response)
            response.status_code = 401
            return response

        col.insert_one(data)
        return tojson(data)

@users_bp.route(f'/{endpoint}/<user_id>', methods=['GET', 'PUT', 'DELETE'])
def users_userid(user_id):
    with DBConnection() as conn:
        col = conn.db.get_collection(db_config.USER_COL)

        if request.method == 'GET':
            return tojson(col.find_one({'user_id': user_id}))

        elif request.method == 'DELETE':
            return tojson(col.delete_one({'user_id': user_id}))

        # Update data
        data = dict(request.get_json())
        hash_user(data)
        response = conn.validate_unique(db_config.USER_COL, data)
        if not response['valid']:
            response = tojson(response)
            response.status_code = 401
            return response

        col.update_one(
            {'user_id': user_id},
            {'$set': data}
        )
        return tojson(col.find_one({'user_id': user_id}))