# ***************************************************************************
# *                                                                         *
# *   Copyright (c) 2023 Yorik van Havre <yorik@uncreated.net>              *
# *                                                                         *
# *   This program is free software; you can redistribute it and/or modify  *
# *   it under the terms of the GNU General Public License (GPL)            *
# *   as published by the Free Software Foundation; either version 3 of     *
# *   the License, or (at your option) any later version.                   *
# *   for detail see the LICENCE text file.                                 *
# *                                                                         *
# *   This program is distributed in the hope that it will be useful,       *
# *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
# *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
# *   GNU General Public License for more details.                          *
# *                                                                         *
# *   You should have received a copy of the GNU Library General Public     *
# *   License along with this program; if not, write to the Free Software   *
# *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
# *   USA                                                                   *
# *                                                                         *
# ***************************************************************************

"""This module contains IFC-related FreeCAD commands"""


import FreeCAD
import FreeCADGui
from nativeifc import ifc_openshell

translate = FreeCAD.Qt.translate
QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP


def get_project():
    """Gets the current project"""

    from nativeifc import ifc_tools

    if FreeCADGui.Selection.getSelection():
        return ifc_tools.get_project(FreeCADGui.Selection.getSelection()[0])
    else:
        return ifc_tools.get_project(FreeCAD.ActiveDocument)


class IFC_Diff:
    """Shows a diff of the changes in the current IFC document"""

    def GetResources(self):
        tt = QT_TRANSLATE_NOOP(
            "IFC_Diff", "Shows the current unsaved changes in the IFC file"
        )
        return {
            "Pixmap": "IFC",
            "MenuText": QT_TRANSLATE_NOOP("IFC_Diff", "IFC Diff..."),
            "ToolTip": tt,
            "Accel": "I, D",
        }

    def Activated(self):
        from nativeifc import ifc_diff

        proj = get_project()
        if proj:
            diff = ifc_diff.get_diff(proj)
            ifc_diff.show_diff(diff)


class IFC_Expand:
    """Expands the children of the selected objects or document"""

    def GetResources(self):
        tt = QT_TRANSLATE_NOOP(
            "IFC_Expand", "Expands the children of the selected objects or document"
        )
        return {
            "Pixmap": "IFC",
            "MenuText": QT_TRANSLATE_NOOP("IFC_Expand", "IFC Expand"),
            "ToolTip": tt,
            "Accel": "I, E",
        }

    def Activated(self):
        ns = []
        for obj in FreeCADGui.Selection.getSelection():
            if hasattr(obj.ViewObject, "Proxy"):
                if hasattr(obj.ViewObject.Proxy, "hasChildren"):
                    if obj.ViewObject.Proxy.hasChildren(obj):
                        no = obj.ViewObject.Proxy.expandChildren(obj)
                        ns.extend(no)
        else:
            from nativeifc import ifc_generator
            from nativeifc import ifc_tools

            document = FreeCAD.ActiveDocument
            ifc_generator.delete_ghost(document)
            ifcfile = ifc_tools.get_ifcfile(document)
            if ifcfile:
                ns = ifc_tools.create_children(
                    document, ifcfile, recursive=True, only_structure=True
                )
        if ns:
            document.recompute()
            FreeCADGui.Selection.clearSelection()
            for o in ns:
                FreeCADGui.Selection.addSelection(o)


class IFC_ConvertDocument:
    """Converts the active document to an IFC document"""

    def GetResources(self):
        tt = QT_TRANSLATE_NOOP(
            "IFC_ConvertDocument", "Converts the active document to an IFC document"
        )
        return {
            "Pixmap": "IFC",
            "MenuText": QT_TRANSLATE_NOOP("IFC_ConvertDocument", "Convert document"),
            "ToolTip": tt,
            # "Accel": "I, C",
        }

    def Activated(self):
        doc = FreeCAD.ActiveDocument
        if (
            hasattr(doc, "Proxy")
            and hasattr(doc.Proxy, "ifcfile")
            and doc.Proxy.ifcfile
        ):
            FreeCAD.Console.PrintError(
                translate("BIM", "The active document is already an IFC document")
            )
        else:
            from nativeifc import ifc_tools

            ifc_tools.convert_document(doc)


class IFC_MakeProject:
    """Converts the current selection to an IFC project"""

    def GetResources(self):
        tt = QT_TRANSLATE_NOOP(
            "IFC_MakeProject", "Converts the current selection to an IFC project"
        )
        return {
            "Pixmap": "IFC",
            "MenuText": QT_TRANSLATE_NOOP("IFC_MakeProject", "Make IFC project"),
            "ToolTip": tt,
            "Accel": "I, P",
        }

    def IsActive(self):
        return bool(FreeCADGui.Selection.getSelection())

    def Activated(self):
        from importers import exportIFC  # lazy loading
        from nativeifc import ifc_tools
        from PySide import QtCore, QtGui

        doc = FreeCAD.ActiveDocument
        objs = FreeCADGui.Selection.getSelection()
        sf = QtGui.QFileDialog.getSaveFileName(
            None,
            "Save an IFC file",
            None,
            "Industry Foundation Classes (*.ifc)",
        )
        if sf and sf[0]:
            sf = sf[0]
            if not sf.lower().endswith(".ifc"):
                sf += ".ifc"
            exportIFC.export(objs, sf)
            ifc_tools.create_document_object(doc, sf, strategy=2)
            ifc_tools.remove_tree(objs)
            doc.recompute()


class IFC_Save:
    """Saves the current IFC document"""

    def GetResources(self):
        tt = QT_TRANSLATE_NOOP(
            "IFC_Save", "Saves the current IFC document"
        )
        return {
            "Pixmap": "IFC_document",
            "MenuText": QT_TRANSLATE_NOOP("IFC_Save", "Save IFC file"),
            "ToolTip": tt,
            "Accel": "Ctrl+S",
        }

    def IsActive(self):
        doc = FreeCAD.ActiveDocument
        if hasattr(doc, "IfcFilePath"):
            return True
        return False

    def Activated(self):
        from nativeifc import ifc_tools  # lazy loading

        doc = FreeCAD.ActiveDocument
        if getattr(doc, "IfcFilePath", None):
            ifc_tools.save(doc)
            gdoc = FreeCADGui.getDocument(doc.Name)
            try:
                gdoc.Modified = False
            except:
                pass
        else:
            FreeCADGui.runCommand("IFC_SaveAs")


class IFC_SaveAs:
    """Saves the current IFC document as another name"""

    def GetResources(self):
        tt = QT_TRANSLATE_NOOP(
            "IFC_SaveAs", "Saves the current IFC document as another file"
        )
        return {
            "Pixmap": "IFC_document",
            "MenuText": QT_TRANSLATE_NOOP("IFC_SaveAs", "Save IFC file as..."),
            "ToolTip": tt,
            "Accel": "Ctrl+Shift+S",
        }

    def IsActive(self):
        doc = FreeCAD.ActiveDocument
        if hasattr(doc, "IfcFilePath"):
            return True
        return False

    def Activated(self):
        from nativeifc import ifc_tools  # lazy loading
        from nativeifc import ifc_viewproviders

        doc = FreeCAD.ActiveDocument
        if ifc_viewproviders.get_filepath(doc):
            ifc_tools.save(doc)
            gdoc = FreeCADGui.getDocument(doc.Name)
            try:
                gdoc.Modified = False
            except:
                pass


def get_commands():
    """Returns a list of IFC commands"""

    return ["IFC_Diff", "IFC_Expand", "IFC_MakeProject", "IFC_UpdateIOS"]


# initialize commands
FreeCADGui.addCommand("IFC_Diff", IFC_Diff())
FreeCADGui.addCommand("IFC_Expand", IFC_Expand())
FreeCADGui.addCommand("IFC_ConvertDocument", IFC_ConvertDocument())
FreeCADGui.addCommand("IFC_MakeProject", IFC_MakeProject())
FreeCADGui.addCommand("IFC_Save", IFC_Save())
FreeCADGui.addCommand("IFC_SaveAs", IFC_SaveAs())
