from funkcje.obraz import Obraz
import os
import sys
import cv2
import numpy as np
from pathlib import Path
from tkinter import Tk, filedialog
import urllib.request
import tempfile

def test_transform(image_path, transform_name):
    """
    Testuje wybraną transformację na podanym obrazie.
    
    Args:
        image_path (str): Ścieżka do obrazu
        transform_name (str): Nazwa transformacji do przetestowania
    """
    try:
        # Wczytanie obrazu
        img = Obraz(image_path)
        img.load_image()
        
        print(f"\n--- Testowanie transformacji: {transform_name} ---")
        
        # Wykonanie transformacji
        result = img.transform(transform_name, show_side_by_side=True)
        
        # Zamknięcie wszystkich okien przed zakończeniem
        cv2.destroyAllWindows()
        return True
        
    except Exception as e:
        print(f"Błąd podczas wykonywania transformacji {transform_name}: {str(e)}")
        import traceback
        traceback.print_exc()
        cv2.destroyAllWindows()
        return False

def select_image_from_disk():
    """Otwiera okno dialogowe do wyboru pliku obrazu z dysku."""
    print("\nOtwieranie okna dialogowego wyboru pliku...")
    
    # Ukryj główne okno Tkinter
    root = Tk()
    root.withdraw()
    root.attributes('-topmost', True)
    
    # Otwórz dialog wyboru pliku
    file_path = filedialog.askopenfilename(
        title="Wybierz plik obrazu",
        filetypes=[
            ("Pliki obrazów", "*.jpg *.jpeg *.png *.bmp *.gif *.tiff"),
            ("JPEG", "*.jpg *.jpeg"),
            ("PNG", "*.png"),
            ("BMP", "*.bmp"),
            ("Wszystkie pliki", "*.*")
        ]
    )
    
    root.destroy()
    
    if file_path:
        print(f"✓ Wybrano plik: {file_path}")
        return file_path
    else:
        print("✗ Nie wybrano pliku.")
        return None

def download_image_from_url(url):
    """Pobiera obraz z URL i zapisuje go w pliku tymczasowym."""
    try:
        print(f"\nPobieranie obrazu z URL: {url}")
        
        # Pobierz obraz
        with urllib.request.urlopen(url, timeout=10) as response:
            image_data = response.read()
        
        # Zapisz do pliku tymczasowego
        temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.jpg')
        temp_file.write(image_data)
        temp_file.close()
        
        print(f"✓ Obraz pobrany i zapisany jako: {temp_file.name}")
        return temp_file.name
        
    except Exception as e:
        print(f"✗ Błąd podczas pobierania obrazu: {str(e)}")
        return None

def select_image_source():
    """Pozwala użytkownikowi wybrać źródło obrazu."""
    print("\n" + "="*60)
    print("WYBÓR ŹRÓDŁA OBRAZU")
    print("="*60)
    print("1. Wybierz plik z dysku (okno dialogowe)")
    print("2. Podaj URL do obrazu w internecie")
    print("3. Użyj domyślnego obrazu z katalogu dzien_01")
    print("0. Anuluj")
    print("="*60)
    
    while True:
        choice = input("\nWybierz opcję (0-3): ").strip()
        
        if choice == '0':
            return None
        elif choice == '1':
            return select_image_from_disk()
        elif choice == '2':
            url = input("\nPodaj URL obrazu: ").strip()
            if url:
                return download_image_from_url(url)
            else:
                print("✗ Nie podano URL.")
                return None
        elif choice == '3':
            # Użyj domyślnego obrazu
            base_dir = Path(__file__).parent.parent
            images_dir = base_dir / 'dzien_01'
            image_extensions = ('.jpg', '.jpeg', '.png', '.bmp')
            available_images = [f for f in os.listdir(images_dir) 
                               if f.lower().endswith(image_extensions)]
            
            if available_images:
                default_path = str(images_dir / available_images[0])
                print(f"✓ Używam domyślnego obrazu: {default_path}")
                return default_path
            else:
                print("✗ Nie znaleziono obrazów w katalogu dzien_01")
                return None
        else:
            print("✗ Nieprawidłowy wybór. Wybierz 0-3.")

def print_menu(transformations):
    """Wyświetla menu z dostępnymi transformacjami."""
    print("\n" + "="*60)
    print("DOSTĘPNE TRANSFORMACJE OBRAZU")
    print("="*60)
    for i, transform in enumerate(transformations, 1):
        print(f"{i:2d}. {transform}")
    print("-"*60)
    print(" C. Zmień obraz (wybierz inny plik)")
    print(" 0. Wyjście z programu")
    print("="*60)

def main():
    print(f"\n{'='*60}")
    print(f"PROGRAM TESTOWANIA TRANSFORMACJI OBRAZÓW")
    print(f"{'='*60}")
    
    # Wybór początkowego obrazu
    image_path = select_image_source()
    
    if not image_path:
        print("\n✗ Nie wybrano obrazu. Program zakończony.")
        return
    
    print(f"\nObecnie używany obraz:")
    print(f"  Nazwa: {os.path.basename(image_path)}")
    print(f"  Ścieżka: {image_path}")
    
    # Lista dostępnych transformacji do przetestowania
    transformations = [
        "GRAY",                 # Skala szarości
        "BLUR_GAUSSIAN",        # Rozmycie Gaussa
        "BLUR_MEDIAN",          # Rozmycie medianowe
        "BLUR_BILATERAL",       # Rozmycie bilateralne
        "CANNY",                # Detekcja krawędzi Canny
        "EDGE_DETECTION",       # Zaawansowana detekcja krawędzi
        "THRESHOLD",            # Progowanie binarne
        "ADAPTIVE",             # Progowanie adaptacyjne
        "SOBEL",                # Detekcja krawędzi Sobel
        "LAPLACIAN",            # Detekcja krawędzi Laplacian
        "CONTOURS",             # Detekcja konturów
        "FACE_DETECTION",       # Detekcja twarzy
        "SHARPEN",              # Wyostrzenie
        "EMBOSS",               # Efekt wytłoczenia
        "YOLO_DETECT",          # YOLO - Detekcja obiektów (szybki)
        "YOLO_DETECT_MEDIUM",   # YOLO - Detekcja obiektów (średni)
        "YOLO_DETECT_LARGE",    # YOLO - Detekcja obiektów (dokładny)
        "YOLO_SEGMENT"          # YOLO - Segmentacja obiektów
    ]
    
    # Pętla główna programu
    while True:
        print_menu(transformations)
        
        try:
            choice = input(f"\nWybierz opcję (0-{len(transformations)}, C aby zmienić obraz): ").strip().upper()
            
            # Sprawdź czy użytkownik chce zakończyć
            if choice == '0':
                print("\nZakończono program. Do widzenia!")
                break
            
            # Sprawdź czy użytkownik chce zmienić obraz
            elif choice == 'C':
                new_image_path = select_image_source()
                if new_image_path:
                    image_path = new_image_path
                    print(f"\n✓ Zmieniono obraz na:")
                    print(f"  Nazwa: {os.path.basename(image_path)}")
                    print(f"  Ścieżka: {image_path}")
                else:
                    print("\n✗ Nie wybrano nowego obrazu. Pozostawiono poprzedni.")
                input("\nNaciśnij ENTER, aby kontynuować...")
                continue
            
            # Konwersja na liczbę
            try:
                choice_idx = int(choice) - 1
            except ValueError:
                print("\n✗ Proszę wprowadzić poprawną liczbę lub 'C'.")
                continue
            
            # Sprawdź poprawność wyboru
            if 0 <= choice_idx < len(transformations):
                transform_name = transformations[choice_idx]
                print(f"\n{'='*60}")
                print(f"Wybrano transformację: {transform_name}")
                print(f"{'='*60}")
                
                # Wykonaj transformację
                success = test_transform(image_path, transform_name)
                
                if success:
                    print(f"\n✓ Transformacja '{transform_name}' zakończona pomyślnie.")
                else:
                    print(f"\n✗ Transformacja '{transform_name}' zakończona z błędem.")
                
                # Poczekaj na potwierdzenie przed powrotem do menu
                input("\nNaciśnij ENTER, aby wrócić do menu...")
            else:
                print(f"\n✗ Nieprawidłowy wybór. Wybierz numer od 0 do {len(transformations)}.")
                
        except KeyboardInterrupt:
            print("\n\nPrzerwano przez użytkownika. Do widzenia!")
            break
        except Exception as e:
            print(f"\n✗ Wystąpił nieoczekiwany błąd: {str(e)}")
            import traceback
            traceback.print_exc()

if __name__ == "__main__":
    main()
