#!/usr/bin/env python

import copy
import types
import re

from dm.common.exceptions.dmException import DmException
from dm.common.mongodb.api.dmMongoDbApi import DmMongoDbApi
from dm.common.mongodb.impl.fileCollection import FileCollection
from dm.common.mongodb.api.dmMongoDbApi import DmMongoDbApi
from dm.common.objects.fileMetadata import FileMetadata
from dm.common.exceptions.invalidRequest import InvalidRequest

class FileMongoDbApi(DmMongoDbApi):

    SYSTEM_KEY_LIST = ['_id', 'experimentFilePath', 'experimentName']

    def __init__(self):
        DmMongoDbApi.__init__(self)
        self.fileCollectionDict = {}

    def getFileCollection(self, experimentName):
        fileCollection = self.fileCollectionDict.get(experimentName)
        if not fileCollection:
            fileCollection = FileCollection(self.dbClient, experimentName)
            self.fileCollectionDict[experimentName] = fileCollection
        return fileCollection

    @classmethod
    def getAndCheckExperimentName(cls, dictObject):
        experimentName = dictObject.get('experimentName')
        cls.checkExperimentName(experimentName)
        return experimentName

    @classmethod
    def checkExperimentName(cls, experimentName):
        if not experimentName:
            raise InvalidRequest('Experiment name has not been provided.')

    @DmMongoDbApi.executeDbCall
    def addExperimentFile(self, fileInfo, **kwargs):
        experimentName = self.getAndCheckExperimentName(fileInfo)
        fileInfo2 = self.getMongoDict(fileInfo)
        dbFileMetadata = self.getFileCollection(experimentName).addByUniqueKeys(fileInfo2)
        return self.toDmObject(dbFileMetadata, FileMetadata)

    @DmMongoDbApi.executeDbCall
    def getExperimentFiles(self, experimentName, queryDict={}, returnFieldDict=FileCollection.ALL_FIELDS_DICT, **kwargs):
        self.checkExperimentName(experimentName)
        queryDict2 = self.getMongoDict(queryDict)
        self.getLogger().debug('Converting query dict to regex patterns')
        ignoreCase = kwargs.get(self.REGEX_IGNORE_CASE_KEY, True)
        queryDict2 = self.convertStringsToRegex(queryDict2, ignoreCase)
        return self.listToDmObjects(self.getFileCollection(experimentName).findByQueryDict(queryDict2, returnFieldDict), FileMetadata)

    @DmMongoDbApi.executeDbCall
    def getExperimentFileById(self, experimentName, id, **kwargs):
        self.checkExperimentName(experimentName)
        dbFileMetadata = self.getFileCollection(experimentName).findById(id)
        return self.toDmObject(dbFileMetadata, FileMetadata)

    @DmMongoDbApi.executeDbCall
    def getExperimentFile(self, experimentName, experimentFilePath, **kwargs):
        self.checkExperimentName(experimentName)
        queryDict = { 'experimentFilePath' : experimentFilePath, 'experimentName' : experimentName }
        dbFileMetadata = self.getFileCollection(experimentName).findByUniqueKeys(queryDict)
        return self.toDmObject(dbFileMetadata, FileMetadata)

    @DmMongoDbApi.executeDbCall
    def updateExperimentFileById(self, fileInfo, **kwargs):
        experimentName = self.getAndCheckExperimentName(fileInfo)
        fileInfo2 = self.getMongoDict(fileInfo)
        dbFileMetadata = self.getFileCollection(experimentName).updateById(fileInfo2)
        return self.toDmObject(dbFileMetadata, FileMetadata)

    @DmMongoDbApi.executeDbCall
    def updateExperimentFile(self, fileInfo, **kwargs):
        experimentName = self.getAndCheckExperimentName(fileInfo)
        fileInfo2 = self.getMongoDict(fileInfo)
        dbFileMetadata = self.getFileCollection(experimentName).updateByUniqueKeys(fileInfo2)
        return self.toDmObject(dbFileMetadata, FileMetadata)

    @DmMongoDbApi.executeDbCall
    def updateOrAddExperimentFile(self, fileInfo, **kwargs):
        experimentName = self.getAndCheckExperimentName(fileInfo)
        fileInfo2 = self.getMongoDict(fileInfo)
        dbFileMetadata = self.getFileCollection(experimentName).updateOrAddByUniqueKeys(fileInfo2)
        return self.toDmObject(dbFileMetadata, FileMetadata)

#######################################################################
# Testing.
if __name__ == '__main__':
    from dm.common.mongodb.impl.mongoDbManager import MongoDbManager
    mgr = MongoDbManager.getInstance()
    mgr.dbName = 'dm'
    api = FileMongoDbApi()

    experimentFilePath = 'file02'
    experimentName = 'exp-01'
    fileInfo = {'experimentFilePath' : experimentFilePath, 'intKey' : 1, 'doubleKey' : 2.0, 'stringKey' : 'myString' , 'experimentName' : experimentName}
    file = api.updateOrAddExperimentFile(fileInfo)
    print '\nADDED FILE\n', file

    import time
    t = long(time.time())
    experimentFilePath = 'f-%s' % t
    experimentName = 'exp-01'
    fileInfo = {'experimentFilePath' : experimentFilePath, 'intKey' : 1, 'doubleKey' : 2.0, 'stringKey' : 'myString' , 'dictKey' : {'a' : 'A', 'b' : 'B', 'c' : 3}, 'experimentName' : experimentName}
    file = api.updateOrAddExperimentFile(fileInfo)
    print '\nADDED FILE\n', file

    files = api.getFiles()
    for file in files:
        print 'FILE: %s\n' % file.getDictRep()

    fileInfo = {'experimentFilePath' : experimentFilePath, 'experimentName' : experimentName, 'intKey' : 101}
    file = api.updateExperimentFile(fileInfo)
    print '\nUPDATED FILE\n', file

    print '\nFILES FOR EXPERIMENT exp1: \n', api.getExperimentFiles(experimentName)
    print '\nFILES FOR EXPERIMENT exp1 with experimentFilePath=file01: \n', api.getExperimentFiles(experimentName, queryDict={'experimentFilePath':'file02'})