# -*- coding: utf-8 -*-
###################################################################################
#
#  CountersunkHoles.py
#  
#  Copyright 2015 Shai Seger <shaise at gmail dot com>
#  
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#  
#  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 General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.
#  
#  
###################################################################################

###################################################################################
# replace below with generated code from pyuic4
###################################################################################


from PySide import QtCore, QtGui
import sys

QTVer = int(QtCore.qVersion().split('.')[0])

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

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_DlgCountersunktHoles(object):
    def setupUi(self, DlgCountersunktHoles):
        DlgCountersunktHoles.setObjectName(_fromUtf8("DlgCountersunktHoles"))
        DlgCountersunktHoles.resize(424, 426)
        self.gridLayout_2 = QtGui.QGridLayout(DlgCountersunktHoles)
        self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
        self.groupBox = QtGui.QGroupBox(DlgCountersunktHoles)
        self.groupBox.setObjectName(_fromUtf8("groupBox"))
        self.hboxlayout = QtGui.QHBoxLayout(self.groupBox)
        #self.hboxlayout.setMargin(9)
        self.hboxlayout.setSpacing(6)
        self.hboxlayout.setObjectName(_fromUtf8("hboxlayout"))
        self.label = QtGui.QLabel(self.groupBox)
        self.label.setObjectName(_fromUtf8("label"))
        self.hboxlayout.addWidget(self.label)
        self.labelBaseObject = QtGui.QLabel(self.groupBox)
        self.labelBaseObject.setObjectName(_fromUtf8("labelBaseObject"))
        self.hboxlayout.addWidget(self.labelBaseObject)
        self.gridLayout_2.addWidget(self.groupBox, 0, 0, 1, 1)
        self.groupBox_2 = QtGui.QGroupBox(DlgCountersunktHoles)
        self.groupBox_2.setObjectName(_fromUtf8("groupBox_2"))
        self.verticalLayout = QtGui.QVBoxLayout(self.groupBox_2)
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
        self.horizontalLayout_2 = QtGui.QHBoxLayout()
        self.horizontalLayout_2.setContentsMargins(-1, 5, -1, -1)
        self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2"))
        spacerItem = QtGui.QSpacerItem(221, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
        self.horizontalLayout_2.addItem(spacerItem)
        self.selectAllButton = QtGui.QPushButton(self.groupBox_2)
        self.selectAllButton.setObjectName(_fromUtf8("selectAllButton"))
        self.horizontalLayout_2.addWidget(self.selectAllButton)
        self.selectNoneButton = QtGui.QPushButton(self.groupBox_2)
        self.selectNoneButton.setObjectName(_fromUtf8("selectNoneButton"))
        self.horizontalLayout_2.addWidget(self.selectNoneButton)
        self.verticalLayout.addLayout(self.horizontalLayout_2)
        self.treeView = QtGui.QTreeView(self.groupBox_2)
        self.treeView.setObjectName(_fromUtf8("treeView"))
        self.verticalLayout.addWidget(self.treeView)
        self.hboxlayout1 = QtGui.QHBoxLayout()
        #self.hboxlayout1.setMargin(0)
        self.hboxlayout1.setSpacing(6)
        self.hboxlayout1.setObjectName(_fromUtf8("hboxlayout1"))
        self.labelRadius = QtGui.QLabel(self.groupBox_2)
        self.labelRadius.setObjectName(_fromUtf8("labelRadius"))
        self.hboxlayout1.addWidget(self.labelRadius)
        self.comboDiameter = QtGui.QComboBox(self.groupBox_2)
        self.comboDiameter.setObjectName(_fromUtf8("comboDiameter"))
        self.comboDiameter.addItem(_fromUtf8(""))
        self.hboxlayout1.addWidget(self.comboDiameter)
        spacerItem1 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum)
        self.hboxlayout1.addItem(spacerItem1)
        self.verticalLayout.addLayout(self.hboxlayout1)
        self.horizontalLayout = QtGui.QHBoxLayout()
        self.horizontalLayout.setContentsMargins(-1, 0, -1, -1)
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
        self.label_2 = QtGui.QLabel(self.groupBox_2)
        self.label_2.setObjectName(_fromUtf8("label_2"))
        self.horizontalLayout.addWidget(self.label_2)
        self.comboScrewType = QtGui.QComboBox(self.groupBox_2)
        self.comboScrewType.setObjectName(_fromUtf8("comboScrewType"))
        self.comboScrewType.addItem(_fromUtf8(""))
        self.horizontalLayout.addWidget(self.comboScrewType)
        spacerItem2 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem2)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.gridLayout_2.addWidget(self.groupBox_2, 1, 0, 1, 1)

        self.retranslateUi(DlgCountersunktHoles)
        QtCore.QMetaObject.connectSlotsByName(DlgCountersunktHoles)

    def retranslateUi(self, DlgCountersunktHoles):
        DlgCountersunktHoles.setWindowTitle(_translate("DlgCountersunktHoles", "Countersunk screw holes", None))
        self.groupBox.setTitle(_translate("DlgCountersunktHoles", "Shape", None))
        self.label.setText(_translate("DlgCountersunktHoles", "Base shape:", None))
        self.labelBaseObject.setText(_translate("DlgCountersunktHoles", "Base", None))
        self.groupBox_2.setTitle(_translate("DlgCountersunktHoles", "Chamfer Parameters", None))
        self.selectAllButton.setText(_translate("DlgCountersunktHoles", "All", None))
        self.selectNoneButton.setText(_translate("DlgCountersunktHoles", "None", None))
        self.labelRadius.setText(_translate("DlgCountersunktHoles", "Diameter:", None))
        self.comboDiameter.setItemText(0, _translate("DlgCountersunktHoles", "No selection", None))
        self.label_2.setText(_translate("DlgCountersunktHoles", "Screw type:", None))
        self.comboScrewType.setItemText(0, _translate("DlgCountersunktHoles", "No Selection", None))


        ###################################################################################
        # End position for generated code from pyuic4
        ###################################################################################

    def fillTable(self, parent, baseObj, edgelist):
        self.comboDiameter.currentIndexChanged.connect(self.onDiameterChange)
        self.comboScrewType.currentIndexChanged.connect(self.onScrewChange)
        self.selectNoneButton.clicked.connect(self.onNoneClicked)
        self.selectAllButton.clicked.connect(self.onAllClicked)
        self.itemRefreshDisabled = False
        
        dm = FSDiameterModel(parent)
        dm.insertColumns(0,2);
        dm.setHeaderData(0, QtCore.Qt.Horizontal, "Edges to chamfer", QtCore.Qt.DisplayRole)
        dm.setHeaderData(1, QtCore.Qt.Horizontal, "Diameter", QtCore.Qt.DisplayRole)
        edges = []
        for i in range(len(baseObj.Shape.Edges)):
          edge = 'Edge' + str(i + 1)
          if FSIsValidEdge(baseObj, edge):
            edges.append(edge)
        nedges = len(edges)
        dm.insertRows(0, nedges)
        
        self.treeView.setRootIsDecorated(False)
        idelegate = FSDiameterDelegate(parent)
        idelegate.setUi(self)
        self.treeView.setItemDelegate(idelegate)
        self.treeView.setModel(dm)
        self.model = dm

        header = self.treeView.header()
        header.setResizeMode(0, QtGui.QHeaderView.Stretch)
        header.setDefaultAlignment(QtCore.Qt.AlignLeft)
        #header.setMovable(False)
        
        edgediams = {}
        type = 'Default'
        #FreeCAD.Console.PrintLog("Num Edge:" + str(len(edgelist)) + "\n")
        for edgediam in edgelist:
           edge, diam, invert, offset, type = cshSplitEdgeDiam(edgediam)
           #FreeCAD.Console.PrintLog("Add Edge:" + str(edge) + "'" + str(diam) + "\n")
           edgediams[edge] = diam
        
        self.fillScrewType(screwMaker.GetAllCountersunkTypes())
        idx = self.comboScrewType.findText(type)
        if idx >= 0:
          self.comboScrewType.setCurrentIndex(idx)
        self.fillDiameters(type)

        for i in range(nedges):
          edge = edges[i]
          dm.setData(dm.index(i,0), edge)
          if edge in edgediams:
            dm.setData(dm.index(i,0), QtCore.Qt.Checked, QtCore.Qt.CheckStateRole)
            dm.setData(dm.index(i,1), edgediams[edge])
          else:
            #dm.setData(dm.index(i,0), i, QtCore.Qt.UserRole)
            dm.setData(dm.index(i,0), QtCore.Qt.Unchecked, QtCore.Qt.CheckStateRole)
            dm.setData(dm.index(i,1), self.comboDiameter.itemText(0))

    def fillScrewType(self, screwList):
        self.comboScrewType.clear()
        self.comboScrewType.addItem('Default')
        for screw in screwList:
            self.comboScrewType.addItem(QtGui.QIcon(os.path.join(iconPath , screw + '.svg')), screw)  

    def fillDiameters(self, type):
        self.diamTable = cshGetTable(type)
        self.diamList = sorted(self.diamTable, key = FastenerBase.MToFloat)
        #self.diamList.sort(cmp = FastenerBase.MCompare)
        self.comboDiameter.clear()
        self.comboDiameter.addItems(self.diamList)        
          
    def GetData(self):
        dm = self.model
        nedges = dm.rowCount()
        listEdges = []
        for i in range (nedges):
            if dm.data(dm.index(i,0), QtCore.Qt.CheckStateRole) == QtCore.Qt.Unchecked:
                continue
            listEdges.append(dm.data(dm.index(i,0)) + ':' + dm.data(dm.index(i,1)) + ':0:0:' + self.SelectedType())
        return listEdges
        
    def AddEdges(self, obj, edges):
        dm = self.model
        nedges = dm.rowCount()
        self.treeView.selectionModel().clearSelection()
        self.itemRefreshDisabled = True
        for edge in edges:
            #FreeCAD.Console.PrintLog("Diam Table:" + str(edge) + "\n")
            for i in range (nedges):
                if dm.data(dm.index(i,0)) == edge:
                    m = FastenerBase.FSAutoDiameterM(obj.Shape.getElement(edge), self.diamTable, -1)
                    index = dm.index(i, 0);
                    dm.setData(index, QtCore.Qt.Checked, QtCore.Qt.CheckStateRole)
                    dm.setData(dm.index(i, 1), m)
                    if QTVer >= 5:
                      self.treeView.selectionModel().select(index, QtCore.QItemSelectionModel.Select)
                    else:
                      self.treeView.selectionModel().select(index, QtGui.QItemSelectionModel.Select)
                    
        self.itemRefreshDisabled = False
        dm.itemChanged.emit(None)
        
    def SelectedType(self):
        return self.comboScrewType.currentText()
        
    def GetClosest(self, diam):
        if diam in self.diamList:
            return diam
        d = FastenerBase.MToFloat(diam)
        l = len(self.diamList)
        if l == 1:
            return self.diamList[0]
        if d > FastenerBase.MToFloat(self.diamList[l - 1]):
            return self.diamList[l - 1]
        for d1 in self.diamList:
            if d < FastenerBase.MToFloat(d1):
                return d1
        
    def onDiameterChange(self, diamindex):
        if self.itemRefreshDisabled:
            return
        diam = self.comboDiameter.itemText(diamindex)
        dm = self.model
        nedges = dm.rowCount()
        self.itemRefreshDisabled = True
        for i in range (nedges):
            if dm.data(dm.index(i,0), QtCore.Qt.CheckStateRole) == QtCore.Qt.Checked:
                dm.setData(dm.index(i,1), diam)
        self.itemRefreshDisabled = False
        dm.itemChanged.emit(None)
               
    def onScrewChange(self, screwindex):
        if screwindex < 0:
            return
        self.itemRefreshDisabled = True
        type = self.comboScrewType.itemText(screwindex)
        #FreeCAD.Console.PrintLog("ScrewChange " + str(screwindex) + ":" + str(type) + "\n")
        self.fillDiameters(type)
        # update diameters if needed
        dm = self.model
        nedges = dm.rowCount()
        isChange = False
        for i in range (nedges):
            diam = dm.data(dm.index(i,1))
            #FreeCAD.Console.PrintLog("Looking for diam:" + str(i) + "," + str(diam) + "\n")
            if diam == None:
                continue
            diam1 = self.GetClosest(diam)
            #FreeCAD.Console.PrintLog(diam + "->" + diam1 + "\n")
            if diam != diam1:
                dm.setData(dm.index(i,1), diam1)
                if dm.data(dm.index(i,0), QtCore.Qt.CheckStateRole) == QtCore.Qt.Checked:
                    isChange = True
        self.itemRefreshDisabled = False
        if isChange:
            dm.itemChanged.emit(None)

    def onNoneClicked(self):
        dm = self.model
        nedges = dm.rowCount()
        self.itemRefreshDisabled = True
        for i in range (nedges):
            dm.setData(dm.index(i,0), QtCore.Qt.Unchecked, QtCore.Qt.CheckStateRole)
        self.itemRefreshDisabled = False
        dm.itemChanged.emit(None)
    
    def onAllClicked(self):
        dm = self.model
        nedges = dm.rowCount()
        self.itemRefreshDisabled = True
        for i in range (nedges):
            dm.setData(dm.index(i,0), QtCore.Qt.Checked, QtCore.Qt.CheckStateRole)
        self.itemRefreshDisabled = False
        dm.itemChanged.emit(None)
    
    

from FreeCAD import Gui
from FreeCAD import Base
import FreeCAD, FreeCADGui, Part, os, math
__dir__ = os.path.dirname(__file__)
iconPath = os.path.join( __dir__, 'Icons' )

import FastenerBase
from FastenerBase import FSBaseObject
import ScrewMaker  
screwMaker = ScrewMaker.Instance()


class FSDiameterDelegate(QtGui.QItemDelegate):
    def createEditor(self, parent, option, index):
        if index.column() < 1:
            return None

        editor = QtGui.QComboBox(parent)
        try:
          editor.addItems(self.ui.diamList)
        except:
          FreeCAD.Console.PrintLog(str(sys.exc_info()) + "\n")
        return editor;
    
    def setEditorData(self, editor, index):
        value = index.data(QtCore.Qt.EditRole)
        index = editor.findText(value)
        if index >= 0:
          editor.setCurrentIndex(index)

    def setModelData(self, editor, model, index):
        value = editor.currentText()
        model.setData(index, value, QtCore.Qt.EditRole)

    def pdateEditorGeometry(self, editor, option, index):
        editor.setGeometry(option.rect)
        
    def setUi(self, ui):
        self.ui = ui
        

class FSDiameterModel(QtGui.QStandardItemModel):
    def updateCheckStates(self):
        self.layoutChanged()

    def flags(self, index):
        #fl = QtGui.QStandardItemModel.flags(index)
        fl = super(FSDiameterModel, self).flags(index)
        if index.column() == 0:
            #FreeCAD.Console.PrintLog(str(fl) + "\n")
            fl = fl | QtCore.Qt.ItemIsUserCheckable
        return fl
    
    def setData(self, index, value, role = QtCore.Qt.EditRole):
        #ok = QStandardItemModel::setData(index, value, role);
        ok = super(FSDiameterModel, self).setData(index, value, role)
        #if role == QtCore.Qt.CheckStateRole:
        #    self.toggleCheckState(index)
        return ok
        
   
        
#    connect(model, SIGNAL(toggleCheckState(const QModelIndex&)),
#            this, SLOT(toggleCheckState(const QModelIndex&)));
#    // timer for highlighting
#    d->highlighttimer = new QTimer(this);
#    d->highlighttimer->setSingleShot(true);
#    connect(d->highlighttimer,SIGNAL(timeout()),
#            this, SLOT(onHighlightEdges()));


def FSIsValidEdge(obj, edge):
  #FreeCAD.Console.PrintLog("IsValid " + str(obj) + ":" + str(edge) + "\n")
  shape = obj.Shape.getElement(edge)
  if shape == None:
    return False
  if not(hasattr(shape,"Curve")):
    return False
  if not(hasattr(shape.Curve,"Center")):
    return False
  return True
  
        
class FSSelectionFilter:
  ''' A selection filter that let the user select only the edges that are circular '''
  def allow(self,doc,obj,sub):
    if obj == None or sub == None or len(sub) == 0:
      return True
    if sub[0:4] == 'Face':
      return True
    #FreeCAD.Console.PrintLog("testing " + str(obj) + ":" + str(sub) + str(len(sub)) + "\n")
    if FSIsValidEdge(obj, sub) == False:
      return False
    #self.lastobj = obj.Name
    #self.lastedge = sub
    return True
    
    
FSSelectionFilterGate = FSSelectionFilter()

class FSSelObserver:
  ''' monitor selection changes to update the task form '''
  def __init__(self, dialog):
    self.dialog = dialog
    self.disableObserver = False
    
  def addSelection(self,doc,obj,sub,pnt):
    if self.disableObserver:
      return
    FreeCAD.Console.PrintLog("FSO-AddSel:" +str(obj) + ":" + str(sub) + "\n")
    #if len(sub) == 0 and obj == FSSelectionFilterGate.lastobj:
    #  self.dialog.addSelection(FSSelectionFilterGate.lastedge)
    if sub[0:4] == 'Edge':
      self.dialog.addSelectionEdge(obj, sub)
    elif sub[0:4] == 'Face':
      self.dialog.addSelectionFace(obj, sub)
    return True
      
  def removeSelection(self,doc,obj,sub):                # Delete the selected object
    FreeCAD.Console.PrintLog("FSO-RemSel:" +str(obj) + ":" + str(sub) + "\n")
    
  def setSelection(self,doc):                           # Selection in ComboView
    FreeCAD.Console.PrintLog("FSO-SetSel:" + "\n")
    
  def clearSelection(self,doc):                         # If click on the screen, clear the selection
    FreeCAD.Console.PrintLog("FSO-ClrSel:" + "\n")
    

import sys

#FSFilletDialog.ui.FillData()

class FSTaskFilletDialog:
    def __init__(self, obj):
        self.object = obj
        if obj == None:
            self.baseObj = Gui.Selection.getSelection()[0]
            edgelist = []
        else:
            edgelist = obj.diameters
            self.baseObj = obj.baseObject[0]
            Gui.ActiveDocument.getObject(obj.Name).Visibility = False
            Gui.ActiveDocument.getObject(self.baseObj.Name).Visibility = True
        FSFilletDialog = QtGui.QWidget()
        FSFilletDialog.ui = Ui_DlgCountersunktHoles()
        FSFilletDialog.ui.setupUi(FSFilletDialog)
        FreeCAD.Console.PrintLog(str(self.baseObj) + "\n")
        FSFilletDialog.ui.fillTable(FSFilletDialog, self.baseObj, edgelist)
        FSFilletDialog.ui.labelBaseObject.setText(self.baseObj.Name)
        FSFilletDialog.ui.model.itemChanged.connect(self.onItemChanged)
                
        self.form = FSFilletDialog
        self.form.setWindowTitle("Chamfer holes for countersunk screws")
        Gui.Selection.addSelectionGate(FSSelectionFilterGate)
        self.selobserver = FSSelObserver(self) 
        Gui.Selection.addObserver(self.selobserver) 
        self.RefreshSelection()
        
    def accept(self):
        if (self.object == None):
          self.object = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Countersunk")
          FSCountersunkObject(self.object, self.baseObj)
          #self.object.ViewObject.Proxy = 0
          FSViewProviderCountersunk(self.object.ViewObject)
        self.object.diameters = self.form.ui.GetData()
        FreeCAD.Console.PrintLog(str(self.object.diameters) + "\n")
        FreeCAD.ActiveDocument.recompute()
        self.DialogClosing()
        return True
        
    def reject(self):
        self.DialogClosing()
        return True
        
    def DialogClosing(self):
        if self.object != None:
          Gui.ActiveDocument.getObject(self.object.Name).Visibility = True
          Gui.ActiveDocument.getObject(self.baseObj.Name).Visibility = False
        Gui.ActiveDocument.resetEdit()
        Gui.Selection.removeSelectionGate()
        Gui.Selection.removeObserver(self.selobserver) 
    
    def getStandardButtons(self):
        return int(QtGui.QDialogButtonBox.Ok) + int(QtGui.QDialogButtonBox.Cancel)
        
    def addSelectionEdge(self, objname, edge):
        if objname == self.baseObj.Name:
            self.form.ui.AddEdges(self.baseObj, [edge])
        self.RefreshSelection()

    def addSelectionFace(self, objname, name):
        obj = self.baseObj
        if objname == obj.Name:
            face = obj.Shape.getElement(name)
            if face == None:
                return
            edges = []
            for edge in face.Edges:
                if not(hasattr(edge,"Curve")):
                    continue
                if not(hasattr(edge.Curve,"Center")):
                    continue
                edges.append(FastenerBase.GetEdgeName(obj.Shape, edge))
            self.form.ui.AddEdges(obj, edges)
        self.RefreshSelection()        
        
    def RefreshSelection(self):
        FreeCAD.Console.PrintLog("Refresh: " "\n")
        self.selobserver.disableObserver = True
        Gui.Selection.clearSelection()
        edges = self.form.ui.GetData()
        FreeCAD.Console.PrintLog("Reselect: " +str(edges) + "\n")
        for edge in edges:
          Gui.Selection.addSelection(self.baseObj, edge)
        self.selobserver.disableObserver = False

    def onItemChanged(self, item):
        #FreeCAD.Console.PrintLog("itemChanged: " "\n")
        if not(self.form.ui.itemRefreshDisabled):
            self.RefreshSelection()

        
class FSViewProviderCountersunk:
  "A View provider for countersunk holes"
      
  def __init__(self, obj):
    obj.Proxy = self
    self.Object = obj.Object
      
  def attach(self, obj):
    self.Object = obj.Object
    return

  #def updateData(self, fp, prop):
  #  return

  def getDisplayModes(self,obj):
    modes=[]
    return modes

  def setDisplayMode(self,mode):
    return mode

  def onChanged(self, vp, prop):
    return

  def __getstate__(self):
    #        return {'ObjectName' : self.Object.Name}
    return None

  def __setstate__(self,state):
    if state is not None:
      import FreeCAD
      doc = FreeCAD.ActiveDocument #crap
      self.Object = doc.getObject(state['ObjectName'])
 
  def claimChildren(self):
    objs = []
    if hasattr(self.Object,"baseObject"):
      objs.append(self.Object.baseObject[0])
    return objs

  def getIcon(self):
    return os.path.join( iconPath , 'IconCSHole.svg')
    return None

  def setEdit(self,vobj,mode=0):
    #FreeCADGui.runCommand("Draft_Edit")
    Gui.Control.showDialog(FSTaskFilletDialog(self.Object))
    return True

  def unsetEdit(self,vobj,mode=0):
    #self.__vobject__.finishEditing()
    FreeCAD.Console.PrintLog("Finish edit\n")
    #self.finishEditing();
    Gui.Control.closeDialog()
    return False

#FSCSHSizes = ['M1.6', 'M2', 'M2.5', 'M3', 'M3.5', 'M4', 'M5', 'M6', 'M8', 'M10', 'M12', 'M14', 'M16', 'M20']
FSCSHTable={
    #       d     k
    'M1.6':(2.8,  1.0),
    'M2':  (3.6,  1.2),
    'M2.5':(4.5,  1.5),
    'M3':  (6.0,  1.86),
    'M3.5':(7.1,  2.35),
    'M4':  (8.0,  2.48),
    'M5':  (10.0, 3.10),
    'M6':  (12.0, 3.72),
    'M8':  (16.0, 4.96),
    'M10': (20.5, 6.20),
    'M12': (25.0, 7.44),
    'M14': (28.4, 8.40),
    'M16': (31.0, 8.80),
    'M20': (38.0, 10.16)}

def cshMakeFace(m, d, k):
  m = m / 2
  d = (d / 2) + 0.2
  h1 = m + k
  h2 = k - (d - m)
  
  fm = FastenerBase.FSFaceMaker()
  fm.AddPoint(0, h1)
  fm.AddPoint(d, h2)
  fm.AddPoint(d, -h2)
  fm.AddPoint(0, -h1)
  return fm.GetFace()

def cshGetTable(type):
  if type == 'Default':
    table = FSCSHTable
  else:
    table = screwMaker.GetCountersunkDiams(type)
  return table

  
def cshMakeCSHole(diam, type):
  table = cshGetTable(type)
  if not(diam in table):
    return None

  (key, shape) = FastenerBase.FSGetKey('CSHole', diam, 0)
  if shape != None:
    return shape
  
  m = FastenerBase.MToFloat(diam)
  d, k = table[diam]
  
  f = cshMakeFace(m, d, k)
  p = f.revolve(Base.Vector(0.0,0.0,0.0),Base.Vector(0.0,0.0,1.0),360)
  FastenerBase.FSCache[key] = p
  return p
  
def cshSplitEdgeDiam(edgeParam):
  res = edgeParam.split(':')
  if len(res) < 5:
    res.append('Default')
  return res

    
class FSCountersunkObject:
  def __init__(self, obj, attachTo):
    '''"Add StandOff (self clinching) type fastener" '''
    
    obj.addProperty("App::PropertyStringList","diameters","Parameters","Countersunk diameters").diameters = []
    #obj.addProperty("Part::PropertyFilletEdges","diameters","Parameters","Countersunk diameters").diameters = [(1,1,1), (2,1,1)]
    obj.addProperty("App::PropertyLinkSub", "baseObject", "Parameters", "Base object").baseObject = attachTo
    obj.setEditorMode("diameters", 2)
    obj.Proxy = self
 
  def execute(self, fp):
    '''"Print a short message when doing a recomputation, this method is mandatory" '''
    #fp.Shape = Part.makeBox(1,1,1 + len(fp.diameters))
    origshape = fp.baseObject[0].Shape
    shape = origshape
    for diam in fp.diameters:
      FreeCAD.Console.PrintLog("Generating hole tool for: " + diam + "\n")
      edge, m, f, o, type = cshSplitEdgeDiam(diam)
      cshole = cshMakeCSHole(m, type)
      FastenerBase.FSMoveToObject(cshole, origshape.getElement(edge), f == '1', float(o))
      shape = shape.cut(cshole)
    fp.Shape = shape


class FSFilletCommand:
  """Make holes for countersunk screws"""

  def GetResources(self):
    icon = os.path.join( iconPath , 'IconCSHole.svg')
    return {'Pixmap'  : icon , # the name of a svg file available in the resources
            'MenuText': "Make countersunk" ,
            'ToolTip' : "Chamfer holes for countersunk screws"}
 
  def Activated(self):
    Gui.Control.showDialog(FSTaskFilletDialog(None))
    return
   
  def IsActive(self):
    return len(Gui.Selection.getSelectionEx()) == 1

Gui.addCommand("FSFillet", FSFilletCommand())
FastenerBase.FSCommands.append("FSFillet", "command")

# to monitor selections: add SelObserver http://www.freecadweb.org/wiki/index.php?title=Code_snippets#Function_resident_with_the_mouse_click_action
# to filter selections: use Gui.Selection.SelectionGate