import System
import clr
import templatetools

from Ansys.ACT.Interfaces.Common import *
from Ansys.ACT.Interfaces.Geometry import *
from Ansys.ACT.Interfaces.Mesh import *

def IsInFilter(prop, values):
    if len(values) == 0: return False
    filters = templatetools.ParseFilter(prop.Attributes["selection_filter"])
    allValueAreInFilter = True
    for v in values:
        if not v in filters:
            allValueAreInFilter = False
            break
    return allValueAreInFilter

def IsSelectionValid(prop, selection):
    """
    Check if the given selection is valid.
    """
    if selection == None: return False
    if len(selection.Ids) == 0: return False

    if not prop.Attributes["selection_filter"]: return True

    nV = 0
    nE = 0
    nF = 0
    nB = 0
    for geoEntity in selection.Entities:
        if   geoEntity.Type == GeoCellTypeEnum.GeoBody  : nB += 1
        elif geoEntity.Type == GeoCellTypeEnum.GeoFace  : nF += 1
        elif geoEntity.Type == GeoCellTypeEnum.GeoEdge  : nE += 1
        elif geoEntity.Type == GeoCellTypeEnum.GeoVertex: nV += 1

    filters = []
    if nB>0 : filters.Add("body")
    if nF>0 : filters.Add("face")
    if nE>0 : filters.Add("edge")
    if nV>0 : filters.Add("vertex")
        
    return IsInFilter(prop, filters)
    
class NamedSelectionObj:

    def __init__(self, api, entity, prop):
        self.api = api
        self.entity = entity
        self.prop = prop
        
    def onactivate(self, entity, prop):
        prop.Options.Clear()
        comps = self.api.DataModel.Components
        for comp in comps:
            if self.isComponentValid(comp):
                prop.Options.Add(str(comp.Id))
                
    def value2string(self, entity, prop, val):
        if val == None: return ""
        if val == ""  : return ""
        comp =  self.api.DataModel.ComponentById(int(val))
        if comp == None: return ""
        return comp.Name
                
    def getvalue(self, entity, prop, val):
        if val == None: return None
        return  self.api.DataModel.ComponentById(int(val))

    def setvalue(self, entity, prop, value):
        if type(value) != int: return
        if not self.isComponentValidById(value): return
        return value
        
    def isvalid(self, entity, prop):
        if not prop.Visible: 
            return True
        selection = prop.Value
        isValid = self.isComponentValid(prop.Value)                    
        if isValid: prop.Attributes.SetValue("_relatedFeatureIds",[selection.Id])
        return isValid
                
    def isComponentValid(self, selection):
        return IsSelectionValid(self.prop, selection)
        
    def isComponentValidById(self, id):
        selection = self.api.DataModel.ComponentById(id)
        return self.isComponentValid(selection)
                
class GeometryObj:

    def __init__(self, api, entity, prop):
        self.api = api
        self.entity = entity
        self.prop = prop

    def onapply(self, entity, prop):
        selection = self.api.SelectionManager.CurrentSelection
        if IsSelectionValid(prop, selection):
            prop.Value = selection
            ids = []
            for entity in selection.Entities:
                body = entity
                if entity.Type != GeoCellTypeEnum.GeoBody:
                    body = entity.Bodies[0]
                ids.Add(body.GetRelatedFeatureId())
            prop.Attributes.SetValue("_relatedFeatureIds",ids)

    def value2string(self, entity, prop, val):
        if val == None : return ""
        if len(val.Ids) == 0: return ""

        txt = ""
        cell = val.Entities[0]
        if len(val.Ids) > 1:
            if cell.Type == GeoCellTypeEnum.GeoBody    : txt = "Bodies"
            elif cell.Type == GeoCellTypeEnum.GeoFace  : txt = "Faces"
            elif cell.Type == GeoCellTypeEnum.GeoEdge  : txt = "Edges"
            elif cell.Type == GeoCellTypeEnum.GeoVertex: txt = "Vertices"
        else:
            if cell.Type == GeoCellTypeEnum.GeoBody    : txt = "Body"
            elif cell.Type == GeoCellTypeEnum.GeoFace  : txt = "Face"
            elif cell.Type == GeoCellTypeEnum.GeoEdge  : txt = "Edge"
            elif cell.Type == GeoCellTypeEnum.GeoVertex: txt = "Vertex"

        return '{0} {1}'.format(len(val.Ids), txt)

    def isvalid(self, entity, prop, callFromParent=False):
        if not prop.Visible: return True
        val = prop.Value
        if val == None : return False
        if len(val.Ids) == 0: return False
        return True

    def onjournalrecording(self, actionName):
        selection = self.api.SelectionManager.CurrentSelection
        return dict(type=selection.SelectionType, ids=selection.Ids)

    def onjournalexecuting(self, actionName, objects):
        newSelection = self.api.SelectionManager.CreateSelectionInfo(objects["type"])
        newSelection.Ids = objects["ids"]
        self.api.SelectionManager.NewSelection(newSelection)
