# -*- coding: utf-8 -*-
import os
import sys
import zipfile
import tempfile
import shutil
import xml.etree.ElementTree as ET
from PySide2 import QtWidgets, QtCore, QtGui
import FreeCAD
import Mesh
import Part
import Import
import pyproj
import simplekml

import os
from datetime import datetime

if FreeCAD.GuiUp:
    import FreeCADGui
    from PySide import QtCore
    from PySide.QtCore import QT_TRANSLATE_NOOP
    from DraftTools import translate
else:
    def translate(ctxt, txt):
        return txt

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

from PVPlantResources import DirIcons as DirIcons


# Verificación de dependencias
try:
    from pyproj import Transformer
except ImportError:
    QtWidgets.QMessageBox.critical(None, "Error", "pyproj no está instalado.")
    sys.exit(1)

try:
    import simplekml
except ImportError:
    QtWidgets.QMessageBox.critical(None, "Error", "simplekml no está instalado.")
    sys.exit(1)


class ExportKMZDialog(QtWidgets.QDialog):
    def __init__(self):
        super(ExportKMZDialog, self).__init__()
        self.setWindowTitle("Exportar a KMZ")
        self.layout = QtWidgets.QVBoxLayout(self)

        # Selección de archivo FCStd
        self.file_layout = QtWidgets.QHBoxLayout()
        self.fcstd_line = QtWidgets.QLineEdit()
        self.browse_fcstd_btn = QtWidgets.QPushButton("Examinar...")
        self.browse_fcstd_btn.clicked.connect(self.browse_fcstd)
        self.file_layout.addWidget(self.fcstd_line)
        self.file_layout.addWidget(self.browse_fcstd_btn)
        self.layout.addLayout(self.file_layout)

        # Sistema de coordenadas
        self.crs_label = QtWidgets.QLabel("Sistema de coordenadas origen:")
        self.crs_display = QtWidgets.QLabel("No encontrado")
        self.layout.addWidget(self.crs_label)
        self.layout.addWidget(self.crs_display)

        # Archivo de salida KMZ
        self.output_layout = QtWidgets.QHBoxLayout()
        self.kmz_line = QtWidgets.QLineEdit()
        self.browse_kmz_btn = QtWidgets.QPushButton("Examinar...")
        self.browse_kmz_btn.clicked.connect(self.browse_kmz)
        self.output_layout.addWidget(self.kmz_line)
        self.output_layout.addWidget(self.browse_kmz_btn)
        self.layout.addWidget(QtWidgets.QLabel("Archivo KMZ de salida:"))
        self.layout.addLayout(self.output_layout)

        # Progreso y logs
        self.progress = QtWidgets.QProgressBar()
        self.log = QtWidgets.QTextEdit()
        self.log.setReadOnly(True)
        self.layout.addWidget(self.progress)
        self.layout.addWidget(self.log)

        # Botones
        self.buttons = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
        self.buttons.accepted.connect(self.accept)
        self.buttons.rejected.connect(self.reject)
        self.layout.addWidget(self.buttons)

        path = os.path.join(os.path.dirname(FreeCAD.ActiveDocument.FileName), "outputs", "kmz")
        if not os.path.exists(path):
            os.makedirs(path)
        name = datetime.now().strftime("%Y%m%d%H%M%S") + "-" + FreeCAD.ActiveDocument.Name
        self.filename = os.path.join(path, name) + ".kmz"

    def browse_fcstd(self):
        path, _ = QtWidgets.QFileDialog.getOpenFileName(
            self, "Seleccionar archivo FreeCAD", "", "*.FCStd")
        if path:
            self.fcstd_line.setText(path)
            crs = self.get_crs_from_fcstd(path)
            self.crs_display.setText(crs if crs else "No encontrado")

    def get_crs_from_fcstd(self, path):
        try:
            with zipfile.ZipFile(path, 'r') as z:
                doc_xml = z.read('Document.xml')
                root = ET.fromstring(doc_xml)
                for prop in root.findall('.//Property[@name="CoordinateSystem"]'):
                    if prop.get('type') == 'App::PropertyString':
                        return prop.find('String').get('value')
        except Exception as e:
            self.log.append(f"Error leyendo CRS: {str(e)}")
        return None

    def browse_kmz(self):
        path, _ = QtWidgets.QFileDialog.getSaveFileName(
            self, "Guardar KMZ", "", "*.kmz")
        if path:
            self.kmz_line.setText(path)


class ExportKMZ(QtCore.QObject):
    progress_updated = QtCore.Signal(int)
    log_message = QtCore.Signal(str)

    def __init__(self, input_path, output_path, crs):
        super().__init__()
        self.input_path = input_path
        self.output_path = output_path
        self.crs = crs
        self.doc = None
        self.transformer = pyproj.Transformer.from_crs(crs, 'EPSG:4326', always_xy=True)
        self.temp_dir = tempfile.mkdtemp()
        self.kml = simplekml.Kml()
        self.model_folder = self.kml.newfolder(name='Modelos 3D')
        self.drawing_folder = self.kml.newfolder(name='Dibujos 2D')

    def process(self):
        try:
            self.doc = FreeCAD.openDocument(self.input_path)
            FreeCAD.setActiveDocument(self.doc.Name)
            self.process_objects()
            self.save_kmz()
            self.log_message.emit("Exportación completada exitosamente.")
            return True
        except Exception as e:
            self.log_message.emit(f"Error: {str(e)}")
            return False
        finally:
            if self.doc:
                FreeCAD.closeDocument(self.doc.Name)
            shutil.rmtree(self.temp_dir, ignore_errors=True)

    def process_objects(self):
        total = len(self.doc.Objects)
        for i, obj in enumerate(self.doc.Objects):
            try:
                if hasattr(obj, 'Shape') and obj.Shape.Volume > 0:
                    self.process_3d(obj)
                elif obj.TypeId == 'Sketcher::SketchObject':
                    self.process_2d(obj)
            except Exception as e:
                self.log_message.emit(f"Error procesando {obj.Name}: {str(e)}")
            self.progress_updated.emit(int((i + 1) / total * 100))

    def process_3d(self, obj):
        placement = obj.getGlobalPlacement()
        x, y, z = placement.Base.x, placement.Base.y, placement.Base.z
        lon, lat = self.transformer.transform(x, y)

        temp_doc = FreeCAD.newDocument("TempExport", hidden=True)
        temp_obj = temp_doc.addObject('Part::Feature', 'TempObj')
        temp_obj.Shape = obj.Shape.copy()
        temp_obj.Placement = FreeCAD.Placement()

        model_path = os.path.join(self.temp_dir, f"{obj.Name}.dae")
        Import.export(temp_obj, model_path)
        FreeCAD.closeDocument(temp_doc.Name)

        color = obj.ViewObject.ShapeColor
        kml_color = simplekml.Color.rgb(
            int(color[0] * 255), int(color[1] * 255), int(color[2] * 255))

        model = self.model_folder.newmodel(name=obj.Name)
        model.altitudemode = simplekml.AltitudeMode.relativetoground
        model.longitude = lon
        model.latitude = lat
        model.altitude = z
        model.model = simplekml.Model()
        model.model.link.href = f"models/{obj.Name}.dae"
        model.style = simplekml.Style()
        model.style.polystyle.color = kml_color

    def process_2d(self, obj):
        coords = []
        placement = obj.getGlobalPlacement()
        for geom in obj.Geometry:
            for point in geom.StartPoint, geom.EndPoint:
                global_point = placement.multVec(point)
                lon, lat = self.transformer.transform(global_point.x, global_point.y)
                coords.append((lon, lat, global_point.z))

        if len(coords) < 3:
            return

        poly = self.drawing_folder.newpolygon(name=obj.Name)
        poly.outerboundaryis = coords
        poly.altitudemode = simplekml.AltitudeMode.relativetoground
        poly.style.polystyle.color = simplekml.Color.rgb(255, 0, 0, 128)

    def save_kmz(self):
        kml_path = os.path.join(self.temp_dir, "doc.kml")
        self.kml.save(kml_path)

        with zipfile.ZipFile(self.output_path, 'w') as zipf:
            zipf.write(kml_path, arcname='doc.kml')
            for root, _, files in os.walk(self.temp_dir):
                for file in files:
                    if file.endswith('.dae'):
                        zipf.write(
                            os.path.join(root, file),
                            arcname=os.path.join('models', file))


'''
def main():
    app = QtWidgets.QApplication([]) if not FreeCAD.GuiUp else QtWidgets.QApplication.instance()
    dialog = ExportKMZDialog()
    if dialog.exec_() == QtWidgets.QDialog.Accepted:
        input_path = dialog.fcstd_line.text()
        output_path = dialog.kmz_line.text()
        crs = dialog.crs_display.text()

        if not crs:
            QtWidgets.QMessageBox.critical(None, "Error", "Sistema de coordenadas no definido.")
            return

        exporter = ExportKMZ(input_path, output_path, crs)
        progress_dialog = QtWidgets.QProgressDialog("Exportando...", "Cancelar", 0, 100)
        exporter.progress_updated.connect(progress_dialog.setValue)
        exporter.log_message.connect(lambda msg: dialog.log.append(msg))
        progress_dialog.show()

        QtCore.QTimer.singleShot(100, exporter.process)
        app.exec_()


if __name__ == "__main__":
    main()
'''


class CommandExportKMZ:
    def GetResources(self):
        return {'Pixmap': str(os.path.join(DirIcons, "googleearth.svg")),
                'Accel': "E, G",
                'MenuText': "Export to KMZ",
                'ToolTip': QT_TRANSLATE_NOOP("Placement", "Export choosed layers to kmz file")}

    def Activated(self):
        taskd = ExportKMZDialog()
        taskd.setParent(FreeCADGui.getMainWindow())
        taskd.setWindowFlags(QtCore.Qt.Dialog or QtCore.Qt.Dialog)
        taskd.setWindowModality(QtCore.Qt.WindowModal)
        taskd.show()

    def IsActive(self):
        if FreeCAD.ActiveDocument:
            return True
        else:
            return False

