""" DIRAC FileCatalog Security Manager mix-in class with full access checks
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

__RCSID__ = "$Id$"

import os

from DIRAC import S_OK
from DIRAC.DataManagementSystem.DB.FileCatalogComponents.SecurityManager.SecurityManagerBase import SecurityManagerBase


class FullSecurityManager(SecurityManagerBase):

  def getPathPermissions(self, paths, credDict):
    """ Get path permissions according to the policy
    """

    toGet = dict(zip(paths, [[path] for path in paths]))
    permissions = {}
    failed = {}
    res = self.db.fileManager.getPathPermissions(paths, credDict)
    if not res['OK']:
      return res
    for path, mode in res['Value']['Successful'].items():
      for resolvedPath in toGet[path]:
        permissions[resolvedPath] = mode
      toGet.pop(path)
    # Copying items because toGet is changed in the cycle
    for path, resolvedPaths in list(toGet.items()):
      if path == '/':
        for resolvedPath in resolvedPaths:
          permissions[path] = {'Read': True, 'Write': True, 'Execute': True}
      if os.path.dirname(path) not in toGet:
        toGet[os.path.dirname(path)] = []
      toGet[os.path.dirname(path)] += resolvedPaths
      toGet.pop(path)
    while toGet:
      res = self.db.dtree.getPathPermissions(list(toGet), credDict)
      if not res['OK']:
        return res
      for path, mode in res['Value']['Successful'].items():
        for resolvedPath in toGet[path]:
          permissions[resolvedPath] = mode
        toGet.pop(path)
      for path, error in res['Value']['Failed'].items():
        if error != 'No such file or directory':
          for resolvedPath in toGet[path]:
            failed[resolvedPath] = error
          toGet.pop(path)
      # Copying items because toGet is changed in the cycle
      for path, resolvedPaths in list(toGet.items()):
        if path == '/':
          for resolvedPath in resolvedPaths:
            permissions[path] = {'Read': True, 'Write': True, 'Execute': True}
        if os.path.dirname(path) not in toGet:
          toGet[os.path.dirname(path)] = []
        toGet[os.path.dirname(path)] += resolvedPaths
        toGet.pop(path)

    if self.db.globalReadAccess:
      for path in permissions:
        permissions[path]['Read'] = True

    return S_OK({'Successful': permissions, 'Failed': failed})
