# <<BEGIN-copyright>>
# Copyright (c) 2016, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
# Written by the LLNL Nuclear Data and Theory group
#         (email: mattoon1@llnl.gov)
# LLNL-CODE-683960.
# All rights reserved.
# 
# This file is part of the FUDGE package (For Updating Data and 
#         Generating Evaluations)
# 
# When citing FUDGE, please use the following reference:
#   C.M. Mattoon, B.R. Beck, N.R. Patel, N.C. Summers, G.W. Hedstrom, D.A. Brown, "Generalized Nuclear Data: A New Structure (with Supporting Infrastructure) for Handling Nuclear Data", Nuclear Data Sheets, Volume 113, Issue 12, December 2012, Pages 3145-3171, ISSN 0090-3752, http://dx.doi.org/10. 1016/j.nds.2012.11.008
# 
# 
#     Please also read this link - Our Notice and Modified BSD License
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the disclaimer below.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the disclaimer (as noted below) in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of LLNS/LLNL nor the names of its contributors may be used
#       to endorse or promote products derived from this software without specific
#       prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL LAWRENCE LIVERMORE NATIONAL SECURITY, LLC,
# THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# 
# 
# Additional BSD Notice
# 
# 1. This notice is required to be provided under our contract with the U.S.
# Department of Energy (DOE). This work was produced at Lawrence Livermore
# National Laboratory under Contract No. DE-AC52-07NA27344 with the DOE.
# 
# 2. Neither the United States Government nor Lawrence Livermore National Security,
# LLC nor any of their employees, makes any warranty, express or implied, or assumes
# any liability or responsibility for the accuracy, completeness, or usefulness of any
# information, apparatus, product, or process disclosed, or represents that its use
# would not infringe privately-owned rights.
# 
# 3. Also, reference herein to any specific commercial products, process, or services
# by trade name, trademark, manufacturer or otherwise does not necessarily constitute
# or imply its endorsement, recommendation, or favoring by the United States Government
# or Lawrence Livermore National Security, LLC. The views and opinions of authors expressed
# herein do not necessarily state or reflect those of the United States Government or
# Lawrence Livermore National Security, LLC, and shall not be used for advertising or
# product endorsement purposes.
# 
# <<END-copyright>>

"""
This module contains the class for the suite chemicalElements.
"""

from .. import suite as suiteModule

from ..families import nuclearLevel as nuclearLevelModule
from ..families import nucleus as nucleusModule

from . import isotope as isotopeModule
from . import chemicalElement as chemicalElementModule

class suite( suiteModule.sortedSuite ) :
    """
    This is the suite class used by a chemicalElement instance for storing 
    its list of istopes for a chemical element (e.g., list of istopes for 'O').
    """

    moniker = 'chemicalElements'

    def __init__( self ) :

        suiteModule.sortedSuite.__init__( self, [ chemicalElementModule.suite ], key = 'id', replace = True )

    def __contains__( self, key ) :

        if( suiteModule.sortedSuite.__contains__( self, key ) ) : return( True )
        for chemicalElement in self :
            if( key in chemicalElement ) : return( True )
        return( False )

    def __getitem__( self, key ) :

        def getitem( key ) :

            for item in self :
                if( getattr( item, self.__key ) == key ) : return( item )
            return( None )

        if( isinstance( key, int ) ) : return( self.__items[key] )
        if( not( isinstance( key, str ) ) ) : raise TypeError( 'key must be a string' )

        item = getitem( key )
        if( item is not None ) : return( item )

        chemicalElementID = None
        try :
            isNucleus, chemicalElementID, A, levelIDs, anti, qualifier = \
                    nucleusModule.chemicalElementAAndLevelIDsFromNuclearLevelID( key, qualifierAllowed = True )
        except :
            try :
                chemicalElementID, A, anti, qualifier = \
                        isotopeModule.chemicalElementAndAIDsFromIsotopeID( key, qualifierAllowed = True )
            except :
                pass
        if( chemicalElementID is not None ) :
            item = getitem( chemicalElementID )
            if( item is not None ) : return( item[key] )
        raise KeyError( 'key "%s" not found' % key )

    def add( self, item ) :

        if( isinstance( item, chemicalElementModule.suite ) ) :
            suiteModule.sortedSuite.add( self, item )
        elif( isinstance( item, isotopeModule.suite ) ) :
            if( item.chemicalElement not in self ) :
                suiteModule.sortedSuite.add( self, chemicalElementModule.suite( 
                        item.chemicalElement, item.Z, chemicalElementModule.nameFromZ[item.Z] ) )
            chemicalElement = self[item.chemicalElement].add( item )
        elif( isinstance( item, nuclearLevelModule.particle ) ) :
            chemicalElementID = item.chemicalElement
            if( chemicalElementID not in self ) :
                name = chemicalElementModule.nameFromSymbol[chemicalElementID]
                suiteModule.sortedSuite.add( self, chemicalElementModule.suite( chemicalElementID, item.Z, name ) )
            self[chemicalElementID].add( item )
        else :
            raise TypeError( "Particle not a nuclearLevel object." )

    def parseXMLNode( self, element, xPath, linkData ) :

        for child in element :
            chemicalElement = chemicalElementModule.suite( child.attrib['id'], int( child.attrib['Z'] ), child.attrib['name'] )
            self.add( chemicalElement.parseXMLNode( child,  xPath, linkData ) )

    @classmethod
    def parseXMLNodeAsClass( cls, element, xPath, linkData ) :

        xPath.append( element.tag )

        self = cls( )
        self.parseXMLNode( element, xPath, linkData )

        xPath.pop( )
        return( self )
