###
# Licensed Materials - Property of IBM* and/or HCL**
# (c) Copyright IBM Corporation 2015, 2017. All Rights Reserved.
# (c) Copyright HCL Technologies Ltd. 2018. All Rights Reserved.
#
# U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by
# GSA ADP Schedule Contract with IBM Corp.
#
# * Trademark of International Business Machines
# ** Trademark of HCL Technologies Limited

from org.codehaus.jettison.json import JSONObject, JSONArray
import sys;
from WASConfLog import Log;
from utilities import Util
from LDAPServer import LDAPServer
from LDAPEntityType import LDAPEntityType

__name_att__ = None;


def _export(parentrespath, name):
  Util.pushPathElement('LDAPRepository')

  if parentrespath == "/":
    parentrespath = "";
  respath = "%(parentrespath)s/%(name)s" % { 'parentrespath':parentrespath, 'name':name }
  if not respath.startswith("/"):
    respath = "/" + respath;

  exportedObject = JSONObject();
  exportedObject.put("name", name);
  exportedObject.put("path", respath);
  exportedObject.put("teamMappings", JSONArray());
  exportedObject.put("inheritTeam", "true");
  exportedObject.put("description", "Discovered WebSphereLDAPRepository");
  exportedObject.put("roleName", "WebSphereLDAPRepository");

  roleProperties = JSONObject();

  # Get the config
  search = '[-id "' + name + '"]';
  config = Util.getIdMgrRepository(search);
  config = config[1:-1];
  entries = config.split(", ");
  for entry in entries:
    if len(entry) > 0:
      # get the attribute name
      att = entry[0:entry.find("=")];
      # get the value
      value = entry[entry.find("=")+1:];
      if att in getValidAttributes():
        Util.addToJsonIfNotNone(roleProperties, att, value);

  Log.debug("Config data for repository " + search + " equals ==> " + config + " <==");
  if (config.find("loginProperties=[") != -1):
    # get the loginProperties and place it in ; delimited format
    loginProperties = config[config.find("loginProperties=[")+17:config.find("]",config.find("loginProperties=[")+17)];
    loginProperties = loginProperties.replace(", ", ";");
    Util.addToJsonIfNotNone(roleProperties, "loginProperties", loginProperties);

  # get the Base Entries and store it as an attribute
  baseEntries = Util.listIdMgrRepositoryBaseEntries(search);
  Util.addToJsonIfNotNone(roleProperties, "baseEntries", baseEntries);

  exportedObject.put("roleProperties", roleProperties);
  result = { 'object': exportedObject, 'respath':respath }
  extraObjects = [];
  typeFolders = {};

  # Get the LDAP Servers
  host = Util.listIdMgrLDAPServers(search);
  if len(host) > 0:
    returndict = Util.createTypeFolder(respath, "LDAPServer", typeFolders);
    currespath = returndict['path'];
    if returndict.has_key('object'):
      extraObjects.append(returndict['object']);
    Util.addAllFromExport(extraObjects, LDAPServer._export(currespath, name, host));

  # Get the LDAP Entity Types
  entityTypes = Util.listIdMgrLDAPEntityTypes(search);
  entityTypeList = entityTypes.split("\n");
  for entityType in entityTypeList:
    if len(entityType) > 0:
      returndict = Util.createTypeFolder(respath, "LDAPEntityType", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        extraObjects.append(returndict['object']);
      Util.addAllFromExport(extraObjects, LDAPEntityType._export(currespath, name, entityType));

  if len(extraObjects) != 0:
    result['extraObjects'] = extraObjects;
  Util.popPathElement('LDAPRepository');
  return result;

def update(parentid, jsonobject, realm):
  Util.pushPathElement('LDAPRepository')
  if not jsonobject.has("roleProperties"):
    raise Exception("LDAPRepository resource has no role properties!");

  roleProperties = jsonobject.getJSONObject("roleProperties");

  # The command AdminTask.configureAdminWIMUserRegistry can take several parameters, but
  # we are only specifying -realName and -verifyRegistry (we will not automatically generate server identity).
  # -verifyRegistry will be set to false so the configuration will be set regardless of if the system can
  # reach the user registry or not
  configureAdminWIMUserRegistryParams = '[-realmName "' + realm + '" -verifyRegistry false]';
  Log.debug("Running command to enable editing of WIMUserRegistry: AdminTask.configureAdminWIMUserRegistry(" + configureAdminWIMUserRegistryParams + ")");
  Util.configureAdminWIMUserRegistry(configureAdminWIMUserRegistryParams);

  id = roleProperties.optString("id", None);
  # get list of LDAP Repositories
  repolist = Util.listIdMgrRepositories();
  if repolist != None and len(repolist) > 0:
    findTarget = id + "=";
    if repolist.find(findTarget) == -1:
      create(roleProperties, jsonobject, realm);
    else:
      # Update the existing LDAP Repository
      # First, need to remove loginProperties value (will add the new value later)
      updateIdMgrLDAPRepositoryParms = '[-id "' + id + '" -loginProperties [\"\"]]';
      Log.debug("Running command to update LDAP Repository: AdminTask.updateIdMgrLDAPRepository(" + updateIdMgrLDAPRepositoryParms + ")");
      Util.updateIdMgrLDAPRepository(updateIdMgrLDAPRepositoryParms);
      # Now, update the properties
      updateIdMgrLDAPRepositoryParms = '[-id "' + id + '"';
      updateIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "ldapServerType", updateIdMgrLDAPRepositoryParms);
      updateIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "securityDomainName", updateIdMgrLDAPRepositoryParms);
      updateIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "adapterClassName", updateIdMgrLDAPRepositoryParms);
      updateIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "supportSorting", updateIdMgrLDAPRepositoryParms);
      updateIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "supportPaging", updateIdMgrLDAPRepositoryParms);
      updateIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "supportTransactions", updateIdMgrLDAPRepositoryParms);
      updateIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "isExtIdUnique", updateIdMgrLDAPRepositoryParms);
      updateIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "supportAsyncMode", updateIdMgrLDAPRepositoryParms);
      updateIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "supportExternalName", updateIdMgrLDAPRepositoryParms);
      updateIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "certificateMapMode", updateIdMgrLDAPRepositoryParms);
      updateIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "certificateFilter", updateIdMgrLDAPRepositoryParms);
      updateIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "loginProperties", updateIdMgrLDAPRepositoryParms);
      updateIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "sslConfiguration", updateIdMgrLDAPRepositoryParms);
      updateIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "translateRDN", updateIdMgrLDAPRepositoryParms);
      updateIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "searchTimeLimit", updateIdMgrLDAPRepositoryParms);
      updateIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "searchCountLimit", updateIdMgrLDAPRepositoryParms);
      updateIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "searchPageSize", updateIdMgrLDAPRepositoryParms);
      updateIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "returnToPrimaryServer", updateIdMgrLDAPRepositoryParms);
      updateIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "primaryServerQueryTimeInterval", updateIdMgrLDAPRepositoryParms);
      updateIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "supportChangeLog", updateIdMgrLDAPRepositoryParms);
      updateIdMgrLDAPRepositoryParms = updateIdMgrLDAPRepositoryParms + "]";
      Log.debug("Running command to update LDAP Repository: AdminTask.updateIdMgrLDAPRepository(" + updateIdMgrLDAPRepositoryParms + ")");
      Util.updateIdMgrLDAPRepository(updateIdMgrLDAPRepositoryParms);

      if jsonobject.has('children'):
        for curjsonobject in Util.getHighestChildrenWithRole(jsonobject.getJSONArray('children')):
          currole = curjsonobject.getString('roleName');
          if currole == "WebSphereLDAPServer":
            LDAPServer.update(curjsonobject, id);

        # Get list of existing LDAPEntityTypes for the repository
        # We will use this later to determine if any LDAPEntityTypes need to be deleted
        search = '[-id "' + id + '"]';
        entityTypes = Util.listIdMgrLDAPEntityTypes(search);
        entityTypeList = "";
        if entityTypes is not None and len(entityTypes) > 0:
          entityTypeList = entityTypes.split("\n");

        handledEntityTypes = [];
        for curjsonobject in Util.getHighestChildrenWithRole(jsonobject.getJSONArray('children')):
          currole = curjsonobject.getString('roleName');
          if currole == "WebSphereLDAPEntityType":
            LDAPEntityType.update(curjsonobject, id);
            roleProperties = curjsonobject.getJSONObject("roleProperties");
            name = roleProperties.optString("name", None);
            handledEntityTypes.append(name);

        # Compare previously existing LDAPEntityTypes to LDAPEntityTypes we created/updated to
        # determine if any LDAPEntityTypes need to be deleted
        if entityTypeList != "":
          for entityType in entityTypeList:
            if len(entityType) > 0:
              if entityType not in handledEntityTypes:
                LDAPEntityType.remove(id, entityType);
  Util.popPathElement('LDAPRepository');

def create(roleProperties, jsonobject, realm):
  Util.pushPathElement('LDAPRepository')

  # Run the AdminTask.createIdMgrLDAPRepository command to create a repository
  # example: AdminTask.createIdMgrLDAPRepository('[-default true -id LDAP8 -adapterClassName com.ibm.ws.wim.adapter.ldap.LdapAdapter -ldapServerType IDS -sslConfiguration -certificateMapMode exactdn -supportChangeLog none -certificateFilter -loginProperties uid]')
  id = roleProperties.optString("id", None);
  ldapServerType = roleProperties.optString("ldapServerType", None);
  createIdMgrLDAPRepositoryParms = '[-id "' + id + '" -ldapServerType ' + ldapServerType;
  createIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "securityDomainName", createIdMgrLDAPRepositoryParms);
  createIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "adapterClassName", createIdMgrLDAPRepositoryParms);
  createIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "supportSorting", createIdMgrLDAPRepositoryParms);
  createIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "supportPaging", createIdMgrLDAPRepositoryParms);
  createIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "supportTransactions", createIdMgrLDAPRepositoryParms);
  createIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "isExtIdUnique", createIdMgrLDAPRepositoryParms);
  createIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "supportAsyncMode", createIdMgrLDAPRepositoryParms);
  createIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "supportExternalName", createIdMgrLDAPRepositoryParms);
  createIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "certificateMapMode", createIdMgrLDAPRepositoryParms);
  createIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "certificateFilter", createIdMgrLDAPRepositoryParms);
  createIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "loginProperties", createIdMgrLDAPRepositoryParms);
  createIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "sslConfiguration", createIdMgrLDAPRepositoryParms);
  createIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "translateRDN", createIdMgrLDAPRepositoryParms);
  createIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "searchTimeLimit", createIdMgrLDAPRepositoryParms);
  createIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "searchCountLimit", createIdMgrLDAPRepositoryParms);
  createIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "searchPageSize", createIdMgrLDAPRepositoryParms);
  createIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "returnToPrimaryServer", createIdMgrLDAPRepositoryParms);
  createIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "primaryServerQueryTimeInterval", createIdMgrLDAPRepositoryParms);
  createIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "default", createIdMgrLDAPRepositoryParms);
  createIdMgrLDAPRepositoryParms = Util.addParmIfNotNone(roleProperties, "supportChangeLog", createIdMgrLDAPRepositoryParms);
  createIdMgrLDAPRepositoryParms = createIdMgrLDAPRepositoryParms + "]";
  Log.debug("Running command to create LDAP Repository: AdminTask.createIdMgrLDAPRepository(" + createIdMgrLDAPRepositoryParms + ")");
  Util.createIdMgrLDAPRepository(createIdMgrLDAPRepositoryParms);

  if jsonobject.has('children'):
    for curjsonobject in Util.getHighestChildrenWithRole(jsonobject.getJSONArray('children')):
      currole = curjsonobject.getString('roleName');
      if currole == "WebSphereLDAPServer":
        LDAPServer.create(curjsonobject, id);
        # Set the base entry
        # example: AdminTask.addIdMgrRepositoryBaseEntry('[-id LDAP1 -name o=ibm.com -nameInRepository o=ibm.com]')
        baseEntries = roleProperties.optString("baseEntries", None);
        # Remove brackets, if needed
        if baseEntries.startswith("{"):
          baseEntries = baseEntries[1:-1];
        baseEntriesList = baseEntries.split(", ");
        for baseEntry in baseEntriesList:
          baseEntry = Util.interpretBaseEntries(baseEntry);
          addIdMgrRepositoryBaseEntryParms = '[-id "' + id + '" -name ' + baseEntry[0] + ' -nameInRepository '+ baseEntry[1] + ']';
          Log.debug("Running command to add LDAP repository base entry: AdminTask.addIdMgrRepositoryBaseEntry(" + addIdMgrRepositoryBaseEntryParms + ")");
          Util.addIdMgrRepositoryBaseEntry(addIdMgrRepositoryBaseEntryParms);
          addIdMgrRealmBaseEntryParms = '[-name "' + realm + '" -baseEntry ' + baseEntry[0] + ']';
          Log.debug("Running command to add LDAP realm base entry: AdminTask.addIdMgrRealmBaseEntry(" + addIdMgrRealmBaseEntryParms + ")");
          Util.addIdMgrRealmBaseEntry(addIdMgrRealmBaseEntryParms);

    for curjsonobject in Util.getHighestChildrenWithRole(jsonobject.getJSONArray('children')):
      currole = curjsonobject.getString('roleName');
      if currole == "WebSphereLDAPEntityType":
        LDAPEntityType.update(curjsonobject, id);
  Util.popPathElement('LDAPRepository');

def remove(realm, repo):
  # Remove each base entry
  listIdMgrRepositoryBaseEntriesParams = '[-id "' + repo + '"]';
  baseEntries = Util.listIdMgrRepositoryBaseEntries(listIdMgrRepositoryBaseEntriesParams);
  # Remove brackets, if needed
  if baseEntries.startswith("{"):
    baseEntries = baseEntries[1:-1];
  baseEntriesList = baseEntries.split(", ");
  j = 1;
  for baseEntry in baseEntriesList:
    baseEntry = Util.interpretBaseEntries(baseEntry);
    # Remove the realm base entry
    deleteIdMgrRealmBaseEntryParams = '[-name "' + realm + '" -baseEntry ' + baseEntry[0] + ']';
    Log.debug("Running command to remove LDAP realm base entry: AdminTask.deleteIdMgrRealmBaseEntry(" + deleteIdMgrRealmBaseEntryParams + ")");
    Util.deleteIdMgrRealmBaseEntry(deleteIdMgrRealmBaseEntryParams);

    # We need to remove all of the repository base entries EXCEPT for the last one
    # (there must always be one base entry remaining)
    if j < len(baseEntriesList):
      deleteIdMgrRepositoryBaseEntryParams = '[-id "' + repo + '" -name ' + baseEntry[0] + ']';
      Log.debug("Running command to remove LDAP repository base entry: AdminTask.deleteIdMgrRepositoryBaseEntry(" + deleteIdMgrRepositoryBaseEntryParams + ")");
      Util.deleteIdMgrRepositoryBaseEntry(deleteIdMgrRepositoryBaseEntryParams);
    j = j + 1;

  # Finally, delete the repository itself
  deleteIdMgrRepositoryParams = '[-id "' + repo + '"]';
  Log.debug("Running command to delete LDAP repository: AdminTask.deleteIdMgrRepository(" + deleteIdMgrRepositoryParams + ")");
  Util.deleteIdMgrRepository(deleteIdMgrRepositoryParams);

def getValidAttributes():
  validAttributes = ['id', 'ldapServerType', 'securityDomainName', 'adapterClassName', 'supportSorting', 'supportPaging', 'supportTransactions',
                    'isExtIdUnique', 'supportAsyncMode', 'supportExternalName', 'certificateMapMode', 'certificateFilter',
                    'sslConfiguration', 'translateRDN', 'searchTimeLimit', 'searchCountLimit', 'searchPageSize', 'returnToPrimaryServer',
                    'primaryServerQueryTimeInterval', 'default', 'supportChangeLog'];
  return validAttributes;
