
import CollectionOfPersistentObjects, CollectionOfValues, CollectionOfLiterals
import BagBase, ListBase, SetBase
import DictionaryValueKeyMixin
import DictionaryValueValueMixin
import DictionaryBase
import DictionaryLiteralValueMixin
import DictionaryLiteralKeyMixin

import DictionaryObjectValueMixin
import DictionaryObjectKeyMixin

from Ft.Ods import Constants
from Ft.Ods.Exception import FtodsUnsupportedError
from Ft.Ods.Collections import CollectionBase

class Association:
    def __init__(self,key,value):
        self.key = key
        self.value = value


    class DuplicateName:
        def __init__(self,key):
            self.key = key

    class KeyNotFound:
        def __init__(self,key):
            self.key = key



def CollectionFromTypes(db,
                        collectionType,
                        subType,
                        subTypeRepositoryId = -1,
                        keyType = -1,
                        keyTypeRepositoryId = -1,
                        isRelationship = 0):
    if collectionType in [Constants.Types.LIST_COLLECTION,
                          Constants.Types.SET_COLLECTION,
                          Constants.Types.BAG_COLLECTION]:

        
        try:
            klass = g_collectionMapping[(isRelationship,collectionType,subType)]
        except KeyError:
            raise FtodsUnsupportedError("%s %s of %ss" % (Constants.g_odmgTypeToString[collectionType],
                                                          isRelationship and "Relationship" or "Collection",
                                                          Constants.g_odmgTypeToString[subType]))


        return klass(db,None,subType,subTypeRepositoryId,None)
    elif collectionType in [Constants.Types.DICTIONARY_COLLECTION]:
        if keyType == -1:
            raise ValueError("You must specify a keyType when creating a dictionary")
        try:
            klass = g_collectionMapping[(collectionType,keyType,subType)]
        except KeyError:
            raise FtodsUnsupportedError("Dictionary of <%s,%s>" % (Constants.g_odmgTypeToString[keyType],
                                                                   Constants.g_odmgTypeToString[subType]))


        return klass(db,None,keyType,keyTypeRepositoryId,subType,subTypeRepositoryId,None)
    else:
        raise FtodsUnsupportedError("Collection %s not supprted" % Constants.g_odmgTypeToString[collectionType])
                       

class LiteralCollectionBase:
    pass




##############################
#List Collections
##############################

class LiteralListOfValues(CollectionOfValues.CollectionOfValues,
                          LiteralCollectionBase,
                          ListBase.ListBase,
                          CollectionBase.FullPythonicCollectionBase,
                          ):

    #Override some inheritence
    allows_duplicates = ListBase.ListBase.allows_duplicates
    is_ordered = ListBase.ListBase.is_ordered
    insert_element = ListBase.ListBase.insert_element
    append = ListBase.ListBase.append


class LiteralListOfLiterals(CollectionOfLiterals.CollectionOfLiterals,
                            LiteralCollectionBase,
                            ListBase.ListBase,
                            CollectionBase.FullPythonicCollectionBase,
                            ):

    #Override some inheritence
    allows_duplicates = ListBase.ListBase.allows_duplicates
    is_ordered = ListBase.ListBase.is_ordered
    insert_element = ListBase.ListBase.insert_element
    append = ListBase.ListBase.append



class LiteralListOfObjects(CollectionOfPersistentObjects.CollectionOfPersistentObjects,
                           LiteralCollectionBase,
                           ListBase.ListBase,
                           CollectionBase.FullPythonicCollectionBase
                           ):

    #Override some inheritence
    allows_duplicates = ListBase.ListBase.allows_duplicates
    is_ordered = ListBase.ListBase.is_ordered
    insert_element = ListBase.ListBase.insert_element
    append = ListBase.ListBase.append


class RelationshipListOfObjects(CollectionOfPersistentObjects.CollectionOfPersistentObjects,
                                LiteralCollectionBase,
                                ListBase.ListBase,
                                CollectionBase.CollectionBase
                                ):

    #Override some inheritence
    allows_duplicates = ListBase.ListBase.allows_duplicates
    is_ordered = ListBase.ListBase.is_ordered
    insert_element = ListBase.ListBase.insert_element
    append = ListBase.ListBase.append




######################################################
#
#  Sets
#
######################################################


class LiteralSetOfValues(CollectionOfValues.CollectionOfValues,
                         LiteralCollectionBase,
                         SetBase.SetBase,
                         CollectionBase.FullPythonicCollectionBase,
                         ):

    #Override some inheritence
    allows_duplicates = SetBase.SetBase.allows_duplicates
    is_ordered = SetBase.SetBase.is_ordered
    insert_element = SetBase.SetBase.insert_element

class LiteralSetOfLiterals(CollectionOfLiterals.CollectionOfLiterals,
                           LiteralCollectionBase,
                           SetBase.SetBase,
                           CollectionBase.FullPythonicCollectionBase,
                           ):

    #Override some inheritence
    allows_duplicates = SetBase.SetBase.allows_duplicates
    is_ordered = SetBase.SetBase.is_ordered
    insert_element = SetBase.SetBase.insert_element

class LiteralSetOfObjects(CollectionOfPersistentObjects.CollectionOfPersistentObjects,
                          LiteralCollectionBase,
                          SetBase.SetBase,
                          CollectionBase.FullPythonicCollectionBase,
                          ):

    #Override some inheritence
    allows_duplicates = SetBase.SetBase.allows_duplicates
    is_ordered = SetBase.SetBase.is_ordered
    insert_element = SetBase.SetBase.insert_element

class RelationshipSetOfObjects(CollectionOfPersistentObjects.CollectionOfPersistentObjects,
                               LiteralCollectionBase,
                               SetBase.SetBase,
                               CollectionBase.CollectionBase,
                               ):

    #Override some inheritence
    allows_duplicates = SetBase.SetBase.allows_duplicates
    is_ordered = SetBase.SetBase.is_ordered
    insert_element = SetBase.SetBase.insert_element



######################################################
#
#  Bags
#
######################################################


class LiteralBagOfValues(CollectionOfValues.CollectionOfValues,
                         LiteralCollectionBase,
                         BagBase.BagBase,
                         CollectionBase.FullPythonicCollectionBase,
                         ):


    #Override some inheritence
    allows_duplicates = BagBase.BagBase.allows_duplicates
    is_ordered = BagBase.BagBase.is_ordered

class LiteralBagOfLiterals(CollectionOfLiterals.CollectionOfLiterals,
                           LiteralCollectionBase,
                           BagBase.BagBase,
                           CollectionBase.FullPythonicCollectionBase,
                           ):


    #Override some inheritence
    allows_duplicates = BagBase.BagBase.allows_duplicates
    is_ordered = BagBase.BagBase.is_ordered


class LiteralBagOfObjects(CollectionOfPersistentObjects.CollectionOfPersistentObjects,
                          LiteralCollectionBase,
                          BagBase.BagBase,
                          CollectionBase.FullPythonicCollectionBase,
                          ):


    #Override some inheritence
    allows_duplicates = BagBase.BagBase.allows_duplicates
    is_ordered = BagBase.BagBase.is_ordered

class RelationshipBagOfObjects(CollectionOfPersistentObjects.CollectionOfPersistentObjects,
                               LiteralCollectionBase,
                               BagBase.BagBase,
                               CollectionBase.CollectionBase,
                               ):

    #Override some inheritence
    allows_duplicates = BagBase.BagBase.allows_duplicates
    is_ordered = BagBase.BagBase.is_ordered





######################################
#
#  Dictionaries
#
######################################

class LiteralDictionaryValueValue(DictionaryValueKeyMixin.DictionaryValueKeyMixin,
                                  DictionaryValueValueMixin.DictionaryValueValueMixin,
                                  DictionaryBase.DictionaryBase):
    pass

class LiteralDictionaryValueLiteral(DictionaryValueKeyMixin.DictionaryValueKeyMixin,
                                    DictionaryLiteralValueMixin.DictionaryLiteralValueMixin,
                                    DictionaryBase.DictionaryBase):
    pass

class LiteralDictionaryValueObject(DictionaryValueKeyMixin.DictionaryValueKeyMixin,
                                   DictionaryObjectValueMixin.DictionaryObjectValueMixin,
                                   DictionaryBase.DictionaryBase):
    pass


class LiteralDictionaryLiteralValue(DictionaryLiteralKeyMixin.DictionaryLiteralKeyMixin,
                                    DictionaryValueValueMixin.DictionaryValueValueMixin,
                                    DictionaryBase.DictionaryBase):
    pass

class LiteralDictionaryLiteralLiteral(DictionaryLiteralKeyMixin.DictionaryLiteralKeyMixin,
                                      DictionaryLiteralValueMixin.DictionaryLiteralValueMixin,
                                      DictionaryBase.DictionaryBase):
    pass

class LiteralDictionaryLiteralObject(DictionaryLiteralKeyMixin.DictionaryLiteralKeyMixin,
                                     DictionaryObjectValueMixin.DictionaryObjectValueMixin,
                                     DictionaryBase.DictionaryBase):
    pass

class LiteralDictionaryObjectValue(DictionaryObjectKeyMixin.DictionaryObjectKeyMixin,
                                   DictionaryValueValueMixin.DictionaryValueValueMixin,
                                   DictionaryBase.DictionaryBase):
    pass

class LiteralDictionaryObjectLiteral(DictionaryObjectKeyMixin.DictionaryObjectKeyMixin,
                                     DictionaryLiteralValueMixin.DictionaryLiteralValueMixin,
                                     DictionaryBase.DictionaryBase):
    pass

class LiteralDictionaryObjectObject(DictionaryObjectKeyMixin.DictionaryObjectKeyMixin,
                                    DictionaryObjectValueMixin.DictionaryObjectValueMixin,
                                    DictionaryBase.DictionaryBase):
    pass




g_allDictionaries = {'ValueValue':LiteralDictionaryValueValue,
                     'ValueLiteral':LiteralDictionaryValueLiteral,
                     'ValueObject':LiteralDictionaryValueObject,
                     'LiteralValue':LiteralDictionaryLiteralValue,
                     'LiteralLiteral':LiteralDictionaryLiteralLiteral,
                     'LiteralObject':LiteralDictionaryLiteralObject,
                     'ObjectValue':LiteralDictionaryObjectValue,
                     'ObjectLiteral':LiteralDictionaryObjectLiteral,
                     'ObjectObject':LiteralDictionaryObjectObject,

                     }




g_collectionMapping = {                       
    }



#Add all of the primitive Types
for t in Constants.g_allTypes:
    if Constants.g_primitiveTypes[t]:
        g_collectionMapping[(0,Constants.Types.LIST_COLLECTION,t)] = LiteralListOfValues
        g_collectionMapping[(0,Constants.Types.SET_COLLECTION,t)] = LiteralSetOfValues
        g_collectionMapping[(0,Constants.Types.BAG_COLLECTION,t)] = LiteralBagOfValues
    elif Constants.g_literalTypes[t]:
        g_collectionMapping[(0,Constants.Types.LIST_COLLECTION,t)] = LiteralListOfLiterals
        g_collectionMapping[(0,Constants.Types.SET_COLLECTION,t)] = LiteralSetOfLiterals
        g_collectionMapping[(0,Constants.Types.BAG_COLLECTION,t)] = LiteralBagOfLiterals
    elif Constants.g_listTypes[t]:
        g_collectionMapping[(0,Constants.Types.LIST_COLLECTION,t)] = LiteralListOfObjects
        g_collectionMapping[(0,Constants.Types.SET_COLLECTION,t)] = LiteralListOfObjects
        g_collectionMapping[(0,Constants.Types.BAG_COLLECTION,t)] = LiteralListOfObjects
        g_collectionMapping[(0,Constants.Types.DICTIONARY_COLLECTION,t)] = LiteralListOfObjects
        



#Pstub object collections
g_collectionMapping[(0,Constants.Types.LIST_COLLECTION,Constants.Types.POBJECT)] = LiteralListOfObjects
g_collectionMapping[(1,Constants.Types.LIST_COLLECTION,Constants.Types.POBJECT)] = RelationshipListOfObjects
g_collectionMapping[(0,Constants.Types.SET_COLLECTION,Constants.Types.POBJECT)] = LiteralSetOfObjects
g_collectionMapping[(1,Constants.Types.SET_COLLECTION,Constants.Types.POBJECT)] = RelationshipSetOfObjects
g_collectionMapping[(0,Constants.Types.BAG_COLLECTION,Constants.Types.POBJECT)] = LiteralBagOfObjects
g_collectionMapping[(1,Constants.Types.BAG_COLLECTION,Constants.Types.POBJECT)] = RelationshipBagOfObjects

#repo object collections
g_collectionMapping[(0,Constants.Types.LIST_COLLECTION,Constants.Types.ROBJECT)] = LiteralListOfObjects
g_collectionMapping[(1,Constants.Types.LIST_COLLECTION,Constants.Types.ROBJECT)] = RelationshipListOfObjects
g_collectionMapping[(0,Constants.Types.SET_COLLECTION,Constants.Types.ROBJECT)] = LiteralSetOfObjects
g_collectionMapping[(1,Constants.Types.SET_COLLECTION,Constants.Types.ROBJECT)] = RelationshipSetOfObjects
g_collectionMapping[(0,Constants.Types.BAG_COLLECTION,Constants.Types.ROBJECT)] = LiteralBagOfObjects
g_collectionMapping[(1,Constants.Types.BAG_COLLECTION,Constants.Types.ROBJECT)] = RelationshipBagOfObjects



#Add the dictionary mappings
for kt in Constants.g_allTypes:
    if kt in [Constants.Types.VOID]:
        continue

    for st in Constants.g_allTypes:

        if st in [Constants.Types.VOID]:
            continue

        
        key=''
        sub = ''
        if Constants.g_primitiveTypes[kt]:
            key = 'Value'
        elif Constants.g_literalTypes[kt]:
            key = 'Literal'
        elif kt in [Constants.Types.POBJECT,
                    Constants.Types.ROBJECT]:
            key = 'Object'
        elif Constants.g_listTypes[kt]:
            key = 'Object'


        if Constants.g_primitiveTypes[st]:
            sub = 'Value'
        elif Constants.g_literalTypes[st]:
            sub = 'Literal'
        elif st in [Constants.Types.POBJECT,
                    Constants.Types.ROBJECT]:
            sub = 'Object'
        elif Constants.g_listTypes[st]:
            sub = 'Object'

        
        try:
            g_collectionMapping[(Constants.Types.DICTIONARY_COLLECTION,kt,st)] = g_allDictionaries[key+sub]
        except KeyError:
            pass



