# NamedType specification for constructed types
import sys
from pyasn1.type import tagmap
from pyasn1 import error

class NamedType:
    isOptional = 0
    isDefaulted = 0
    def __init__(self, name, t):
        self.__name = name; self.__type = t
    def __repr__(self): return '%s(%s, %s)' % (
        self.__class__.__name__, self.__name, self.__type
        )
    def getType(self): return self.__type
    def getName(self): return self.__name
    def __getitem__(self, idx):
        if idx == 0: return self.__name
        if idx == 1: return self.__type
        raise IndexError()
    
class OptionalNamedType(NamedType):
    isOptional = 1
class DefaultedNamedType(NamedType):
    isDefaulted = 1
    
class NamedTypes:
    def __init__(self, *namedTypes):
        self.__namedTypes = namedTypes
        self.__namedTypesLen = len(self.__namedTypes)
        self.__minTagSet = None
        self.__tagToPosIdx = {}; self.__nameToPosIdx = {}
        self.__tagMap = { False: None, True: None }
        self.__ambigiousTypes = {}

    def __repr__(self):
        r = '%s(' % self.__class__.__name__
        for n in self.__namedTypes:
            r = r + '%r, ' % (n,)
        return r + ')'
    
    def __getitem__(self, idx): return self.__namedTypes[idx]

    if sys.version_info[0] <= 2:
        def __nonzero__(self): return bool(self.__namedTypesLen)
    else:
        def __bool__(self): return bool(self.__namedTypesLen)
    def __len__(self): return self.__namedTypesLen
    
    def getTypeByPosition(self, idx):
        if idx < 0 or idx >= self.__namedTypesLen:
            raise error.PyAsn1Error('Type position out of range')
        else:
            return self.__namedTypes[idx].getType()

    def getPositionByType(self, tagSet):
        if not self.__tagToPosIdx:
            idx = self.__namedTypesLen
            while idx > 0:
                idx = idx - 1
                tagMap = self.__namedTypes[idx].getType().getTagMap()
                for t in tagMap.getPosMap():
                    if t in self.__tagToPosIdx:
                        raise error.PyAsn1Error('Duplicate type %s' % (t,))
                    self.__tagToPosIdx[t] = idx
        try:
            return self.__tagToPosIdx[tagSet]
        except KeyError:
            raise error.PyAsn1Error('Type %s not found' % (tagSet,))
        
    def getNameByPosition(self, idx):
        try:
            return self.__namedTypes[idx].getName()
        except IndexError:
            raise error.PyAsn1Error('Type position out of range')
    def getPositionByName(self, name):
        if not self.__nameToPosIdx:
            idx = self.__namedTypesLen
            while idx > 0:
                idx = idx - 1
                n = self.__namedTypes[idx].getName()
                if n in self.__nameToPosIdx:
                    raise error.PyAsn1Error('Duplicate name %s' % (n,))
                self.__nameToPosIdx[n] = idx
        try:
            return self.__nameToPosIdx[name]
        except KeyError:
            raise error.PyAsn1Error('Name %s not found' % (name,))

    def __buildAmbigiousTagMap(self):
        ambigiousTypes = ()
        idx = self.__namedTypesLen
        while idx > 0:
            idx = idx - 1
            t = self.__namedTypes[idx]
            if t.isOptional or t.isDefaulted:
                ambigiousTypes = (t, ) + ambigiousTypes
            else:
                ambigiousTypes = (t, )
            self.__ambigiousTypes[idx] = NamedTypes(*ambigiousTypes)
        
    def getTagMapNearPosition(self, idx):
        if not self.__ambigiousTypes: self.__buildAmbigiousTagMap()
        try:
            return self.__ambigiousTypes[idx].getTagMap()
        except KeyError:
            raise error.PyAsn1Error('Type position out of range')

    def getPositionNearType(self, tagSet, idx):
        if not self.__ambigiousTypes: self.__buildAmbigiousTagMap()
        try:
            return idx+self.__ambigiousTypes[idx].getPositionByType(tagSet)
        except KeyError:
            raise error.PyAsn1Error('Type position out of range')

    def genMinTagSet(self):
        if self.__minTagSet is None:
            for t in self.__namedTypes:
                __type = t.getType()
                tagSet = getattr(__type,'getMinTagSet',__type.getTagSet)()
                if self.__minTagSet is None or tagSet < self.__minTagSet:
                    self.__minTagSet = tagSet
        return self.__minTagSet
    
    def getTagMap(self, uniq=False):
        if self.__tagMap[uniq] is None:
            tagMap = tagmap.TagMap()
            for nt in self.__namedTypes:
                tagMap = tagMap.clone(
                    nt.getType(), nt.getType().getTagMap(), uniq
                    )
            self.__tagMap[uniq] = tagMap
        return self.__tagMap[uniq]
