import os
import subprocess
import commands
import socket
import random
import threading
import Queue
from PIL import Image
import time
import sys
import fnmatch
import urllib
import imdb
import requests

frameBufferCommand = "sudo fbi -T 1 -d /dev/fb0 -noverbose "
omxplayerCommand = "omxplayer -b "
moviePosterLocation = "/home/pi/movieposters/"
videoPosterLocation = "/home/pi/videoposters/"
turnOffScreen = "sudo /opt/vc/bin/tvservice -o"
turnOnScreen = "sudo /opt/vc/bin/tvservice -p"
screenState = False

#----------- QUEUE CREATION

posterLinkToDownload = Queue.Queue()
posterToOpen = Queue.Queue()
posterLinkSet = threading.Event()
posterLinkRetrieved = threading.Event()

#----------- FUNCTIONS

def searchDirectory(Location):
    directorySearched = False
    fileCount = next(os.walk(Location))[2] #get the number of available posters
    print('Current # Of Posters in Directory: ' + str(len(fileCount)))
    maxNumber = len(fileCount) - 1
    posterToDisplay = random.randint(0, maxNumber)
    return fileCount[posterToDisplay]    

def displayVideo(videoToDisplay):
    try:
        print("About to Play Poster Video")
        os.system(omxplayerCommand + videoPosterLocation + videoToDisplay)
        videoFunctionSuccess = True
    except IndexError as msg:
        print(msg)
        videoFunctionSuccess = False
        return videoFunctionSuccess
    return videoFunctionSuccess

def displayPoster(posterToDisplay):
    posterFunctionSuccess = False
    while not posterFunctionSuccess:
        try:
            image = Image.open(moviePosterLocation + posterToDisplay) #Open the image to test the width and height
            width, height = image.size
        except IndexError as msg:
            print("encountered an IndexError while opening the image")
            width = 0
            height = 0 
            posterFunctionSuccess = False
            return posterFunctionSuccess     
        except IOError as msg:
            print(msg)
            posterFunctionSuccess = False
            return posterFunctionSuccess   
        if width > height:
            if attemptNumber > 5:
                print("Too Many Attempts, Stopping")
                posterFunctionSuccess = False
                return posterFunctionSuccess
                break
            else:
                print("We Think This Isnt A Poster, Trying Again")               
                continue
        else:
            try:
                print("About to Open Image")
                os.system(frameBufferCommand + moviePosterLocation + posterToDisplay)
                posterFunctionSucces = True
            except IndexError as msg:
                print(msg)
                posterFunctionSuccess = False
                return posterFunctionSuccess
            return posterFunctionSuccess             


def client(conn): #---------- MAIN THREAD
    global screenState
    global randomMoviePoster

    dataReceived = conn.recv(1024)
    reply = "OK.. "
    while dataReceived: #--------- LOOP 
        conn.send(reply + dataReceived)
        print("dataRecieved = " + dataReceived)
        if "screenOn" in dataReceived:
            os.system(turnOnScreen)
            print("Display Power On")
            screenState = True
            time.sleep(2)
            try:
                print("Displaying Poster Video")
                try:
                    os.system("sudo killall omxplayer")
                except OSError as msg:
                    print("Error Killing omxplayer")
                    break
                randomVideoPoster = searchDirectory(videoPosterLocation)
                displayVideo(randomVideoPoster)
            except IndexError as msg:
                print(msg)
        elif "screenOff" in dataReceived:
            os.system(turnOffScreen)
            print("Display Power Off")
            screenState = False
        else:
            if "src_02" in dataReceived:
                print("watching Kodi")
                #ASK FOR POSTER
                try:
                    conn.send("posterLink?\x0A\x0D")
                except socketerror as msg:
                    print(msg)
                #WAIT FOR ANSWER
                print("waiting for Incoming Data")
                try:
                    moviePosterInfo = conn.recv(1024)
                except socket.timeout:
                    print("Timed Out")
                
                #FORMAT MOVIE INFO FOR FILENAME
                fileExtension = '.jpg'
                tempMovieInfo = moviePosterInfo.replace("\'", "")
                tempMovieInfo = tempMovieInfo.replace(" ", "_")
                tempMovieInfo2 = tempMovieInfo.replace("\r\n", "_")
                moviePosterFilename = tempMovieInfo2 + fileExtension
                print(moviePosterFilename)

                searchResults = movieDatabase.search_movie(moviePosterInfo)
                indexWeWant = -1
                for item in searchResults:
                    indexWeWant = indexWeWant + 1
                    print("Movie Title: " + item['long imdb canonical title'] + " | Release Year: " + str(item['year']))
                    releaseYear = item['year']
                    if str(releaseYear) in moviePosterInfo:
                        movieWeWant = indexWeWant
                        break
                    else:
                        continue
                try:
                    movieObject = searchResults[indexWeWant]
                except IndexError as msg:
                    print(msg)
                try:
                    currentMovieID = movieObject.movieID
                    print("We want " + moviePosterInfo + " which is index #" + str(movieWeWant) + " which is IMDB ID: " + str(currentMovieID))
                except UnboundLocalError as msg:
                    print(msg)

                try:
                    configPattern = 'http://api.themoviedb.org/3/configuration?api_key=f52d026918bb3ec364eae9f16eaefaab'
                    apiKey = 'f52d026918bb3ec364eae9f16eaefaab'

                    url = configPattern
                    r = requests.get(url)
                    config = r.json()

                    baseLink = config['images']['base_url']
                    posterSizes = config['images']['poster_sizes']

                    def size_str_to_int(x):
                        return float("inf") if x == 'original' else int(x[1:])
                    maxPosterSize = max(posterSizes, key=size_str_to_int)

                    imgRequestChunk1 = 'http://api.themoviedb.org/3/movie/tt'
                    imgRequestChunk2 = '/images?api_key=' 
                    imgRequest = imgRequestChunk1 + currentMovieID + imgRequestChunk2 + apiKey
                    r = requests.get(imgRequest)
                    api_response = r.json()

                    posters = api_response['posters']
                    poster_urls = []

                    for poster in posters:
                        rel_path = poster['file_path']
                        url = "{0}{1}{2}".format(baseLink, maxPosterSize, rel_path)
                        poster_urls.append(url)
                except UnboundLocalError as msg:
                    print(msg)
                except KeyError as msg:
                    print(msg)

                print("Trying to Download Movie Poster")
                #DISPLAY POSTER   
                try:
                    urllib.urlretrieve(poster_urls[0], moviePosterLocation + moviePosterFilename)
                    print("Poster Downloaded")
                    displayPoster(moviePosterFilename)
                    currentPoster = moviePosterFilename
                except UnboundLocalError as msg:
                    print(msg)
                    print("Error Downloading Poster")
                    randomMoviePoster = searchDirectory(moviePosterLocation)
                    displayPoster(randomMoviePoster)
                    currentPoster = randomMoviePoster
            else:
                print("source not Kodi")
                if screenState is True:
                    print("Display On Displaying Poster")
                    randomMoviePoster = searchDirectory(moviePosterLocation)
                    displayPoster(randomMoviePoster)
                    currentPoster = randomMoviePoster
                else:
                    os.system(turnOnScreen)
                    screenState = True
                    randomMoviePoster = searchDirectory(moviePosterLocation)
                    displayPoster(randomMoviePoster)
                    currentPoster = randomMoviePoster
        try: #-------- KILL OLD PROCESSES
            processObject = subprocess.Popen(['ps', '-aux'], stdout=subprocess.PIPE)
            out, err = processObject.communicate()
            for line in out.splitlines():
                if 'fbi' in line:
                    comparisonLabel = line.split(None)[16]
                    processToKill = int(line.split(None)[1])
                    try:
                        if currentPoster in comparisonLabel:
                            print("This is the current poster, " + currentPoster+ ", so we dont want to kill it")
                        else:
                            print(comparisonLabel + " is NOT the current poster, so we want to kill it")
                            os.kill(processToKill, 9)
                    except UnboundLocalError as msg:
                        print(msg)
                else:
                    print("We didnt find 'fbi' in this line so we dont fucking care.")
            break
        except OSError as msg:
            print(msg)
            break
        break
    conn.close()


#--------- STARTUP STUFF
host = ''
communicationPort = 5005
bindSuccess = False
crestronSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Socket Created Successfully")

try: #------- TRY TO BIND COMMUNICATION PORT
    crestronSocket.bind((host, communicationPort))
    bindSuccess = True
except socket.error as msg: 
    bindSuccess = False
    print("Socket Bind Error")
    sys.exit()

crestronSocket.listen(1)
print("Crestron Socket Listening")

os.system("sudo killall fbi") #--------- KILL ANY MISBEHAVING FBI PROCESSES

while bindSuccess == True: #--------- WAIT TO ACCEPT CONNECTION
    try:
        movieDatabase = imdb.IMDb()
        conn, addr = crestronSocket.accept()
        print('Connected with Client: ' + addr[0] + ':' + str(addr[1]))    
        serverThread = threading.Thread(target = client, args = (conn,))
        serverThread.start()
    except KeyboardInterrupt: 
        print("Keyboard Interrupt Activated Closing Program")
        crestronSocket.close()
        sys.exit()

crestronSocket.close()
