# -*- coding: utf-8 -*-
"""
Compute the difference between two shapes. Additions are marked red, removals
are marked green. Both original parts will be half transparent. The volume of
the additions and removals are printed in the console.
"""

from __future__ import unicode_literals

__Name__ = 'Highlight Difference'
__Comment__ = 'Compute the difference between two shapes'
__Author__ = 'galou and other contributors'
__Version__ = '2.2.0'
__Date__ = '2021-07-01'
__License__ = 'CC0-1.0'
__Web__ = 'https://freecadweb.org/wiki/Macro_HighlightDifference'
__Wiki__ = 'https://freecadweb.org/wiki/Macro_HighlightDifference'
__Icon__ = 'HighlightDifference.svg'
__Help__ = 'Select two objects and run'
__Status__ = 'Production'
__Requires__ = 'FreeCAD V0.17+'
__Communication__ = 'https://github.com/FreeCAD/FreeCAD-macros/issues/'
__Files__ = 'HighlightDifference.svg'

from PySide import QtCore  # FreeCAD's special PySide!
from PySide.QtGui import QMessageBox  # FreeCAD's special PySide!

import FreeCAD as app
import FreeCADGui as gui


PREFERENCE_PATH = 'User parameter:BaseApp/Preferences/Mod/HighlightDifference'


def error_dialog(msg):
    """Create a simple dialog QMessageBox with an error message."""
    app.Console.PrintError(msg + '\n')
    diag = QMessageBox(QMessageBox.Icon.Critical,
                       'Error in macro highlight_difference',
                       msg)
    diag.setWindowModality(QtCore.Qt.ApplicationModal)
    diag.exec_()


def load_and_save_settings():
    param_change = 'change_transparency'
    param_transparency = 'transparency'
    p = app.ParamGet(PREFERENCE_PATH)
    change_transparency = p.GetBool(param_change, True)
    transparency = p.GetInt(param_transparency, 80)
    p.SetBool(param_change, change_transparency)
    p.SetInt(param_transparency, transparency)
    return change_transparency, transparency


def main():
    if len(gui.Selection.getSelection()) < 2:
        error_dialog('Select two objects')
        return

    object_a = gui.Selection.getSelection()[0]
    object_b = gui.Selection.getSelection()[1]
    try:
        shape_a = object_a.Shape
        shape_b = object_b.Shape
        label_a = object_a.Label
        label_b = object_b.Label
    except AttributeError:
        error_dialog('No suitable objects selected, select two objects\n')
        return

    shape_addition = shape_a.cut(shape_b)
    if shape_addition.Volume < 1e-6:
        app.Console.PrintMessage('No addition from {} to {}\n'.format(
            label_a, label_b))
    else:
        app.Console.PrintMessage(
            'Volume of the addition from {} to {}: {}\n'.format(
                label_a, label_b, shape_addition.Volume))

    shape_removal = shape_b.cut(shape_a)
    if shape_removal.Volume < 1e-6:
        app.Console.PrintMessage('No removal from {} to {}\n'.format(
            label_a, label_b))
    else:
        app.Console.PrintMessage(
            'Volume of the removal from {} to {}: {}\n'.format(
                label_a, label_b, shape_removal.Volume))

    if (shape_addition.Volume < 1e-6) and (shape_removal.Volume < 1e-6):
        app.Console.PrintMessage('{} and {} have the same shape\n'.format(
            label_a, label_b))

    added = app.ActiveDocument.addObject('Part::Feature')
    added.Label = 'Addition ({} − {})'.format(label_a, label_b)
    added.Shape = shape_addition
    added.ViewObject.ShapeColor = (1.0, 0.0, 0.0, 1.0)
    removed = app.ActiveDocument.addObject('Part::Feature')
    removed.Label = 'Removal ({} − {})'.format(label_b, label_a)
    removed.Shape = shape_removal
    removed.ViewObject.ShapeColor = (0.0, 0.5, 0.0, 1.0)

    change_transparency, transparency = load_and_save_settings()
    if change_transparency:
        try:
            object_a.ViewObject.Transparency = transparency
            object_b.ViewObject.Transparency = transparency
        except AttributeError:
            pass


if __name__ == '__main__':
    main()
