# Michael Gousie
# five.py
# Senior Seminar 2023
#
# Clean up four.py with additional features:
#   - window much neater
#   - title with bold font, centered, etc.
#   - 500x500 fixed size window for image
#       - images are auto-scaled to fit in this window
#   - 'scale' button to scale images into 500x500 while keeping aspect ratio
#   - blue background behind smaller images
#   - displays original image size (so user knows it's being scaled)

import PySimpleGUI as sg
import os.path
import io             
from PIL import Image 

sg.theme ("LightGreen10")

# define output for first and third columns
firstCol = [ [sg.Text("Image Viewer", text_color = "blue", relief = "raised", 
              size = (35, 3), border_width = 3, font="bold", auto_size_text = "True",
              justification = "center")],
             [sg.Text("Image Folder: "), 
              sg.In (size=(25,1), enable_events=True, key="-FOLDER-"), 
              sg.FolderBrowse()], 
             [sg.Listbox(values=[], enable_events=True, size=(50,10), key="-FILE LIST-")],
             [sg.Button ("Close"), sg.Button ("Scale")] ]

thirdCol = [ [sg.Text("Choose image from list at left")],
             [sg.Text("File:", size=(4,1)), sg.Text(size=(65, 1), key="-FILENAME-")],
             [sg.Text("Image size:"), sg.Text(size=(60, 1), key="-SIZE-")],
             [sg.Image(key="-IMAGE-", background_color = "black", size=(500, 500))] ]

# define the layout
layout = [ [sg.Column(firstCol), sg.VSeperator(), sg.Column(thirdCol)] ]
          
# display the window
window = sg.Window ("Image Viewer", layout, resizable = True) #, margins=(150, 50))

while True:
    event, values = window.read()

    if event == "Close" or event == sg.WIN_CLOSED:
        break

    # User chose a folder after clicking 'Browse' button
    if event == "-FOLDER-":     # uses identifer from first column
        # get actual folder that was chosen
        folder = values["-FOLDER-"]
        try:
            # get list of files in chosen folder
            # this needs: import os.path
            fileList = os.listdir (folder)
            # debugging: print (fileList)
        except:
            # no files found!
            fileList = []   
            # debugging: print (fileList)

        # create a list of filenames that are in the chosen folder
        # and that end with .jpg
        fileNames = [
            f
            for f in fileList
            if os.path.isfile (os.path.join (folder, f))
            and f.lower().endswith ((".jpg"))
        ]
        # debugging: print (fileNames)
        # add the filenames to the image file list in first column
        window["-FILE LIST-"].update (fileNames)

    # User chose a file to display from the file list
    if event == "-FILE LIST-" or event == "Scale":
        try:
            # create full path name of file
            # FILE-LIST is an array of file names; 
            # we want the first (and only) one
            # debugging: print (values)
            fileName = os.path.join(values["-FOLDER-"], values["-FILE LIST-"][0])
            
            # display filename in appropriate spot in right column
            window["-FILENAME-"].update(fileName)

            # convert to png
            pilImage = Image.open (fileName)

            # get current size
            w, h = pilImage.size
            outStr = "Width: " + str(w) + "  Height: " + str(h)
            print (outStr)
            window["-SIZE-"].update(outStr)

            # change size
            if event == "Scale":

                # image smaller than alloted size; pad it
                if w <= 500 and h <= 500:
                    padX = (500 - w) // 2
                    padY = (500 - h) // 2
                    print ("x, y padding: ", padX, padY)
                    new_pilImage = Image.new(pilImage.mode, (500, 500), (0, 0, 255))
                    # x and y must be integers
                    new_pilImage.paste (pilImage, (padX, padY))
                    pilImage = new_pilImage

                # width is too large and image is wider than high
                elif w > 500 and w > h:
                    # keep aspect ratio!
                    y = round(500 * h / w)
                    print ("x, y size: ", 500, y)
                    # first resize with aspect ratio
                    newsize = (500, y)
                    pilImage = pilImage.resize(newsize)
                    new_pilImage = Image.new(pilImage.mode, (500, 500), (0, 0, 255))

                    padX = 0
                    padY = (500 - y) // 2
                    new_pilImage.paste (pilImage, (padX, padY))
                    pilImage = new_pilImage
                    
                # height is too large; process as above but changing width
                else:
                    y = 500
                    x = round (y * w / h)
                    newsize = (x, y)
                    pilImage = pilImage.resize(newsize) 
                    new_pilImage = Image.new(pilImage.mode, (500, 500), (0, 0, 255))

                    padX = (500 - x) // 2
                    padY = (500 - y) // 2
                    new_pilImage.paste (pilImage, (padX, padY))
                    pilImage = new_pilImage

            # fit into existing 500x500 window
            else:
                newsize = (500, 500)
                pilImage = pilImage.resize(newsize) 

            # save as a hidden file
            pilImage.save (".tempName.png")

            # read new file
            pngFileName = os.path.join (".tempName.png")

            # display the image file
            window["-IMAGE-"].update(filename = pngFileName)

        except:
            # don't display anything but keep going
            pass

window.close()
