#
# This file is an example of the sort of detailed wrappers that could
# be written to assist in very detailed python macros.
#
# A partial example of its use appears at the bottom of the file
#
# Note: These wrappers and the examples that use them are unfinished
#       and unsupported. They are provided only to show additional 
#       possible uses of Python code in CAFEAN.
#

#
# Retrieves the component with the given number in the given
# category and wraps the component in a type-specific wrapper
# to allow data access that more closely resembles the TRACE manual.
#
def findComponent(model, catName, number):
    comp = model.findComponentByCC(catName,number)
    if comp == None:
        return None
    elif comp.getFluidSegmentCount() == 0:
        if comp.getCategory().toString() == "Fills":
            return FillWrapper(comp)
        elif comp.getCategory().toString() == "Breaks":
            return BreakWrapper(comp)
    elif comp.getFluidSegmentCount() == 1:
        return PipeWrapper(comp)
    elif comp.getFluidSegmentCount() == 2:
        return TeeWrapper(comp)
    return None


##
# Wraps a hydraulic component with a single fluid segment
# to allow data access that more closely resembles the TRACE manual.
# 
# This class is incomplete and unsupported.
# 
# For components with 2 fluid segments see TeeWrapper
##
class PipeWrapper:
    __comp = None

    def __init__(self,component):
        self.__comp = component
    def __str__(self):
        return self.__comp.toString()

    # Retrieves the cell at 'index' in the given fluid segment.
    # Index and segment are both 1-n fortran index notation.
    def __getCell(self,segment,index):
        if index == 0:
            raise ValueError, "Cell indicies start with 1."
        if index > self.__comp.getFluidSegment(segment-1).getCellsCount():
            raise ValueError, self.__comp.toString()+" has no cell "+str(index)
        return self.__comp.getFluidSegment(segment-1).getCells(index-1)
        
    # Retrieves the edge at 'index' in the given fluid segment.
    # Index and segment are both 1-n fortran index notation.
    def __getEdge(self,segment, index ):
        if index == 0:
            raise ValueError, "Edge indicies start with 1."
        if index > self.__comp.getFluidSegment(segment-1).getEdgesCount():
            raise ValueError, self.__comp.toString()+" has no edge "+str(index)
        return self.__comp.getFluidSegment(segment-1).getEdges(index-1)
    def num(self):
        return int(self.__comp.getComponentNumber())
    def npipes(self):
        return int(self.__comp.getNpipes())
    def nodes(self):
        return int(self.__comp.getNodes())
    
    def jun1(self):
        return int(self.__comp.getJun1CC())
    def jun2(self):
        return int(self.__comp.getJun2CC())
    
    #FLUID SEGMENT DATA
    def ncells(self):
        if self.__comp.getFluidSegmentCount() < 1:
            raise ValueError, self.__comp.toString+" has no main tube."
        return int(self.__comp.getFluidSegment(0).getCellsCount())

    def iconc(self):
        if self.__comp.getFluidSegmentCount() < 1:
            raise ValueError, self.__comp.toString+" has no main tube."
        return int(self.__comp.getFluidSegment(0).getIconc())
    def ipow(self):
        if self.__comp.getFluidSegmentCount() < 1:
            raise ValueError, self.__comp.toString+" has no main tube."
        return int(self.__comp.getFluidSegment(0).getIpow())
    def ichf(self):
        return int(self.__comp.getIchf())
    def epsw(self):
        return float(self.__comp.getEpsw().getDoubleValue())
    def cost(self):
        return float(self.__comp.getCost().getDoubleValue())
    def ientrn(self):
        return int(self.__comp.getIentrn())
    # MAIN TUBE CELL DATA
    def dx(self,idx):
        return float(self.__getCell(1,idx).getDx().getDoubleValue())
    def dy(self,idx):
        return float(self.__getCell(1,idx).getLengthY().getDoubleValue())
    def dz(self,idx):
        return float(self.__getCell(1,idx).getLengthZ().getDoubleValue())
    def yangle(self,idx):
        return float(self.__getCell(1,idx).getYAngle().getDoubleValue())
    def vol(self,idx):
        return float(self.__getCell(1,idx).getVol().getDoubleValue())
    # Initial Conditions
    def alp(self,idx):
        return float(self.__getCell(1,idx).getAlp().getDoubleValue())
    def tl(self,idx):
        return float(self.__getCell(1,idx).getTl().getDoubleValue())
    def tv(self,idx):
        return float(self.__getCell(1,idx).getTv().getDoubleValue())
    def p(self,idx):
        return float(self.__getCell(1,idx).getP().getDoubleValue())
    def pa(self,idx):
        return float(self.__getCell(1,idx).getPa().getDoubleValue())

    def ilev(self,idx):
        return int(self.__getCell(1,idx).getIlev())
    def conc(self,idx):
        return float(self.__getCell(1,idx).getConc().getDoubleValue())
    def s(self,idx):
        return float(self.__getCell(1,idx).getS().getDoubleValue())
    def elev(self,idx):
        return float(self.__getCell(1,idx).getElev().getDoubleValue())

    # MAIN TUBE EDGE DATA
    def fa(self,idx):
        return float(self.__getEdge(1,idx).getFa().getDoubleValue())
    def hd(self,idx):
        return float(self.__getEdge(1,idx).getHd().getDoubleValue())
    def hd_ht(self,idx):
        return float(self.__getEdge(1,idx).getHd_ht().getDoubleValue())
    def icflg(self,idx):
        return int(self.__getEdge(1,idx).getIcflg())
    def nff(self,idx):
        return int(self.__getEdge(1,idx).getNff())
    def grav(self,idx):
        return float(self.__getEdge(1,idx).getGrav())
    def fric(self,idx):
        return float(self.__getEdge(1,idx).getFric().getDoubleValue())
    def fricr(self,idx):
        return float(self.__getEdge(1,idx).getFricr().getDoubleValue())
    def fricv(self,idx):
        return float(self.__getEdge(1,idx).getFricv().getDoubleValue())
    def fricrv(self,idx):
        return float(self.__getEdge(1,idx).getFricrv().getDoubleValue())
    def kfac(self,idx):
        return float(self.__getEdge(1,idx).getKfac().getDoubleValue())
    def kfacr(self,idx):
        return float(self.__getEdge(1,idx).getKfacr().getDoubleValue())
    def kfacv(self,idx):
        return float(self.__getEdge(1,idx).getKfac().getDoubleValue())
    def kfacrv(self,idx):
        return float(self.__getEdge(1,idx).getKfacr().getDoubleValue())
    # Initial Conditions
    def vl(self,idx):
        return float(self.__getEdge(1,idx).getVl().getDoubleValue())
    def vv(self,idx):
        return float(self.__getEdge(1,idx).getVv().getDoubleValue())
##
# Wraps a hydraulic component with two fluid segments
# to allow data access that more closely resembles the TRACE manual.
# 
# This class is incomplete and unsupported.
#
# For components with a single fluid segment see PipeWrapper.
##
class TeeWrapper(PipeWrapper):
    #FLUID SEGMENT DATA
    def ncells2(self):
        if self.__comp.getFluidSegmentCount() < 2:
            raise ValueError, self.__comp.toString+" has no side tube."
        return int(self.__comp.getFluidSegment(1).getCellsCount())
    def iconc2(self):
        if self.__comp.getFluidSegmentCount() < 2:
            raise ValueError, self.__comp.toString+" has no side tube."
        return int(self.__comp.getFluidSegment(1).getIconc())
    def ipow2(self):
        if self.__comp.getFluidSegmentCount() < 2:
            raise ValueError, self.__comp.toString+" has no side tube."
        return int(self.__comp.getFluidSegment(1).getIpow())

    def ichf(self):
        return int(self.__comp.getIchf())
    def epsw(self):
        return float(self.__comp.getEpsw())
    def cost(self):
        return float(self.__comp.getCost().getDoubleValue())
    def ientrn(self):
        return int(self.__comp.getIentrn())
            
    # SIDE TUBE CELL DATA
    def dx2(self,idx):
        return float(self.__getCell(2,idx).getDx().getDoubleValue())
    def dy2(self,idx):
        return float(self.__getCell(2,idx).getLengthY().getDoubleValue())
    def dz2(self,idx):
        return float(self.__getCell(2,idx).getLengthZ().getDoubleValue())
    def yangle2(self,idx):
        return float(self.__getCell(2,idx).getYAngle().getDoubleValue())
    def vol2(self,idx):
        return float(self.__getCell(2,idx).getVol().getDoubleValue())
    # Initial Conditions
    def alp2(self,idx):
        return float(self.__getCell(2,idx).getAlp().getDoubleValue())
    def tl2(self,idx):
        return float(self.__getCell(2,idx).getTl().getDoubleValue())
    def tv2(self,idx):
        return float(self.__getCell(2,idx).getTv().getDoubleValue())
    def p2(self,idx):
        return float(self.__getCell(2,idx).getP().getDoubleValue())
    def pa2(self,idx):
        return float(self.__getCell(2,idx).getPa().getDoubleValue())

    def ilev2(self,idx):
        return int(self.__getCell(2,idx).getIlev())
    def conc2(self,idx):
        return float(self.__getCell(2,idx).getConc().getDoubleValue())
    def s2(self,idx):
        return float(self.__getCell(2,idx).getS().getDoubleValue())
    def elev2(self,idx):
        return float(self.__getCell(2,idx).getElev().getDoubleValue())

    # SIDE TUBE EDGE DATA
    def fa2(self,idx):
        return float(self.__getEdge(2,idx).getFa().getDoubleValue())
    def hd2(self,idx):
        return float(self.__getEdge(2,idx).getHd().getDoubleValue())
    def hd_ht2(self,idx):
        return float(self.__getEdge(2,idx).getHd_ht().getDoubleValue())
    def icflg2(self,idx):
        return int(self.__getEdge(2,idx).getIcflg())
    def nff2(self,idx):
        return int(self.__getEdge(2,idx).getNff())
    def grav2(self,idx):
        return float(self.__getEdge(2,idx).getGrav())
    def fric2(self,idx):
        return float(self.__getEdge(2,idx).getFric().getDoubleValue())
    def fricr2(self,idx):
        return float(self.__getEdge(2,idx).getFricr().getDoubleValue())
    def fricv2(self,idx):
        return float(self.__getEdge(2,idx).getFricv().getDoubleValue())
    def fricrv2(self,idx):
        return float(self.__getEdge(2,idx).getFricrv().getDoubleValue())
    def kfac2(self,idx):
        return float(self.__getEdge(2,idx).getKfac().getDoubleValue())
    def kfacr2(self,idx):
        return float(self.__getEdge(2,idx).getKfacr().getDoubleValue())
    def kfacv2(self,idx):
        return float(self.__getEdge(2,idx).getKfac().getDoubleValue())
    def kfacrv2(self,idx):
        return float(self.__getEdge(2,idx).getKfacr().getDoubleValue())
    # Initial Conditions
    def vl2(self,idx):
        return float(self.__getEdge(2,idx).getVl().getDoubleValue())
    def vv2(self,idx):
        return float(self.__getEdge(2,idx).getVv().getDoubleValue())

##
# Wraps a break component to allow data access that more 
# closely resembles the TRACE manual.
# 
# This class is incomplete and unsupported.
##
class BreakWrapper:
    __comp = None

    def __init__(self,component):
        self.__comp = component
    def __str__(self):
        return self.__comp.toString()

    def ibty(self):
        return int(self.__comp.getIbty())
    def isat(self):
        return int(self.__comp.getIsat())
    def ioff(self):
        return int(self.__comp.getIoff())
    def eos(self):
        return int(self.__comp.getEos())
    def belv(self):
        return float(self.__comp.getBelv().getDoubleValue()) 
    def dxin(self):
        return float(self.__comp.getDxin().getDoubleValue()) 
    def volin(self):
        return float(self.__comp.getVolin().getDoubleValue()) 
    def alpin(self):
        return float(self.__comp.getAlpin().getDoubleValue()) 
    def tlin(self):
        return float(self.__comp.getTlin().getDoubleValue()) 
    def tvin(self):
        return float(self.__comp.getTvin().getDoubleValue()) 
    def pin(self):
        return float(self.__comp.getPin().getDoubleValue()) 
    def pain(self):
        return float(self.__comp.getPain().getDoubleValue()) 
    def concin(self):
        return float(self.__comp.getConcin().getDoubleValue()) 

    def alpoff(self):
        return float(self.__comp.getAlpoff().getDoubleValue()) 
    def tloff(self):
        return float(self.__comp.getTloff().getDoubleValue()) 
    def tvoff(self):
        return float(self.__comp.getTvoff().getDoubleValue()) 
    def poff(self):
        return float(self.__comp.getPoff().getDoubleValue()) 
    def paoff(self):
        return float(self.__comp.getPaoff().getDoubleValue()) 
    def conoff(self):
        return float(self.__comp.getConoff().getDoubleValue()) 
    def deltl(self):
        return float(self.__comp.getDeltl().getDoubleValue()) 
    def deltv(self):
        return float(self.__comp.getDeltv().getDoubleValue()) 
    def bdspray(self):
        return float(self.__comp.getBdspray().getDoubleValue()) 
    def bdcond(self):
        return float(self.__comp.getBdcond()).getDoubleValue() 
    def pscl(self):
        return float(self.__comp.getPscl()).getDoubleValue() 
    def tlscl(self):
        return float(self.__comp.getTlscl()).getDoubleValue() 
    def tvscl(self):
        return float(self.__comp.getTvscl().getDoubleValue()) 
    def pscl(self):
        return float(self.__comp.getPscl()).getDoubleValue()
    def pascl(self):
        return float(self.__comp.getPascl()).getDoubleValue() 
    def conscl(self):
        return float(self.__comp.getConscl()).getDoubleValue()

##
# Wraps a break component to allow data access that more 
# closely resembles the TRACE manual.
# 
# This class is incomplete and unsupported.
##
class FillWrapper:
    __comp = None

    def __init__(self,component):
        self.__comp = component
    def __str__(self):
        return self.__comp.toString()

    def ifty(self):
        return int(self.__comp.getIfty())
    def ioff(self):
        return int(self.__comp.getIoff())
    def eos(self):
        return int(self.__comp.getEos())
    def felv(self):
        return float(self.__comp.getFelv()).getDoubleValue() 
    def dxin(self):
        return float(self.__comp.getDxin()).getDoubleValue() 
    def volin(self):
        return float(self.__comp.getVolin().getDoubleValue()) 
    def alpin(self):
        return float(self.__comp.getAlpin()).getDoubleValue() 
    def tlin(self):
        return float(self.__comp.getTlin()).getDoubleValue() 
    def tvin(self):
        return float(self.__comp.getTvin()).getDoubleValue() 
    def pin(self):
        return float(self.__comp.getPin()).getDoubleValue() 
    def pain(self):
        return float(self.__comp.getPain()).getDoubleValue() 
    def concin(self):
        return float(self.__comp.getConcin()).getDoubleValue() 
    def flowin(self):
        return float(self.__comp.getFlowin()).getDoubleValue() 
    def vlin(self):
        return float(self.__comp.getVlin()).getDoubleValue() 
    def vvin(self):
        return float(self.__comp.getVvin()).getDoubleValue() 
    def flwoff(self):
        return float(self.__comp.getFlwoff()).getDoubleValue() 
    def vloff(self):
        return float(self.__comp.getVloff()).getDoubleValue() 
    def vvoff(self):
        return float(self.__comp.getVvoff()).getDoubleValue() 
    def alpoff(self):
        return float(self.__comp.getAlpoff()).getDoubleValue() 
    def tloff(self):
        return float(self.__comp.getTloff()).getDoubleValue() 
    def tvoff(self):
        return float(self.__comp.getTvoff()).getDoubleValue() 
    def poff(self):
        return float(self.__comp.getPoff()).getDoubleValue() 
    def paoff(self):
        return float(self.__comp.getPaoff()).getDoubleValue() 
    def conoff(self):
        return float(self.__comp.getConoff()).getDoubleValue() 
    def twtold(self):
        return float(self.__comp.getTwtold()).getDoubleValue() 
    def rfmxd(self):
        return float(self.__comp.getRfmxd()).getDoubleValue() 
    def rfmxm(self):
        return float(self.__comp.getRfmxm()).getDoubleValue() 
    def rfmxv(self):
        return float(self.__comp.getRfmxv()).getDoubleValue() 
    def vmscl(self):
        return float(self.__comp.getVmscl()).getDoubleValue() 
    def vvscl(self):
        return float(self.__comp.getVvscl()).getDoubleValue() 
    def tlscl(self):
        return float(self.__comp.getTlscl()).getDoubleValue() 
    def tvscl(self):
        return float(self.__comp.getTvscl()).getDoubleValue() 
    def pscl(self):
        return float(self.__comp.getPscl()).getDoubleValue()
    def pascl(self):
        return float(self.__comp.getPascl()).getDoubleValue() 
    def conscl(self):
        return float(self.__comp.getConscl()).getDoubleValue()



##
# The following is a brief example of the usage of the preceeding wrapper 
# classes for use in examining the data in a TRACE model.
#
##

# Find pipe number 2
comp = findComponent(getModel(),"Pipes",2)
addMessage( "Found Component: "+str(comp) )
# print out the header and first line of a PIPE input section
addMessage( "*******   type           num            id        ctitle")
addMessage( "pipe                       %d             %d     %s" \
            % (comp.num(), comp.num(), str(comp)) )
addMessage( "*       ncells         nodes          jun1          jun2          epsw" )
addMessage( "             %d             %d             %d             %d         %1.3f" \
            %( comp.ncells(), comp.nodes(), comp.jun1(), comp.jun2(), comp.epsw()) )
