import FreeCAD as App
import Part
import math
import Draft
import os
from PySide import QtGui

# ... (DATA bleibt gleich) ...
DATA = {
    0.50:  [7.0,   8.0,  16.5, 12.0,  29.0,  7.0,   13.0,  6.0,   0.06],
    0.75:  [9.0,   10.0, 20.0, 13.5,  32.0,  9.0,   17.0,  8.0,   0.11],
    1.00:  [10.0,  11.0, 22.5, 17.0,  36.5,  10.0,  19.0,  10.0,  0.16],
    1.50:  [11.0,  13.0, 26.5, 18.5,  43.0,  11.0,  22.0,  11.0,  0.22],
    2.00:  [13.5,  16.0, 34.0, 22.0,  51.0,  13.5,  24.0,  13.0,  0.42],
    3.25:  [16.0,  19.0, 40.0, 27.0,  64.0,  16.0,  30.0,  15.0,  0.74],
    4.75:  [19.0,  22.0, 46.0, 31.0,  76.0,  19.0,  32.0,  18.0,  1.18],
    6.50:  [22.0,  25.0, 52.0, 36.0,  83.0,  22.0,  36.0,  20.0,  1.77],
    8.50:  [25.0,  28.0, 59.0, 43.0,  95.0,  25.0,  41.0,  23.0,  2.58],
    9.50:  [28.0,  32.0, 66.0, 47.0,  108.0, 28.0,  50.0,  27.0,  3.66],
    12.0:  [32.0,  35.0, 72.0, 51.0,  115.0, 32.0,  55.0,  30.0,  4.91],
    13.5:  [35.0,  38.0, 80.0, 57.0,  133.0, 35.0,  60.0,  32.0,  6.54],
    17.0:  [38.0,  42.0, 88.0, 60.0,  146.0, 38.0,  65.0,  35.0,  8.19],
    25.0:  [45.0,  50.0, 103.0, 74.0, 178.0, 45.0,  75.0,  40.0,  14.22],
    35.0:  [50.0,  57.0, 111.0, 83.0, 197.0, 50.0,  85.0,  45.0,  19.85],
    42.5:  [57.0,  65.0, 130.0, 95.0, 222.0, 57.0,  95.0,  50.0,  28.33],
    55.0:  [65.0,  70.0, 145.0, 105.0, 260.0, 65.0,  105.0, 55.0,  39.59],
    85.0:  [75.0,  83.0, 163.0, 127.0, 329.0, 75.0,  125.0, 65.0,  62.00],
    120.0: [95.0,  95.0, 200.0, 146.0, 397.0, 95.0,  145.0, 75.0,  110.00],
    150.0: [105.0, 108.0, 225.0, 165.0, 434.0, 105.0, 165.0, 85.0,  160.00],
    250.0: [140.0, 140.0, 300.0, 210.0, 540.0, 140.0, 210.0, 110.0, 305.0],
    400.0: [170.0, 175.0, 370.0, 260.0, 680.0, 175.0, 260.0, 140.0, 565.0],
    600.0: [205.0, 210.0, 450.0, 310.0, 820.0, 210.0, 315.0, 170.0, 980.0]
}

def make_hex_shape(width, height):
    r = width / math.sqrt(3)
    pts = [App.Vector(r * math.cos(math.radians(a)), r * math.sin(math.radians(a)), 0) for a in range(0, 361, 60)]
    poly = Part.makePolygon(pts + [pts[0]])
    face = Part.Face(Part.Wire(poly))
    return face.extrude(App.Vector(0, 0, height))

def create_shackle_compound(wll):
    doc = App.ActiveDocument or App.newDocument(f"Shackle_{wll}t")
    d = DATA[wll]
    bow_H, pin_D, eye_G, inner_W, inner_H_total, jaw_F, nut_W, nut_H, weight = d
    
    eye_R, eye_T = eye_G / 2.0, bow_H
    r_unten = (jaw_F + eye_T) / 2.0
    r_oben = (inner_W + bow_H) / 2.0
    h_gerade = inner_H_total - r_oben
    
    # KORREKTUR: Tieferes Eintauchen (Overlap)
    # Wir starten den Pfad deutlich tiefer im Auge (Y-Richtung)
    overlap_y = eye_R * 0.5 

    # 1. Bow Pfad
    p1 = App.Vector(-r_unten, -overlap_y, 0)
    p2 = App.Vector(-r_oben, h_gerade, 0)
    p3 = App.Vector(r_oben, h_gerade, 0)
    p4 = App.Vector(r_unten, -overlap_y, 0)
    
    arc = Part.ArcOfCircle(p2, App.Vector(0, h_gerade + r_oben, 0), p3)
    path = Part.Wire([Part.LineSegment(p1, p2).toShape(), arc.toShape(), Part.LineSegment(p3, p4).toShape()])
    
    # Sweep Querschnitt senkrecht zum Start-Segment
    circle = Part.makeCircle(bow_H/2.0, p1, p2 - p1)
    bow_s = path.makePipe(Part.Wire([circle]))
    bow_s.translate(App.Vector(0, eye_R, 0))

    # 2. Augen
    eye_base = Part.makeCylinder(eye_R, eye_T, App.Vector(-eye_T/2.0, 0, 0), App.Vector(1, 0, 0))
    eye_base = eye_base.cut(Part.makeCylinder(pin_D/2.0, eye_T+10, App.Vector(-20, 0, 0), App.Vector(1, 0, 0)))
    eye_L = eye_base.copy(); eye_L.translate(App.Vector(-r_unten, 0, 0))
    eye_R_s = eye_base.copy(); eye_R_s.translate(App.Vector(r_unten, 0, 0))

    # 3. Bolzen & Mutter
    overhang, head_K = 15.0, nut_H * 0.8
    pin_start_x, nut_x = -r_unten - eye_T/2.0, r_unten + eye_T/2.0
    
    head = make_hex_shape(nut_W, head_K)
    head.rotate(App.Vector(0,0,0), App.Vector(0,1,0), 90)
    head.translate(App.Vector(pin_start_x - head_K, 0, 0))
    
    shaft = Part.makeCylinder(pin_D/2.0, (nut_x + nut_H + overhang) - pin_start_x, App.Vector(pin_start_x, 0, 0), App.Vector(1, 0, 0))
    
    nut = make_hex_shape(nut_W, nut_H).cut(Part.makeCylinder(pin_D/2.0, nut_H+2, App.Vector(0,0,-1), App.Vector(0,0,1)))
    nut.rotate(App.Vector(0,0,0), App.Vector(0,1,0), 90)
    nut.translate(App.Vector(nut_x, 0, 0))

    # 4. WLL Text (Verbesserte Font-Suche)
    t_shape = None
    fonts = ["C:/Windows/Fonts/arialbd.ttf", "C:/Windows/Fonts/arial.ttf", "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf"]
    font_file = ""
    for f in fonts:
        if os.path.exists(f):
            font_file = f
            break
            
    if font_file:
        try:
            s_str = Draft.makeShapeString(f"{wll}t", font_file, size=bow_H*0.4)
            t_shape = s_str.Shape.extrude(App.Vector(0, 0, 3.0))
            t_shape.rotate(App.Vector(0,0,0), App.Vector(1,0,0), 90)
            # Positionierung auf der Bogen-Flanke
            t_shape.translate(App.Vector(-bow_H*0.5, h_gerade + eye_R, r_oben))
            doc.removeObject(s_str.Name)
        except: pass

    # --- FARBEN & COMPOUND ---
    # Wir erstellen zwei Compounds für die Optik
    green_parts = Part.makeCompound([bow_s, eye_L, eye_R_s])
    steel_parts = Part.makeCompound([head, shaft, nut])
    
    shackle_main = doc.addObject("Part::Feature", f"GreenPin_{wll}t")
    if t_shape:
        shackle_main.Shape = Part.makeCompound([green_parts, steel_parts, t_shape])
    else:
        shackle_main.Shape = Part.makeCompound([green_parts, steel_parts])

    # Properties hinzufügen
    sh_obj = shackle_main
    if not hasattr(sh_obj, "Weight"): sh_obj.addProperty("App::PropertyFloat", "Weight", "Rigging").Weight = weight
    if not hasattr(sh_obj, "WLL"): sh_obj.addProperty("App::PropertyFloat", "WLL", "Rigging").WLL = wll
    if not hasattr(sh_obj, "Bow_D"): sh_obj.addProperty("App::PropertyFloat", "Bow_D", "Rigging").Bow_D = bow_H

    # Visuals
    sh_obj.ViewObject.ShapeColor = (0.0, 0.5, 0.0)
    # Farbe für Bolzen/Mutter im Compound via Sub-Elemente ist schwer, 
    # daher lassen wir es erstmal einheitlich, fixen aber die Bounding Box:
    sh_obj.purgeTouched()
    doc.recompute()

class ShackleUI(QtGui.QWidget):
    def __init__(self):
        super(ShackleUI, self).__init__()
        layout = QtGui.QVBoxLayout(self)
        self.combo = QtGui.QComboBox()
        self.combo.addItems([str(w) for w in sorted(DATA.keys())])
        layout.addWidget(QtGui.QLabel("Green Pin WLL:"))
        layout.addWidget(self.combo)
        btn = QtGui.QPushButton("Generieren")
        btn.clicked.connect(self.run)
        layout.addWidget(btn)
        self.show()
    def run(self):
        create_shackle_compound(float(self.combo.currentText()))
        self.close()

if __name__ == "__main__":
    ui = ShackleUI()