#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
FreeCAD Simple Info - Bounding Box ve Alüminyum Ağırlık Hesaplayıcı
FreeCADCmd ile uyumlu basit bilgi çıkarma scripti
STP dosyasını otomatik olarak açıp tüm nesneleri analiz eder
fcinfo.py SAT 234-240, 375-377, 623-630, 3459-3491 AYNEN ALINMIŞTIR
"""

import FreeCAD
import FreeCAD as App
import sys
import os
import json

# GLOBAL DEĞİŞKENLER (fcinfo.py satır 375-377, 623-630)
seTDecimalValue = 4  # fcinfo.py satır 375-377
uniteM  = 1.0   # mm (fcinfo.py satır 623)
uniteMs = "mm"  # fcinfo.py satır 624
uniteS  = 1.0   # mm² (fcinfo.py satır 625)
uniteSs = "mm²" # fcinfo.py satır 626
uniteV  = 1.0   # mm³ (fcinfo.py satır 627)
uniteVs = "mm³" # fcinfo.py satır 628
uniteP  = 1.0   # gram (fcinfo.py satır 629)
unitePs = "g"   # fcinfo.py satır 630

def Around(a):
    """
    fcinfo.py satır 234-240 AYNEN ALINDI
    """
    global seTDecimalValue

    if seTDecimalValue == -1:
        seTDecimalValue = 1000
    ard = round(a, seTDecimalValue)
    return ard

def get_object_info(obj):
    """
    fcinfo.py satır 3459-3491 AYNEN ALINDI - SHAPE İÇİN
    """
    global seTDecimalValue, uniteM, uniteMs, uniteV, uniteVs, uniteP, unitePs

    # Alüminyum yoğunluğu (fcinfo.py satır 2138)
    seTDensiteValue = 2.71  # kg/dm³ - Metal Aluminium (Al)

    try:
        print(f"\n[DEBUG] ===== Nesne: {obj.Name} =====")
        print(f"[DEBUG] TypeId: {obj.TypeId if hasattr(obj, 'TypeId') else 'N/A'}")
        print(f"[DEBUG] Label: {obj.Label if hasattr(obj, 'Label') else 'N/A'}")

        # Shape kontrolü
        if not hasattr(obj, "Shape"):
            print(f"[DEBUG] ✗ Shape YOK, atlanıyor\n")
            return None

        # fcinfo.py satır 3459: surface (object)
        try:
            surface = obj.Shape.Area
            print(f"[DEBUG] surface = obj.Shape.Area = {surface}")
        except Exception as e:
            surface = 0.0
            print(f"[DEBUG] surface HATA: {e}, = 0.0")

        # fcinfo.py satır 3470: volume
        try:
            volume_ = obj.Shape.Volume
            print(f"[DEBUG] volume_ = obj.Shape.Volume = {volume_}")
        except Exception as e:
            volume_ = 0.0
            print(f"[DEBUG] volume_ HATA: {e}, = 0.0")

        # fcinfo.py satır 3475: poids (TAM FORMÜL)
        poids = ((volume_ * seTDensiteValue) * uniteP) / 1000.0
        print(f"[DEBUG] poids = ((volume_ * seTDensiteValue) * uniteP) / 1000.0")
        print(f"[DEBUG] poids = (({volume_} * {seTDensiteValue}) * {uniteP}) / 1000.0 = {poids}")

        # AXIS-ALIGNED BoundBox (eski yöntem - YANLIŞ yönlerde)
        try:
            print(f"[DEBUG] Axis-Aligned BoundBox (YANLIŞ yönler):")
            boundBox_aa = obj.Shape.BoundBox
            boundBoxLX_aa = boundBox_aa.XLength
            boundBoxLY_aa = boundBox_aa.YLength
            boundBoxLZ_aa = boundBox_aa.ZLength
            print(f"[DEBUG]   X={boundBoxLX_aa}, Y={boundBoxLY_aa}, Z={boundBoxLZ_aa}")
        except Exception as e:
            print(f"[DEBUG] Axis-Aligned BoundBox HATA: {e}")
            boundBoxLX_aa = boundBoxLY_aa = boundBoxLZ_aa = 0.0

        # OPTIMAL BoundBox (DOĞRU yönlerde - Oriented Bounding Box)
        try:
            print(f"[DEBUG] Optimal BoundBox (DOĞRU yönler - OBB):")
            import Part
            obb = obj.Shape.optimalBoundingBox()
            print(f"[DEBUG] optimalBoundingBox() = {obb}")

            boundBoxLX = obb.XLength
            boundBoxLY = obb.YLength
            boundBoxLZ = obb.ZLength
            boundBoxDiag = obb.DiagonalLength

            print(f"[DEBUG] ✓ OBB X={boundBoxLX}, Y={boundBoxLY}, Z={boundBoxLZ}, Diag={boundBoxDiag}")

            # String formatı
            boundBox_S = "[X: "+str(Around(boundBoxLX * uniteM))+" "+uniteMs+"] x [Y: "+str(Around(boundBoxLY * uniteM))+" "+uniteMs+"] x [Z: "+str(Around(boundBoxLZ * uniteM))+" "+uniteMs+"] Diagonal: " + str(Around(boundBoxDiag * uniteM))+" "+uniteMs
            print(f"[DEBUG] boundBox_S = {boundBox_S}")

            # Min değerler
            boundBoxXMin = obb.XMin
            boundBoxYMin = obb.YMin
            boundBoxZMin = obb.ZMin
            print(f"[DEBUG] OBB Min: X={boundBoxXMin}, Y={boundBoxYMin}, Z={boundBoxZMin}")

        except Exception as e:
            print(f"[DEBUG] ✗ Optimal BoundBox HATA: {e}")
            print(f"[DEBUG] Axis-Aligned değerleri kullanılıyor...")
            boundBoxLX = boundBoxLX_aa
            boundBoxLY = boundBoxLY_aa
            boundBoxLZ = boundBoxLZ_aa
            try:
                boundBoxDiag = boundBox_aa.DiagonalLength
            except:
                boundBoxDiag = 0.0
            boundBox_S = "[FALLBACK] [X: "+str(Around(boundBoxLX * uniteM))+" "+uniteMs+"] x [Y: "+str(Around(boundBoxLY * uniteM))+" "+uniteMs+"] x [Z: "+str(Around(boundBoxLZ * uniteM))+" "+uniteMs+"]"
            boundBoxXMin = boundBoxYMin = boundBoxZMin = 0.0

        # Matrix of Inertia
        try:
            matrixOfInertia = obj.Shape.MatrixOfInertia
            matrixOfInertiaRaw = str(matrixOfInertia)
            print(f"[DEBUG] Matrix of Inertia: {matrixOfInertiaRaw}")
        except Exception as e:
            matrixOfInertiaRaw = ""
            print(f"[DEBUG] Matrix of Inertia HATA: {e}")

        # Sonuçlar - TÜM PARAMETRELER
        result = {
            'object_name': obj.Label if hasattr(obj, 'Label') else obj.Name,  # STEP body ismini önceliklendir
            'object_label': obj.Label if hasattr(obj, 'Label') else obj.Name,
            'object_type': obj.TypeId if hasattr(obj, 'TypeId') else 'Unknown',

            # Boyutlar - Optimal BoundBox (DOĞRU)
            'bounding_box': {
                'x_length_mm': Around(boundBoxLX * uniteM),
                'y_length_mm': Around(boundBoxLY * uniteM),
                'z_length_mm': Around(boundBoxLZ * uniteM),
                'diagonal_mm': Around(boundBoxDiag * uniteM),
                'x_min': Around(boundBoxXMin),
                'y_min': Around(boundBoxYMin),
                'z_min': Around(boundBoxZMin),
                'string': boundBox_S,
                'type': 'optimal_oriented'
            },

            # Boyutlar - Axis-Aligned (eski/yanlış yönler)
            'bounding_box_axis_aligned': {
                'x_length_mm': Around(boundBoxLX_aa * uniteM),
                'y_length_mm': Around(boundBoxLY_aa * uniteM),
                'z_length_mm': Around(boundBoxLZ_aa * uniteM),
                'type': 'axis_aligned'
            },

            # Hacim ve Yüzey
            'surface_mm2': Around(surface),
            'volume_mm3': Around(volume_),
            'volume_cm3': Around(volume_ / 1000.0),

            # Ağırlık - Alüminyum (Yoğunluk: 2.7 kg/dm³)
            'weight_aluminium': {
                'grams': Around(poids),
                'kilograms': Around(poids / 1000.0),
                'density_kg_dm3': seTDensiteValue
            },

            # Matrix of Inertia
            'matrix_of_inertia': {
                'raw': matrixOfInertiaRaw
            }
        }

        print(f"[DEBUG] ✓ BAŞARILI")
        print(f"[DEBUG] Sonuç OBB: X={result['bounding_box']['x_length_mm']} Y={result['bounding_box']['y_length_mm']} Z={result['bounding_box']['z_length_mm']}")
        print(f"[DEBUG] =====================================\n")
        return result

    except Exception as e:
        print(f"[DEBUG] ✗✗✗ GENEL HATA: {e}\n")
        import traceback
        traceback.print_exc()
        return None


def print_object_info(result):
    """Sonuçları yazdır"""
    if result:
        print("\n" + "="*70)
        print(f"Nesne: {result['object_label']} ({result['object_name']})")
        print(f"Tip  : {result['object_type']}")
        print("="*70)
        print(f"Optimal BoundBox (DOĞRU):")
        print(f"  X Length     : {result['bounding_box']['x_length_mm']} mm")
        print(f"  Y Length     : {result['bounding_box']['y_length_mm']} mm")
        print(f"  Z Length     : {result['bounding_box']['z_length_mm']} mm")
        print(f"  Diagonal     : {result['bounding_box']['diagonal_mm']} mm")
        print(f"  String       : {result['bounding_box']['string']}")
        print(f"\nAxis-Aligned BoundBox (eski):")
        print(f"  X: {result['bounding_box_axis_aligned']['x_length_mm']} mm")
        print(f"  Y: {result['bounding_box_axis_aligned']['y_length_mm']} mm")
        print(f"  Z: {result['bounding_box_axis_aligned']['z_length_mm']} mm")
        print(f"\nYüzey ve Hacim:")
        print(f"  Surface      : {result['surface_mm2']} mm²")
        print(f"  Volume       : {result['volume_mm3']} mm³ ({result['volume_cm3']} cm³)")
        print(f"\nAlüminyum Ağırlık:")
        print(f"  Weight       : {result['weight_aluminium']['grams']} g")
        print(f"               : {result['weight_aluminium']['kilograms']} kg")
        print(f"  Density      : {result['weight_aluminium']['density_kg_dm3']} kg/dm³")
        print("="*70)


def analyze_step_file(file_path):
    """
    STP/STEP dosyasını açıp tüm nesneleri analiz eder

    Args:
        file_path: STP/STEP dosya yolu

    Returns:
        list: Tüm nesnelerin bilgilerini içeren liste
    """
    # Dosya kontrolü
    if not os.path.exists(file_path):
        print(f"HATA: Dosya bulunamadı: {file_path}")
        return []

    print(f"\nDosya açılıyor: {file_path}")
    print("Lütfen bekleyin...\n")

    try:
        # STEP dosyasını import et
        import Part
        print("[DEBUG] Part modülü yüklendi")

        doc = FreeCAD.newDocument("TempDoc")
        print(f"[DEBUG] Yeni doküman oluşturuldu: {doc.Name}")

        print("[DEBUG] STEP dosyası import ediliyor...")
        Part.insert(file_path, doc.Name)
        print("[DEBUG] STEP dosyası import edildi")

        # Tüm nesneleri al
        objects = doc.Objects
        print(f"[DEBUG] doc.Objects uzunluğu: {len(objects)}")

        if objects:
            print("[DEBUG] Nesne tipleri:")
            for i, obj in enumerate(objects):
                obj_type = obj.TypeId if hasattr(obj, 'TypeId') else 'Unknown'
                has_shape = hasattr(obj, 'Shape')
                has_mesh = hasattr(obj, 'Mesh')
                print(f"  [{i}] {obj.Name} - Type: {obj_type}, HasShape: {has_shape}, HasMesh: {has_mesh}")

        if not objects:
            print("HATA: Dosyada nesne bulunamadı!")
            FreeCAD.closeDocument(doc.Name)
            return []

        print(f"\nToplam {len(objects)} nesne bulundu.\n")

        results = []
        total_weight_g = 0

        # Her nesneyi analiz et
        print("="*60)
        print("NESNELER ANALİZ EDİLİYOR:")
        print("="*60)
        for i, obj in enumerate(objects):
            print(f"\n[{i+1}/{len(objects)}] Analiz ediliyor: {obj.Name}")
            result = get_object_info(obj)
            if result:
                results.append(result)
                print_object_info(result)
                total_weight_g += result['weight_aluminium']['grams']
            else:
                print(f"  → Atlandı (veri alınamadı)\n")

        # Toplam özet
        print("\n" + "="*60)
        if results:
            print("\n" + "█"*60)
            print("TOPLAM ÖZET")
            print("█"*60)
            print(f"Analiz edilen nesne sayısı: {len(results)}")
            print(f"Toplam alüminyum ağırlık  : {round(total_weight_g, 2)} g")
            print(f"                           : {round(total_weight_g / 1000.0, 4)} kg")
            print("█"*60 + "\n")

            # JSON ÇIKTISI
            json_output = {
                'file_path': file_path,
                'total_objects': len(results),
                'total_weight_aluminium_grams': round(total_weight_g, 4),
                'total_weight_aluminium_kg': round(total_weight_g / 1000.0, 4),
                'objects': results
            }

            # JSON dosyasına kaydet
            json_file = file_path.replace('.stp', '_analysis.json').replace('.step', '_analysis.json')
            with open(json_file, 'w', encoding='utf-8') as f:
                json.dump(json_output, f, indent=2, ensure_ascii=False)

            print(f"\n✓ JSON çıktısı kaydedildi: {json_file}\n")

            # Console'a da yazdır
            print("\n" + "="*60)
            print("JSON ÇIKTISI:")
            print("="*60)
            print(json.dumps(json_output, indent=2, ensure_ascii=False))
            print("="*60 + "\n")
        else:
            print("\n[UYARI] Hiçbir nesne analiz edilemedi!")
            print("Muhtemel sebepler:")
            print("  - Nesnelerde Shape/Mesh özelliği yok")
            print("  - BoundBox hesaplanamıyor")
            print("  - Dosya formatı uyumsuz")
            print("="*60 + "\n")

        # Belgeyi kapat
        FreeCAD.closeDocument(doc.Name)

        return results

    except Exception as e:
        print(f"\n[HATA] Dosya açılırken hata oluştu: {str(e)}")
        import traceback
        print("\nDetaylı hata:")
        traceback.print_exc()
        return []


# FreeCADCmd kullanımı için ana fonksiyon
# FreeCADCmd ile if __name__ == "__main__" çalışmayabilir, direkt çalıştır

# Argümanları debug için yazdır
print(f"[DEBUG] Script başlatıldı")
print(f"[DEBUG] sys.argv: {sys.argv}")
print(f"[DEBUG] Toplam argüman sayısı: {len(sys.argv)}")
for i, arg in enumerate(sys.argv):
    print(f"[DEBUG] sys.argv[{i}] = {arg}")
print()

# Dosya yolunu bul
step_file = None

# freecadcmd bazen farklı şekillerde argüman geçirebilir
# Önce .stp veya .step uzantılı dosyayı ara
for arg in sys.argv[1:]:
    if arg.lower().endswith('.stp') or arg.lower().endswith('.step'):
        step_file = arg
        break

if step_file is None:
    # Uzantı bulunamazsa, son argümanı al (eğer varsa)
    if len(sys.argv) >= 2:
        step_file = sys.argv[-1]  # Son argüman

if step_file and os.path.exists(step_file):
    print(f"[DEBUG] Kullanılacak dosya: {step_file}\n")
    analyze_step_file(step_file)
else:
    print("\n[HATA] Geçerli bir STEP dosyası bulunamadı!")
    print("\nKullanım:")
    print("  freecadcmd free.py <dosya.stp>")
    print("\nÖrnek:")
    print('  freecadcmd free.py "C:\\path\\dosya.stp"')
    if step_file:
        print(f"\nBulunan dosya yolu: {step_file}")
        print(f"Dosya var mı: {os.path.exists(step_file)}")
    print()
