#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Tests für create_numbers.py Funktionen
"""

import sys
sys.stdout.reconfigure(encoding='utf-8')
import unittest

from create_numbers import sort_symbols_by_direction

def create_test_symbols():
    """
    Erstellt 16 Test-Symbole auf einem 4x4 Raster.

    Raster-Layout (Y-Achse nach oben, wie in DXF üblich):
    Y=300: (0,300)  (100,300)  (200,300)  (300,300)  <- Oben
    Y=200: (0,200)  (100,200)  (200,200)  (300,200)
    Y=100: (0,100)  (100,100)  (200,100)  (300,100)
    Y=0:   (0,0)    (100,0)    (200,0)    (300,0)    <- Unten
           X=0      X=100      X=200      X=300
           ^                              ^
         Links                          Rechts
    """
    symbols = []
    symbol_id = 1

    # Erstelle 4x4 Raster
    for y in [0, 100, 200, 300]:
        for x in [0, 100, 200, 300]:
            symbols.append({
                'id': symbol_id,
                'position': (x, y),
                'entity': None,  # Für den Test nicht benötigt
                'attributes': {'IO': f'SYM-{symbol_id}@@'},
                'layer': 'TEST_LAYER'
            })
            symbol_id += 1

    return symbols

class TestEntitySorting(unittest.TestCase):
    """Tests for running all combinations of sort_symbols_by_direction."""

    @classmethod
    def setUpClass(cls):
        """Wird einmal vor allen Tests ausgeführt."""
        print("="*70)
        print("Test Suite: sort_symbols_by_direction")
        print("="*70)
        print()
        sys.stdout.flush()

    def test_top_bottom_left_right(self):
        """
        Test TOP_BOTTOM/LEFT_RIGHT: Von oben nach unten, in jeder Zeile von links nach rechts
        """
        symbols = create_test_symbols()
        sorted_symbols = sort_symbols_by_direction(symbols, "TOP_BOTTOM/LEFT_RIGHT")

        # Erwartete Reihenfolge: Zeile Y=300, dann Y=200, dann Y=100, dann Y=0
        # In jeder Zeile: X=0, X=100, X=200, X=300
        expected_positions = [
            (0, 300), (100, 300), (200, 300), (300, 300),  # Zeile Y=300 (oben)
            (0, 200), (100, 200), (200, 200), (300, 200),  # Zeile Y=200
            (0, 100), (100, 100), (200, 100), (300, 100),  # Zeile Y=100
            (0, 0), (100, 0), (200, 0), (300, 0)        # Zeile Y=0 (unten)
        ]

        actual_positions = [s['position'] for s in sorted_symbols]

        assert actual_positions == expected_positions, f"Fehler! Erwartet: {expected_positions}, Erhalten: {actual_positions}"


    def test_top_bottom_right_left(self):
        """
        Test TOP_BOTTOM/RIGHT_LEFT: Von oben nach unten, in jeder Zeile von rechts nach links
        """
        symbols = create_test_symbols()
        sorted_symbols = sort_symbols_by_direction(symbols, "TOP_BOTTOM/RIGHT_LEFT")

        # Erwartete Reihenfolge: Zeile Y=300, dann Y=200, dann Y=100, dann Y=0
        # In jeder Zeile: X=300, X=200, X=100, X=0
        expected_positions = [
            (300, 300), (200, 300), (100, 300), (0, 300),  # Zeile Y=300 (oben)
            (300, 200), (200, 200), (100, 200), (0, 200),  # Zeile Y=200
            (300, 100), (200, 100), (100, 100), (0, 100),  # Zeile Y=100
            (300, 0), (200, 0), (100, 0), (0, 0)        # Zeile Y=0 (unten)
        ]

        actual_positions = [s['position'] for s in sorted_symbols]

        assert actual_positions == expected_positions, f"Fehler! Erwartet: {expected_positions}, Erhalten: {actual_positions}"


    def test_bottom_top_left_right(self):
        """
        Test BOTTOM_TOP/LEFT_RIGHT: Von unten nach oben, in jeder Zeile von links nach rechts
        """
        symbols = create_test_symbols()
        sorted_symbols = sort_symbols_by_direction(symbols, "BOTTOM_TOP/LEFT_RIGHT")

        # Erwartete Reihenfolge: Zeile Y=0, dann Y=100, dann Y=200, dann Y=300
        # In jeder Zeile: X=0, X=100, X=200, X=300
        expected_positions = [
            (0, 0), (100, 0), (200, 0), (300, 0),        # Zeile Y=0 (unten)
            (0, 100), (100, 100), (200, 100), (300, 100),  # Zeile Y=100
            (0, 200), (100, 200), (200, 200), (300, 200),  # Zeile Y=200
            (0, 300), (100, 300), (200, 300), (300, 300)   # Zeile Y=300 (oben)
        ]

        actual_positions = [s['position'] for s in sorted_symbols]

        assert actual_positions == expected_positions, f"Fehler! Erwartet: {expected_positions}, Erhalten: {actual_positions}"


    def test_bottom_top_right_left(self):
        """
        Test BOTTOM_TOP/RIGHT_LEFT: Von unten nach oben, in jeder Zeile von rechts nach links
        """
        symbols = create_test_symbols()
        sorted_symbols = sort_symbols_by_direction(symbols, "BOTTOM_TOP/RIGHT_LEFT")

        # Erwartete Reihenfolge: Zeile Y=0, dann Y=100, dann Y=200, dann Y=300
        # In jeder Zeile: X=300, X=200, X=100, X=0
        expected_positions = [
            (300, 0), (200, 0), (100, 0), (0, 0),        # Zeile Y=0 (unten)
            (300, 100), (200, 100), (100, 100), (0, 100),  # Zeile Y=100
            (300, 200), (200, 200), (100, 200), (0, 200),  # Zeile Y=200
            (300, 300), (200, 300), (100, 300), (0, 300)   # Zeile Y=300 (oben)
        ]

        actual_positions = [s['position'] for s in sorted_symbols]

        assert actual_positions == expected_positions, f"Fehler! Erwartet: {expected_positions}, Erhalten: {actual_positions}"


    def test_left_right(self):
        """
        Test LEFT_RIGHT: Spaltenweise von links nach rechts
        """
        symbols = create_test_symbols()
        sorted_symbols = sort_symbols_by_direction(symbols, "LEFT_RIGHT")

        # Spalte für Spalte: X=0, dann X=100, dann X=200, dann X=300
        # Innerhalb jeder Spalte: Y aufsteigend (0, 100, 200, 300)
        expected_positions = [
            (0, 0), (0, 100), (0, 200), (0, 300),        # Spalte X=0
            (100, 0), (100, 100), (100, 200), (100, 300),  # Spalte X=100
            (200, 0), (200, 100), (200, 200), (200, 300),  # Spalte X=200
            (300, 0), (300, 100), (300, 200), (300, 300)   # Spalte X=300
        ]

        actual_positions = [s['position'] for s in sorted_symbols]

        assert actual_positions == expected_positions, f"Fehler! Erwartet: {expected_positions}, Erhalten: {actual_positions}"


    def test_right_left(self):
        """
        Test RIGHT_LEFT: Spaltenweise von rechts nach links
        """
        symbols = create_test_symbols()
        sorted_symbols = sort_symbols_by_direction(symbols, "RIGHT_LEFT")

        # Spalte für Spalte: X=300, dann X=200, dann X=100, dann X=0
        # Innerhalb jeder Spalte: Y aufsteigend (0, 100, 200, 300)
        expected_positions = [
            (300, 0), (300, 100), (300, 200), (300, 300),  # Spalte X=300
            (200, 0), (200, 100), (200, 200), (200, 300),  # Spalte X=200
            (100, 0), (100, 100), (100, 200), (100, 300),  # Spalte X=100
            (0, 0), (0, 100), (0, 200), (0, 300)        # Spalte X=0
        ]

        actual_positions = [s['position'] for s in sorted_symbols]

        assert actual_positions == expected_positions, f"Fehler! Erwartet: {expected_positions}, Erhalten: {actual_positions}"


    def test_top_bottom(self):
        """
        Test TOP_BOTTOM: Default ist TOP_BOTTOM/LEFT_RIGHT
        """
        symbols = create_test_symbols()
        sorted_symbols = sort_symbols_by_direction(symbols, "TOP_BOTTOM")

        # Sollte identisch mit TOP_BOTTOM/LEFT_RIGHT sein
        expected_positions = [
            (0, 300), (100, 300), (200, 300), (300, 300),
            (0, 200), (100, 200), (200, 200), (300, 200),
            (0, 100), (100, 100), (200, 100), (300, 100),
            (0, 0), (100, 0), (200, 0), (300, 0)
        ]

        actual_positions = [s['position'] for s in sorted_symbols]

        assert actual_positions == expected_positions, f"Fehler! Erwartet: {expected_positions}, Erhalten: {actual_positions}"


    def test_bottom_top(self):
        """
        Test BOTTOM_TOP: Default ist BOTTOM_TOP/LEFT_RIGHT
        """
        symbols = create_test_symbols()
        sorted_symbols = sort_symbols_by_direction(symbols, "BOTTOM_TOP")

        # Sollte identisch mit BOTTOM_TOP/LEFT_RIGHT sein
        expected_positions = [
            (0, 0), (100, 0), (200, 0), (300, 0),
            (0, 100), (100, 100), (200, 100), (300, 100),
            (0, 200), (100, 200), (200, 200), (300, 200),
            (0, 300), (100, 300), (200, 300), (300, 300)
        ]

        actual_positions = [s['position'] for s in sorted_symbols]

        assert actual_positions == expected_positions, f"Fehler! Erwartet: {expected_positions}, Erhalten: {actual_positions}"


    def test_left_right_top_bottom(self):
        """
        Test LEFT_RIGHT/TOP_BOTTOM: Umgekehrte Reihenfolge, identisch mit TOP_BOTTOM/LEFT_RIGHT
        """
        symbols = create_test_symbols()
        sorted_symbols = sort_symbols_by_direction(symbols, "LEFT_RIGHT/TOP_BOTTOM")

        expected_positions = [
            (0, 300), (0, 200), (0, 100), (0, 0),
            (100, 300), (100, 200), (100, 100), (100, 0),
            (200, 300), (200, 200), (200, 100), (200, 0),
            (300, 300), (300, 200), (300, 100), (300, 0)
        ]

        actual_positions = [s['position'] for s in sorted_symbols]

        assert actual_positions == expected_positions, f"Fehler! Erwartet: {expected_positions}, Erhalten: {actual_positions}"


    def test_right_left_top_bottom(self):
        """
        Test RIGHT_LEFT/TOP_BOTTOM: Umgekehrte Reihenfolge, identisch mit TOP_BOTTOM/RIGHT_LEFT
        """
        symbols = create_test_symbols()
        sorted_symbols = sort_symbols_by_direction(symbols, "RIGHT_LEFT/TOP_BOTTOM")

        expected_positions = [
            (300, 300), (300, 200), (300, 100), (300, 0),
            (200, 300), (200, 200), (200, 100), (200, 0),
            (100, 300), (100, 200), (100, 100), (100, 0),
            (0, 300),   (0, 200),   (0, 100),   (0, 0)
        ]

        actual_positions = [s['position'] for s in sorted_symbols]

        assert actual_positions == expected_positions, f"Fehler! Erwartet: {expected_positions}, Erhalten: {actual_positions}"


    def test_left_right_bottom_top(self):
        """
        Test LEFT_RIGHT/BOTTOM_TOP: Umgekehrte Reihenfolge, identisch mit BOTTOM_TOP/LEFT_RIGHT
        """
        symbols = create_test_symbols()
        sorted_symbols = sort_symbols_by_direction(symbols, "LEFT_RIGHT/BOTTOM_TOP")

        expected_positions = [
              (0, 0),   (0, 100),   (0, 200),   (0, 300),
            (100, 0), (100, 100), (100, 200), (100, 300),
            (200, 0), (200, 100), (200, 200), (200, 300),
            (300, 0), (300, 100), (300, 200), (300, 300),
        ]

        actual_positions = [s['position'] for s in sorted_symbols]

        assert actual_positions == expected_positions, f"Fehler! Erwartet: {expected_positions}, Erhalten: {actual_positions}"


    def test_right_left_bottom_top(self):
        """
        Test RIGHT_LEFT/BOTTOM_TOP: Umgekehrte Reihenfolge, identisch mit BOTTOM_TOP/RIGHT_LEFT
        """
        symbols = create_test_symbols()
        sorted_symbols = sort_symbols_by_direction(symbols, "RIGHT_LEFT/BOTTOM_TOP")

        # Sollte identisch mit BOTTOM_TOP/RIGHT_LEFT sein
        expected_positions = [
            (300, 0), (300, 100), (300, 200), (300, 300),
            (200, 0), (200, 100), (200, 200), (200, 300),
            (100, 0), (100, 100), (100, 200), (100, 300),
              (0, 0),   (0, 100),   (0, 200),   (0, 300),
        ]

        actual_positions = [s['position'] for s in sorted_symbols]

        assert actual_positions == expected_positions, f"Fehler! Erwartet: {expected_positions}, Erhalten: {actual_positions}"


    def test_fallback(self):
        """
        Test Fallback (unbekannte DIRECTION): Default ist TOP_BOTTOM/LEFT_RIGHT
        """
        symbols = create_test_symbols()
        sorted_symbols = sort_symbols_by_direction(symbols, "UNKNOWN_DIRECTION")

        # Sollte identisch mit TOP_BOTTOM/LEFT_RIGHT sein
        expected_positions = [
            (0, 300), (100, 300), (200, 300), (300, 300),
            (0, 200), (100, 200), (200, 200), (300, 200),
            (0, 100), (100, 100), (200, 100), (300, 100),
            (0, 0), (100, 0), (200, 0), (300, 0)
        ]

        actual_positions = [s['position'] for s in sorted_symbols]

        assert actual_positions == expected_positions, f"Fehler! Erwartet: {expected_positions}, Erhalten: {actual_positions}"




#     print("\n16 Symbole auf 4x4 Raster:")
#     print("  X-Koordinaten: 0, 100, 200, 300")
#     print("  Y-Koordinaten: 0, 100, 200, 300")
#     print("\nUnterstützte Richtungen (beide Reihenfolgen):")
#     print("  - TOP_BOTTOM/LEFT_RIGHT = LEFT_RIGHT/TOP_BOTTOM")
#     print("  - TOP_BOTTOM/RIGHT_LEFT = RIGHT_LEFT/TOP_BOTTOM")
#     print("  - BOTTOM_TOP/LEFT_RIGHT = LEFT_RIGHT/BOTTOM_TOP")
#     print("  - BOTTOM_TOP/RIGHT_LEFT = RIGHT_LEFT/BOTTOM_TOP")
#     print("\nEinfache Richtungen:")
#     print("  - LEFT_RIGHT: Spaltenweise links→rechts (sortiert nach X, dann Y)")
#     print("  - RIGHT_LEFT: Spaltenweise rechts→links (sortiert nach -X, dann Y)")
#     print("  - TOP_BOTTOM → TOP_BOTTOM/LEFT_RIGHT (zeilenweise)")
#     print("  - BOTTOM_TOP → BOTTOM_TOP/LEFT_RIGHT (zeilenweise)")

#     # Test kombinierte Richtungen (Y/X Reihenfolge)
#     test_top_bottom_left_right()
#     test_top_bottom_right_left()
#     test_bottom_top_left_right()
#     test_bottom_top_right_left()

#     # Test einfache Richtungen
#     test_left_right()
#     test_right_left()
#     test_top_bottom()
#     test_bottom_top()

#     # Test umgekehrte Reihenfolge (X/Y Reihenfolge)
#     test_left_right_top_bottom()
#     test_right_left_top_bottom()
#     test_left_right_bottom_top()
#     test_right_left_bottom_top()

#     # Test Fallback
#     test_fallback()


#     print("\n" + "="*70)
#     print("✓✓✓ ALLE 13 TESTS BESTANDEN ✓✓✓")
#     print("="*70)
#     print("\nZusammenfassung:")
#     print("  - Alle 4 kombinierten Richtungen (Y/X) funktionieren")
#     print("  - Alle 4 kombinierten Richtungen (X/Y) funktionieren")
#     print("  - Alle 4 einfachen Richtungen mappen korrekt")
#     print("  - Fallback funktioniert")



if __name__ == '__main__':
    unittest.main()
