#Imporitert alle Bibliotheken
from pypdf import PdfWriter #pip install pypdf
import re
import os
import sys
import subprocess
import pikepdf #pip install pikepdf
import time
import glob
from PIL import Image, ImageOps #pip install Pillow
#Um exe zu erstellen: python -m PyInstaller --onefile --icon icon_new.ico CCT.py

#Funktion zum Neustart des Skriptes
def Restart(Error):
    if str(Error).upper() == "JA":
        skriptPfad = os.path.abspath(__file__)
        subprocess.run([sys.executable] + [skriptPfad] + sys.argv[1:])
#Funktion zum konvertieren von Bilddateien zu PDFs mit Pillow
def image_to_pdf_pillow(input_path, output_path, resolution=300):
    img = Image.open(input_path) #Bild laden
    img = ImageOps.exif_transpose(img) #Bild richtig orientieren
    if img.mode in ("RGBA", "LA"): #Transparenten Hintergrund ersetzen, fallse existent
        background = Image.new("RGB", img.size, (255, 255, 255)) #Weißen Hintergrund generieren
        background.paste(img, mask=img.split()[-1]) #Transparentes Bild auf weißen Hintergrund platzieren
        img = background
    else:
        img = img.convert("RGB") # Direkt zu nicht transparentem Bildformat konvertieren
    img.save(output_path, "PDF", resolution=resolution) # Als PDF speichern
# Funktion zum konvertieren von regulären Bilddateien in effizientere webp Bilddateien
def convert_to_webp(input_path, output_path, quality=80, lossless=False):
    img = Image.open(input_path) # Bild laden
    img = ImageOps.exif_transpose(img) # Bild richtig orientieren
    img.save(output_path, "WEBP", quality=quality, method=6, lossless=lossless) #Bild als WEBP speichern

def RestartPrompt(Message):
    print(Message)
    Restart(input("\n↳ Zurückkehren (Ja/Nein): ")) # Leitet Antwort an Neustart Funktion weiter
# Checkt ob komprimiert werden soll und sammelt Bilddateien
def compress(Command, images):
    if str(Command).upper() == "JA":
        ID = 0 # Ladebalken
        for img in images:
            ID+=1 # Ladebalken
            Loading_Bar = '_'*(ID-1) + '/' + '|'*(len(images)-ID) # Ladebalken
            sys.stdout.write(f"\rBilder -> WebP {Loading_Bar}") # Ladebalken
            sys.stdout.flush() # Ladebalken
            convert_to_webp(img, FolderPath + "\\Img_" + str(ID) + ".webp")
        Loading_Bar = '_'*(ID) # Ladebalken
        sys.stdout.write(f"\rBilder -> WebP {Loading_Bar}") # Ladebalken
        sys.stdout.flush() # Ladebalken
        print('\n')
        webp = glob.glob(str(FolderPath) +"\\*.webp") # Alle webp Datei-pfade werden aufgelistet
        return webp
# Begrüßungsnachricht
print("\nPdf Merge von Nikita Kossack v1\n===================================\n[1] Bilder & PDF's mergen\n[1?] Hilfe zum mergen\n[2] Bild komprimieren\n[2?] Hilfe zum komprimieren\n[3] Mitwirken\n===================================\n")

Tool = input('↦ Welches Tool willst du verwenden?: ') # Eingabefeld Menüauswahl
if Tool == str(1):
    FolderPath = input('↦ Ordnerpfad der zusammenzufügenden PDF\'s: ') # Eingabefeld [Ordnerpfad]
    if os.path.isdir(str(FolderPath)): # Checkt ob der Dateiordnerpfad valide ist
        Result_Name = input('↦ Dateiname der zusammengefügten PDF: ') # Eingabefeld [Neuer Dateiname]
        if not re.search(r'[<>:"/\\|?*]', Result_Name) and not Result_Name=='': # Checkt ob der Name valide ist
            jpegs = glob.glob(str(FolderPath) +"\\*.jpg") # Alle jpeg Datei-pfade werden aufgelistet
            pngs = glob.glob(str(FolderPath) +"\\*.png") # Alle png Datei-pfade werden aufgelistet
            images = jpegs + pngs # Alle Bild Datei-pfade werden zusammengefasst
            if len(images)>0: # Es wird geprüft ob Bilder im Merge enthalten sind
                ID = 0 # Ladebalken
                Comp_images = compress(input('↦ Bilder wurden gefunden, sollen diese komprimiert werden? (Ja/Nein): '), images) # Bilder werden zu WEBP Dateien konvertiert
                if Comp_images is not None:
                    images = Comp_images # Falls sich für komprimieren entschieden wird, werden die Bilder ausgetauscht
                for img in images:
                    ID+=1 # Ladebalken
                    Loading_Bar = '_'*(ID-1) + '/' + '|'*(len(images)-ID) # Ladebalken
                    sys.stdout.write(f"\rBilder -> PDF {Loading_Bar}") # Ladebalken
                    sys.stdout.flush() # Ladebalken
                    image_to_pdf_pillow(img, FolderPath + "\\Img_" + str(ID) + ".pdf") # Bilder werden in PDFs konvertiert
                    os.remove(img)
                Loading_Bar = '_'*(ID)  # Ladebalken
                sys.stdout.write(f"\rBilder -> PDF {Loading_Bar}") # Ladebalken
                sys.stdout.flush() # Ladebalken
                print('\n')
            pdfs = glob.glob(str(FolderPath) +"\\*.pdf") # Alle pdf Datei-pfade werden aufgelistet
            if len(pdfs) > 1: # Überprüft ob mehr als eine Pdf enthalten sind
                print('============================================\nPDF\'s werden zusammengefügt...')
                time.sleep(0.2) # Sichert ab, dass die Nachricht übermittelt wird, wegen lag
                merger = PdfWriter() # Merger wird geladen
                for pdf in pdfs: # PDFs werden zusammengefügt
                    merger.append(pdf)
                    os.remove(pdf)
                os.makedirs(os.path.join(str(FolderPath), "Merged_PDF"), exist_ok=True) #Erstellt den Ordner fuer das Ergebnis
                merger.write(str(FolderPath) + "\\Merged_PDF\\"+ str(Result_Name) + ".pdf") #Die zusammengefügte PDF wird gespeichert
                merger.close() # Merge-prozess wird beendet
                print('Datei wird komprimiert...')
                time.sleep(0.2) # Sichert ab, dass die Nachricht übermittelt wird, wegen lag
                input_pdf = str(FolderPath) + "\\Merged_PDF\\"+ str(Result_Name) + ".pdf" # Dateipfade defenieren
                output_pdf = str(FolderPath) + "\\Merged_PDF\\"+ str(Result_Name) + ".pdf"
                with pikepdf.open(input_pdf, allow_overwriting_input=True) as pdf: #Optimierung der Zusammengefügten PDF durch pikepdf
                    pdf.save(output_pdf) # PDF nochmals speichern
                RestartPrompt('============================================\n🟢Fertig, bis zum nächsten mal!🟢')
            elif len(pdfs) == 1:
                RestartPrompt('============================================\n🟥Fehlgeschlagen: Nur eine PDF gefunden🟥')
            else:
                RestartPrompt('============================================\n🟥Fehlgeschlagen: Keine PDF gefunden🟥')
        else:
            RestartPrompt('============================================\n🟥Fehlgeschlagen: Invalider Dateiname🟥')
    else:
        RestartPrompt('============================================\n🟥Fehlgeschlagen: Dateipfad existiert nicht🟥')
if Tool == str(1) + '?':
    RestartPrompt('\n===================================\nSchritt 1: Bevor du beginnst, erstelle einen Ordner auf deinem Computer. \nSchritt 2: Bewege alle Bilder und PDF\'s in diesen neu erstellten Ordner, die zusammengefügt werden sollen. Achte darauf, dass alle Datein in diesem Ordner zusammengefügt werden und Altbestände aus früheren merges vorher entfernt werden müssen. Die Datein werden nach der Reihenfolge, in der sie im Ordner gelistet sind zusammengefügt, um die Reihenfolge zu ändern bennene die Dateien alphabetisch dementsprechend. Unterstützte Dateiformate sind PDF, PNG und JPEG. \nSchritt 3: Kopiere den Dateipfad des Ordners (Du siehst ihn wenn du oben beim Ordner in die Leiste klickst) und füge ihn hier im Programm ein. Benenne anschließend deine neu entstehende Datei. Die gemergde Datei ist unter deiner Benennung im Ordner \'Merged_PDF\' aufzufinden.')
if Tool == str(2):
    Dateipfad = input('↦ Dateipfad des zu komprimierenden Bild: ').replace("\"", "") # Dateipfad Eingabe
    Dateiloc = os.path.dirname(Dateipfad) # Ordner der Datei bestimmen
    if Dateipfad.lower().endswith((".jpg", ".jpeg", ".png")): # Überprüfen ob es sich um eine png oder jpeg Datei handelt
        convert_to_webp(Dateipfad,Dateiloc+'\\ZK.webp') # Zu Webp konvertieren
        image_to_pdf_pillow(Dateiloc+'\\ZK.webp',Dateiloc+'\\Result.pdf') # Zu PDF konvertieren
        os.remove(Dateiloc+'\\ZK.webp') # Webp Datei wieder entfernen
        RestartPrompt('============================================\n🟢Fertig, bis zum nächsten mal!🟢')
    else:
        RestartPrompt('============================================\n🟥Fehlgeschlagen: Invalider Dateipfad🟥')
if Tool == str(2) + '?':
    RestartPrompt('\n===================================\nFinde das Bild auf, dass du komprimieren möchtest. Rechtsklicke darauf und kopiere den Dateipfad. Gib ihn nun hier im Porgramm ein und das Bild wird zu einer komprimierten PDF, unter dem Namen \'Result.pdf\', konvertiert. Nur JPEG und PNG Dateien werden unterstützt.')
if Tool == str(3):
    RestartPrompt('\n===================================\nKontakt: https://nikanoku.de/contact.html')