"""
Contains helper methods for the ANSYS solver.
"""

import os
import clr

clr.AddReference("Ans.Utilities")
import Ansys.Utilities
from Ansys.Utilities import ApplicationConfiguration

clr.AddReference("Ansys.Common.Interop.182")
from Ansys.Common.Interop.AnsCoreObjects import AnsUINTColl

from System.Diagnostics import Process
from System.Diagnostics import ProcessStartInfo
from System.Diagnostics import ProcessWindowStyle

def RunANSYS(api, args, runDir = None, exelocation = None, minimized = False, hidden = False, unlockLicense=True):
    """
    Run the ANSYS solver with the given arguments.
    """
    if exelocation==None:
        exelocation = ApplicationConfiguration.DefaultConfiguration.AwpRootEnvironmentVariableValue
        exelocation = os.path.join(exelocation, "ansys", "bin")
        exelocation = os.path.join(exelocation, ApplicationConfiguration.DefaultConfiguration.AnsysPlatform)
        exelocation = os.path.join(exelocation, "ansys" + ApplicationConfiguration.DefaultConfiguration.VersionInfo.VersionString + ".exe")

    code = -1
    try:
        startInfo = ProcessStartInfo(exelocation, args)
        if runDir: startInfo.WorkingDirectory = runDir
        if minimized: startInfo.WindowStyle = ProcessWindowStyle.Minimized
        startInfo.CreateNoWindow = hidden
        
        if unlockLicense:
            api.UnlockPrePostLicense()

        p = Process.Start(startInfo)
        p.WaitForExit()
        code = p.ExitCode

        if unlockLicense:
            api.LockPrePostLicense()
    finally:
        return code
        
def createNodeComponent(ids, groupName, mesh, stream, fromGeoIds=True):
    """
    Create a MAPDL node component based on the given ids. Ids are meshIds if
    fromGeoIds is true, geoIds else.
    """
    nodeIds = []
    if fromGeoIds:
        for id in ids:
            nodeIds += mesh.MeshRegionById(id).NodeIds
    else: nodeIds = ids
    createMeshComponent(nodeIds, groupName, "NODE", stream)
            
def createElementComponent(ids, groupName, mesh, stream, fromGeoIds=True):
    """
    Create a MAPDL element component based on the given ids. Ids are meshIds if
    fromGeoIds is true, geoIds else.
    """
    elemIds = []
    if fromGeoIds:
        for id in ids:
            elemIds += mesh.MeshRegionById(id).ElementIds
    else: elemIds = ids
    createMeshComponent(elemIds, groupName, "ELEM", stream)

def createMeshComponent(ids, groupName, groupType, stream):
    """
    Create a MAPDL mesh component based on the given ids. Ids are meshIds, and
    the group type is the MAPDL type of the component.
    """
    # Remove duplicate
    ids = sorted(set(ids))
    stream.WriteLine("CMBLOCK,{0},{1},      {2}",groupName,groupType,len(ids))
    stream.WriteLine("(8i10)")
    counter = 0;
    for id in ids:
        counter += 1;
        if counter % 8 == 0:
            stream.WriteLine('% 10d' % id)
        else:
            stream.Write('% 10d' % id)
    stream.WriteLine()
