import sys
import os
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout, QHBoxLayout, QFileDialog, QLabel, QMessageBox, QCheckBox, QComboBox, QRadioButton, QButtonGroup
from PyQt5.QtCore import QUrl, Qt
from PyQt5.QtGui import QDesktopServices
from fastkml import kml
from fastkml.geometry import Point, LineString, Polygon
import ezdxf
from pyproj import Transformer, CRS

class KMLDXFConverter(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
        self.init_projections()

    def initUI(self):
        self.setWindowTitle('KML/DXF Dönüştürücü v2')
        self.setFixedSize(400, 300)
        self.setWindowFlags(self.windowFlags() & ~Qt.WindowMaximizeButtonHint)

        layout = QVBoxLayout()

        self.direction_group = QButtonGroup(self)
        self.kml_to_dxf_radio = QRadioButton('KML/KMZ → DXF', self)
        self.dxf_to_kml_radio = QRadioButton('DXF/DWG → KML', self)
        self.direction_group.addButton(self.kml_to_dxf_radio)
        self.direction_group.addButton(self.dxf_to_kml_radio)
        self.kml_to_dxf_radio.setChecked(True)
        layout.addWidget(self.kml_to_dxf_radio)
        layout.addWidget(self.dxf_to_kml_radio)

        self.file_button = QPushButton('Dosya Seç', self)
        self.file_button.clicked.connect(self.select_file)
        layout.addWidget(self.file_button)

        self.file_label = QLabel('Seçilen dosya: Yok', self)
        layout.addWidget(self.file_label)

        self.projection_combo = QComboBox(self)
        self.projection_combo.addItems(['ITRF96 / TM30', 'ITRF96 / TM33', 'ITRF96 / TM36', 'ITRF96 / TM39', 'Web Mercator'])
        layout.addWidget(QLabel('Projeksiyon Seç:'))
        layout.addWidget(self.projection_combo)

        self.explode_checkbox = QCheckBox('Objeleri parçala', self)
        layout.addWidget(self.explode_checkbox)

        self.convert_save_button = QPushButton('Dönüştür ve Kaydet', self)
        self.convert_save_button.clicked.connect(self.convert_and_save)
        layout.addWidget(self.convert_save_button)

        self.about_button = QPushButton('Hakkında', self)
        self.about_button.clicked.connect(self.open_about)
        layout.addWidget(self.about_button)

        self.setLayout(layout)

    def init_projections(self):
        self.projections = {
            'ITRF96 / TM30': 'EPSG:5254',
            'ITRF96 / TM33': 'EPSG:5255',
            'ITRF96 / TM36': 'EPSG:5256',
            'ITRF96 / TM39': 'EPSG:5257',
            'Web Mercator': 'EPSG:3857'
        }

    def select_file(self):
        if self.kml_to_dxf_radio.isChecked():
            file_name, _ = QFileDialog.getOpenFileName(self, 'KML/KMZ Dosyası Seç', '', 'KML/KMZ Files (*.kml *.kmz)')
        else:
            file_name, _ = QFileDialog.getOpenFileName(self, 'DXF/DWG Dosyası Seç', '', 'DXF/DWG Files (*.dxf *.dwg)')
        if file_name:
            self.input_file = file_name
            self.file_label.setText(f'Seçilen dosya: {os.path.basename(file_name)}')

    def convert_and_save(self):
        if not hasattr(self, 'input_file'):
            QMessageBox.warning(self, 'Hata', 'Lütfen önce bir dosya seçin.')
            return

        proj = self.projections[self.projection_combo.currentText()]
        
        if self.kml_to_dxf_radio.isChecked():
            output_file, _ = QFileDialog.getSaveFileName(self, 'DXF Olarak Kaydet', '', 'DXF Files (*.dxf)')
            if output_file:
                try:
                    self.kml_to_dxf(self.input_file, output_file, self.explode_checkbox.isChecked(), proj)
                    QMessageBox.information(self, 'Başarılı', 'KML/KMZ → DXF dönüştürme işlemi tamamlandı!')
                except Exception as e:
                    QMessageBox.critical(self, 'Hata', f'Dönüştürme sırasında bir hata oluştu: {str(e)}')
        else:
            output_file, _ = QFileDialog.getSaveFileName(self, 'KML Olarak Kaydet', '', 'KML Files (*.kml)')
            if output_file:
                try:
                    self.dxf_to_kml(self.input_file, output_file, proj)
                    QMessageBox.information(self, 'Başarılı', 'DXF/DWG → KML dönüştürme işlemi tamamlandı!')
                except Exception as e:
                    QMessageBox.critical(self, 'Hata', f'Dönüştürme sırasında bir hata oluştu: {str(e)}')

    def open_about(self):
        QDesktopServices.openUrl(QUrl("https://ettunc.com"))

    def kml_to_dxf(self, kml_file, dxf_file, explode, proj):
        with open(kml_file, 'rb') as f:
            k = kml.KML()
            k.from_string(f.read())

        doc = ezdxf.new('R2010')
        msp = doc.modelspace()

        self.transformer = Transformer.from_crs("EPSG:4326", proj, always_xy=True)

        features = list(k.features())
        while features:
            feature = features.pop(0)
            if hasattr(feature, 'features'):
                features.extend(feature.features())
            if isinstance(feature, kml.Placemark):
                geometry = feature.geometry
                if geometry:
                    self.process_geometry(msp, geometry, explode)

        doc.saveas(dxf_file)

    def process_geometry(self, msp, geometry, explode):
        if geometry.geom_type == 'Point':
            x, y = self.transform_point(geometry.x, geometry.y)
            msp.add_point((x, y))
        elif geometry.geom_type == 'LineString':
            points = [self.transform_point(p[0], p[1]) for p in geometry.coords]
            if explode:
                for i in range(len(points) - 1):
                    msp.add_line(points[i], points[i+1])
            else:
                msp.add_lwpolyline(points)
        elif geometry.geom_type == 'Polygon':
            exterior = [self.transform_point(p[0], p[1]) for p in geometry.exterior.coords]
            if explode:
                for i in range(len(exterior) - 1):
                    msp.add_line(exterior[i], exterior[i+1])
                for interior in geometry.interiors:
                    interior_points = [self.transform_point(p[0], p[1]) for p in interior.coords]
                    for i in range(len(interior_points) - 1):
                        msp.add_line(interior_points[i], interior_points[i+1])
            else:
                msp.add_lwpolyline(exterior, close=True)
                for interior in geometry.interiors:
                    interior_points = [self.transform_point(p[0], p[1]) for p in interior.coords]
                    msp.add_lwpolyline(interior_points, close=True)
        elif geometry.geom_type == 'MultiGeometry':
            for geom in geometry.geoms:
                self.process_geometry(msp, geom, explode)

    def transform_point(self, lon, lat):
        x, y = self.transformer.transform(lon, lat)
        return x, y

    def dxf_to_kml(self, dxf_file, kml_file, proj):
        doc = ezdxf.readfile(dxf_file)
        msp = doc.modelspace()

        k = kml.KML()
        d = kml.Document(ns=None, name="DXF Conversion")
        k.append(d)

        transformer = Transformer.from_crs(proj, "EPSG:4326", always_xy=True)

        for entity in msp:
            if entity.dxftype() == 'POINT':
                x, y = transformer.transform(entity.dxf.location[0], entity.dxf.location[1])
                point = Point(y, x)
                p = kml.Placemark(ns=None, geometry=point)
                d.append(p)
            elif entity.dxftype() == 'LINE':
                start = transformer.transform(entity.dxf.start[0], entity.dxf.start[1])
                end = transformer.transform(entity.dxf.end[0], entity.dxf.end[1])
                line = LineString([(start[1], start[0]), (end[1], end[0])])
                p = kml.Placemark(ns=None, geometry=line)
                d.append(p)
            elif entity.dxftype() == 'LWPOLYLINE':
                points = [transformer.transform(point[0], point[1]) for point in entity.get_points()]
                if entity.closed:
                    poly = Polygon([(p[1], p[0]) for p in points])
                    p = kml.Placemark(ns=None, geometry=poly)
                else:
                    line = LineString([(p[1], p[0]) for p in points])
                    p = kml.Placemark(ns=None, geometry=line)
                d.append(p)

        with open(kml_file, 'w', encoding='utf-8') as f:
            f.write(k.to_string(prettyprint=True))

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = KMLDXFConverter()
    ex.show()
    sys.exit(app.exec_())
