#***************************************************************************
#*                                                                         *
#*   Copyright (c) 2016 - Victor Titov (DeepSOIC)                          *
#*                                               <vv.titov@gmail.com>      *  
#*                                                                         *
#*   This program is free software; you can redistribute it and/or modify  *
#*   it under the terms of the GNU Lesser General Public License (LGPL)    *
#*   as published by the Free Software Foundation; either version 2 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 Library 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                                                                   *
#*                                                                         *
#***************************************************************************

__title__= "Lattice ExposeLinkSub tool for FreeCAD"
__author__ = "DeepSOIC"
__doc__ = "Tool to expose LinkSub properties of objects, by spawning a SubLink object for each sublinked element, and redirecting the links"

from lattice2Common import *
import lattice2SubLink as LSL
import lattice2Executer as Executer
from lattice2Subsequencer import linkSubList_convertToOldStyle
import FreeCAD as App

def ExposeLinkSub(feature, propname):
    # read links out into reflist variable
    if feature.getTypeIdOfProperty(propname) == 'App::PropertyLinkSubList':
        reflist = linkSubList_convertToOldStyle(getattr(feature,propname))
    elif feature.getTypeIdOfProperty(propname) == 'App::PropertyLinkSub':
        (obj, subnames) = getattr(feature,propname)
        reflist = [(obj,subname) for subname in subnames]
        if len(reflist)>1:
            raise ValueError("Link of type 'App::PropertyLinkSub' points to more than one subelement. Not supported yet.")
        del (obj)
    else:
        raise ValueError("Link type not supported: "+feature.getTypeIdOfProperty(propname))
    if reflist is None:
        raise ValueError("Nothing is linked, nothing to do")
        #return
        
    # make SubLinks objects, and redirect the links in reflist
    for i in range(len(reflist)):
        (obj, subname) = reflist[i]
        if "Face" in subname: 
            newsubname = "Face1"
        elif "Edge" in subname: 
            newsubname = "Edge1"
        elif "Vertex" in subname: 
            newsubname = "Vertex1"
        else: 
            App.Console.PrintLog("Link %prop of feature %feat links either to whole object, or to something unknown. Subname is %sub. Skipped.\n"
                                 .replace("%prop",propname)
                                 .replace("%feat",feature.Name)
                                 .replace("%sub",repr(subname))  )
            continue
        sublink = LSL.CreateSubLink(obj, [subname])
        reflist[i] = (sublink,newsubname)
    del obj
    
    # write back
    if feature.getTypeIdOfProperty(propname) == 'App::PropertyLinkSubList':
        setattr(feature,propname,reflist)
    elif feature.getTypeIdOfProperty(propname) == 'App::PropertyLinkSub':
        setattr(feature,propname,reflist[0])
    
def cmdExposeLinkSubs():
    sel = FreeCADGui.Selection.getSelectionEx()
    if len(sel) != 1:
        raise SelectionError(   "Bad selection", "Select one object, first! You have selected %i objects".replace("%i",str(len(sel)))   )
    App.ActiveDocument.openTransaction("Expose LinkSub of "+sel[0].Object.Name)
    obj = sel[0].Object
    cnt = 0
    try:
        for propname in obj.PropertiesList:
            if 'App::PropertyLinkSub' in obj.getTypeIdOfProperty(propname):
                if getattr(obj,propname) is None:  continue
                try:
                    if obj.isDerivedFrom("Part::Part2DObject") and propname == "Support":
                        if False == askYesNo("Support", "ExposeLinkSub is about to expose Support link of %feat. This will cause PartDesign additive operations to start new objects instead of adding to support solid, and subtractive PartDesign operations to fail. Expose the support link?"
                                                        .replace("%feat",obj.Label)):
                            continue
                    ExposeLinkSub(obj, propname)
                    cnt += 1
                except Exception as err:
                    Executer.warning(None,"Attempting to expose sublink property {prop} of {feat} caused an error:\n{err}"
                                          .format(prop= propname, feat= obj.Name, err= str(err))   )
        if cnt == 0:
            raise ValueError("No links to expose were found.")
    except Exception:
        App.ActiveDocument.abortTransaction()
        raise
        
    
# candidate for transferring
def askYesNo(title, message):
    '''Displays messagebox with three buttons: yes, no, abort. yes -> returns True. no -> returns False. abort -> raises CancelError'''
    from PySide import QtGui
    mb = QtGui.QMessageBox()
    mb.setIcon(mb.Icon.Question)
    mb.setText(message)
    mb.setWindowTitle(title)
    btnAbort = mb.addButton(QtGui.QMessageBox.StandardButton.Abort)
    btnYes = mb.addButton(QtGui.QMessageBox.StandardButton.Yes)
    btnNo = mb.addButton(QtGui.QMessageBox.StandardButton.No)
    mb.setDefaultButton(btnYes)
    mb.exec_()
    if mb.clickedButton() is btnAbort:
        raise CancelError()
    return mb.clickedButton() is btnYes



class _CommandExposeLinkSub:
    "Command to expose ..LinkSub.. properties of other features"
    def GetResources(self):
        return {
                'MenuText': QtCore.QT_TRANSLATE_NOOP("Lattice2_ExposeLinkSub","Expose links to subelements"),
                'Accel': "",
                'ToolTip': QtCore.QT_TRANSLATE_NOOP("Lattice2_ExposeLinkSub","Expose links to subelements: create SubLink features as proxies for subelement dependencies of selected object")}
        
    def Activated(self):
        try:
            if len(FreeCADGui.Selection.getSelection())==0:
                infoMessage("ExposeLinkSub",
                    "'Expose links to subelements' command. Exposes subelement links of an object by creating SubLink features as proxies for subelement dependencies.\n\n"+
                    "Please select one object, then invoke the command.")
                return
            cmdExposeLinkSubs()
        except Exception as err:
            msgError(err)
            
    def IsActive(self):
        if App.ActiveDocument:
            return True
        else:
            return False
            
if FreeCAD.GuiUp:
    FreeCADGui.addCommand('Lattice2_ExposeLinkSub', _CommandExposeLinkSub())

exportedCommands = ['Lattice2_ExposeLinkSub']