# Raspberry Pi - Photo Booth
#
# Copyright (c) 2014, John Croucher - www.jcroucher.com
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification, 
# are permitted provided that the following conditions are met:
# 
# 1. Redistributions of source code must retain the above copyright notice, this 
# list of conditions and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright notice, this 
# list of conditions and the following disclaimer in the documentation and/or other 
# materials provided with the distribution.
# 
# 3. Neither the name of the copyright holder nor the names of its contributors may 
# be used to endorse or promote products derived from this software without specific 
# prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
# THE POSSIBILITY OF SUCH DAMAGE.


import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
import tweepy
import time
from threading import Thread
from subprocess import call  
from datetime import datetime
import picamera
import PIL
from PIL import Image
#import cups
import os
import sys
import pygame
import random
import requests
import urllib
buttonled = 7
flashled = 22
button = 18

slideshowRunning = True
basewidth = 177 # Used for merging the photos onto one
printPhoto = False
TweetPhoto = True
Combine = True
imgPath = '/home/pi/BoothPi/.images/tmp'

# Light big light
GPIO.setup(buttonled, GPIO.OUT) ## Setup GPIO Pin 7 to OUT
GPIO.output(buttonled, 1) ## Turn on GPIO pin 7

# Push button for starting the photo sequence
GPIO.setup(button, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# Display surface
pygame.init()

pygame.mouse.set_visible(0)

w = pygame.display.Info().current_w
h = pygame.display.Info().current_h

screenSize = (w, h)

screen = pygame.display.set_mode(screenSize, pygame.FULLSCREEN) # Full screen the display with no window


# Used for loading a random photo for the slideshow
def random_file(dir):
        files = [os.path.join(path, filename)
                for path, dirs, files in os.walk(dir)
                for filename in files]

        return random.choice(files)


def displayImage(file):
        screen.fill((0,0,0))

        img = pygame.image.load(file) 
        img = pygame.transform.scale(img,(w,h)) # Make the image full screen
        screen.blit(img,(0,0))
        pygame.display.flip() # update the display


# Display a random image
def slideshow():
        while True:

                if slideshowRunning == True:
        
                        checkEvents()

                        randomFile = random_file('/home/pi/BoothPi/.images')
                        
                        displayImage(randomFile)
        
                        time.sleep(10) # pause 

# Handle events like keypress
def checkEvents():
        for event in pygame.event.get():
                # Shutdown the application if quit event or escape key is pressed
                if event.type == pygame.QUIT or ( event.type is pygame.KEYDOWN and event.key == pygame.K_ESCAPE ):
                        slideshowRunning = False
                        pygame.quit()
                        sys.exit()

                if event.type is pygame.KEYDOWN and event.key == pygame.K_f: # Switch the display mode between full screen and windowed
                        if screen.get_flags() & pygame.FULLSCREEN:
                                pygame.display.set_mode(screenSize)
                        else:
                                pygame.display.set_mode(screenSize,pygame.FULLSCREEN)

# On screen text message
def displayStatus(status):
        screen.fill((0,0,0))
        
        font = pygame.font.SysFont("monospace",92)
        text = font.render(status,True,(255,255,255))

        # Display in the center of the screen
        textrect = text.get_rect()
        textrect.centerx = screen.get_rect().centerx
        textrect.centery = screen.get_rect().centery

        screen.blit(text,textrect)
        
        pygame.display.flip() # update the display
        

# Merge all photos onto one ready for printing
def combineImages():
	if Combine == True:
        	displayStatus('Saving')
                        
	        # Do the merging
	        blankImage = Image.open('blank.jpg')

	        image1 = Image.open(imgPath + '/image1.jpg')    
	        image1 = image1.resize((640,480))
	        blankImage.paste(image1, (0,0))
	        displayStatus('25%')

	        image2 = Image.open(imgPath + '/image2.jpg')  
	        image2 = image2.resize((640,480))
	        blankImage.paste(image2, (0,480))
	        displayStatus('50%')

	        image3 = Image.open(imgPath + '/image3.jpg') 
	        image3 = image3.resize((640,480))
	        blankImage.paste(image3, (640,0))
	        displayStatus('75%')

	        image4 = Image.open(imgPath + '/image4.jpg')
	        image4 = image4.resize((640,600))
	        blankImage.paste(image4, (640,480))
        	displayStatus('100%')

	        blankImage.save(imgPath + '/combined.jpg', 'JPEG', quality=80)
	        displayStatus('Saved')

# Check net
def CheckNet():
	try :
	    stri = "https://www.google.com"
	    data = urllib.urlopen(stri)
	    Tweet()
	except:
	    displayStatus('Offline')
            time.sleep(3) # pause 


# Upload to Twitter
def Tweet():
	if Combine == True:
	        if TweetPhoto == True:
			displayStatus('Tweeting')

			# Consumer keys and access tokens, used for OAuth  
			consumer_key = 'DVW3lqng3wY6hE77L7HV3Pq6o'  
			consumer_secret = 'o8hOsaAGuDkoHyH8CjBrhhAYidf8KsyubAVhad6bAZDlP0nQ6U'  
			access_token = '2867471873-HPqS3vtqHUOJHnWskkZK4ofZNWM7laef6L1LTWa'  
			access_token_secret = 'rZbxlDLqlgGuHZRXSH2V2rMRzWJLAIXWSbxorpZrFgVDX' 

			# OAuth process, using the keys and tokens  
			auth = tweepy.OAuthHandler(consumer_key, consumer_secret)  
			auth.set_access_token(access_token, access_token_secret)  
   
			# Creation of the actual interface, using authentication  
			api = tweepy.API(auth)  

			# Send the tweet with photo  
			photo_path = imgPath + '/combined.jpg'  
			status = 'Photo Tweet from HudgellBooth: ' + i.strftime('%Y/%m/%d %H:%M:%S')   
			api.update_with_media(photo_path, status=status)
			displayStatus('Complete')	

	if Combine == False:
	        if TweetPhoto == True:
			displayStatus('Tweeting')

			# Consumer keys and access tokens, used for OAuth  
			consumer_key = 'DVW3lqng3wY6hE77L7HV3Pq6o'  
			consumer_secret = 'o8hOsaAGuDkoHyH8CjBrhhAYidf8KsyubAVhad6bAZDlP0nQ6U'  
			access_token = '2867471873-HPqS3vtqHUOJHnWskkZK4ofZNWM7laef6L1LTWa'  
			access_token_secret = 'rZbxlDLqlgGuHZRXSH2V2rMRzWJLAIXWSbxorpZrFgVDX' 

			# OAuth process, using the keys and tokens  
			auth = tweepy.OAuthHandler(consumer_key, consumer_secret)  
			auth.set_access_token(access_token, access_token_secret)  
   
			# Creation of the actual interface, using authentication  
			api = tweepy.API(auth)  
  
			# Send the tweet with photo 1
			displayStatus('25%')
			photo_path = imgPath + '/image1.jpg'  
			status = 'Photo Tweet from HudgellBooth: ' + i.strftime('%Y/%m/%d %H:%M:%S')   
			api.update_with_media(photo_path, status=status)

			# Send the tweet with photo 2
			displayStatus('50%')
			photo_path = imgPath + '/image2.jpg'  
			status = 'Photo Tweet from HudgellBooth: ' + i.strftime('%Y/%m/%d %H:%M:%S')   
			api.update_with_media(photo_path, status=status)

			# Send the tweet with photo 3
			displayStatus('75%')
			photo_path = imgPath + '/image3.jpg'  
			status = 'Photo Tweet from HudgellBooth: ' + i.strftime('%Y/%m/%d %H:%M:%S')   
			api.update_with_media(photo_path, status=status)

			# Send the tweet with photo 4
			displayStatus('100%')
			photo_path = imgPath + '/image4.jpg'  
			status = 'Photo Tweet from HudgellBooth: ' + i.strftime('%Y/%m/%d %H:%M:%S')   
			api.update_with_media(photo_path, status=status)
			displayStatus('Complete')		

# Print the photo
def printPhoto():
        if printPhoto == True:
                displayStatus('Printing')

                conn = cups.Connection()
                printers = conn.getPrinters()
                printer_name = printers.keys()[0]
                conn.printFile(printer_name, imgPath + '/combined.jpg',"TITLE",{})

                time.sleep(2)

# Combine Preview
def combinePre():
	if Combine == True:
		displayImage( imgPath + '/combined.jpg' ) # Display a preview of the combined image


# Thread for the slideshow
t = Thread(target=slideshow)
t.start()
		
with picamera.PiCamera() as camera:

        while True:
                checkEvents() # Needed to check for keypresses and close signals

		# Putton press to start the photo sequence
                input_state = GPIO.input(button)
                if input_state == False:

			GPIO.output(buttonled, 0) ## Turn off GPIO pin 7
                    
                        # Stop the slideshow
                        slideshowRunning = False
			displayStatus('')		

                        # Start the camera preview
			camera.hflip = False
			camera.vflip = False

                        camera.start_preview()

                        # Make the destination path for the photos
                        if not os.path.exists(imgPath):
                                os.mkdir(imgPath)

                        # Loop through the 4 photo taking sequences
			GPIO.setup(flashled, GPIO.OUT) ## Setup GPIO Pin 22 to OUT
			GPIO.output(flashled, 1) ## Turn on GPIO pin 22
			i = datetime.now()               #take time and date for filename  
			now = i.strftime('%Y%m%d-%H%M%S')  

                        for pNum in range (1,5):
                                camera.annotate_text = 'Photo ' + str(pNum) + ' of 4'
                                time.sleep(1)

				for countDown in range (3,0,-1):
                                	camera.annotate_text = str(countDown)
                                	time.sleep(1)
        
                                camera.annotate_text = ''
				#camera.resolution = (2560, 1920)
				camera.resolution = (1280, 960)
				os.system('omxplayer CSC.mp3 &')
                                camera.capture ( imgPath + '/image' + str(pNum) + '.jpg')
                                time.sleep(3)
                        
                        # Stop the camera preview so we can return to the pygame surface
			GPIO.output(flashled, 0) ## Turn on GPIO pin 7
                        camera.stop_preview()

                        combineImages()
		
			CheckNet()			

                        printPhoto()

			combinePre()

                        time.sleep(5)

                        # Move the temp files to a new dir based on the current timestamp so they can be retrieved later
                        os.rename(imgPath, '/home/pi/BoothPi/.images/' + str(int(time.time())))

			GPIO.output(buttonled, 1) ## Turn on GPIO pin 7

                        # Restart the slideshow
                        slideshowRunning = True

