/**
   * Get the user guid from a given id record and id entry. <br>
   * Return an empty string if the entry is not an EntryTypeMyLuteceUser nor
   * EntryTypeRemoteMyLuteceUser
   *
   * @param nIdRecord the id record
   * @param nIdEntry the id entry
   * @return the user GUID
   */
  public String getUserGuid(int nIdRecord, int nIdEntry) {
    String strUserGuid = StringUtils.EMPTY;
    Plugin plugin = PluginService.getPlugin(DirectoryPlugin.PLUGIN_NAME);
    IEntry entry = EntryHome.findByPrimaryKey(nIdEntry, plugin);

    if ((entry != null) && (entry.getEntryType() != null)) {
      if (((entry.getEntryType().getIdType()
                  == AppPropertiesService.getPropertyInt(
                      PROPERTY_ENTRY_TYPE_REMOTE_MYLUTECE_USER, 21))
              && DirectoryUserAttributesManager.getManager().isEnabled())
          || (entry.getEntryType().getIdType()
              == AppPropertiesService.getPropertyInt(PROPERTY_ENTRY_TYPE_MYLUTECE_USER, 19))) {
        RecordFieldFilter recordFieldFilter = new RecordFieldFilter();
        recordFieldFilter.setIdRecord(nIdRecord);
        recordFieldFilter.setIdEntry(nIdEntry);

        List<RecordField> listRecordFields =
            DirectoryService.getInstance().getRecordFieldByFilter(recordFieldFilter);

        if ((listRecordFields != null)
            && !listRecordFields.isEmpty()
            && (listRecordFields.get(0) != null)) {
          strUserGuid = listRecordFields.get(0).getValue();
        }
      }
    }

    return strUserGuid;
  }
  /**
   * Get the user infos from a given id record and id entry. <br>
   * The retrieval of the user infos depends on the entry type : <br>
   *
   * <ul>
   *   <li>If it is an {@link EntryTypeMyLuteceUser}, then it will use the {@link SecurityService}
   *       API
   *   <li>If it is an {@link EntryTypeRemoteMyLuteceUser}, then it will use the {@link
   *       UserAttributesService} API
   * </ul>
   *
   * @param strUserGuid the user guid
   * @param nIdEntry the id entry
   * @return a {@link ReferenceList}
   */
  public ReferenceList getUserInfos(String strUserGuid, int nIdEntry) {
    ReferenceList userInfos = null;

    if (StringUtils.isNotBlank(strUserGuid)) {
      Plugin plugin = PluginService.getPlugin(DirectoryPlugin.PLUGIN_NAME);
      IEntry entry = EntryHome.findByPrimaryKey(nIdEntry, plugin);

      if ((entry != null) && (entry.getEntryType() != null)) {
        if ((entry.getEntryType().getIdType()
                == AppPropertiesService.getPropertyInt(
                    PROPERTY_ENTRY_TYPE_REMOTE_MYLUTECE_USER, 21))
            && DirectoryUserAttributesManager.getManager().isEnabled()) {
          userInfos =
              DirectoryUtils.convertMapToReferenceList(
                  DirectoryUserAttributesManager.getManager().getAttributes(strUserGuid));
        } else if (entry.getEntryType().getIdType()
            == AppPropertiesService.getPropertyInt(PROPERTY_ENTRY_TYPE_MYLUTECE_USER, 19)) {
          LuteceUser user = SecurityService.getInstance().getUser(strUserGuid);

          if (user != null) {
            userInfos = DirectoryUtils.convertMapToReferenceList(user.getUserInfos());
          }
        }
      }
    }

    return userInfos;
  }
  /**
   * Get the records count
   *
   * @param directory the {@link Directory}
   * @param user the {@link AdminUser}
   * @return the record count
   */
  public int getRecordsCount(Directory directory, AdminUser user) {
    Plugin plugin = PluginService.getPlugin(DirectoryPlugin.PLUGIN_NAME);
    int nNbRecords = 0;
    boolean bWorkflowServiceEnable = WorkflowService.getInstance().isAvailable();
    RecordFieldFilter filter = new RecordFieldFilter();
    filter.setIdDirectory(directory.getIdDirectory());
    filter.setWorkgroupKeyList(AdminWorkgroupService.getUserWorkgroups(user, user.getLocale()));

    if ((directory.getIdWorkflow() != DirectoryUtils.CONSTANT_ID_NULL)
        && (directory.getIdWorkflow() != DirectoryUtils.CONSTANT_ID_ZERO)
        && bWorkflowServiceEnable) {
      List<Integer> listResultRecordIds =
          DirectorySearchService.getInstance()
              .getSearchResults(directory, null, null, null, null, filter, plugin);
      List<Integer> listTmpResultRecordIds =
          WorkflowService.getInstance()
              .getAuthorizedResourceList(
                  Record.WORKFLOW_RESOURCE_TYPE,
                  directory.getIdWorkflow(),
                  DirectoryUtils.CONSTANT_ID_NULL,
                  Integer.valueOf(directory.getIdDirectory()),
                  user);
      listResultRecordIds =
          DirectoryUtils.retainAllIdsKeepingFirstOrder(listResultRecordIds, listTmpResultRecordIds);
      nNbRecords = listResultRecordIds.size();
    } else {
      IRecordService recordService = SpringContextService.getBean(RecordService.BEAN_SERVICE);
      nNbRecords = recordService.getCountRecord(filter, plugin);
    }

    return nNbRecords;
  }
  /** {@inheritDoc} */
  @Override
  public void doCreateUserFields(int nIdUser, HttpServletRequest request, Locale locale) {
    Plugin myLutecePlugin = PluginService.getPlugin(MyLutecePlugin.PLUGIN_NAME);
    List<IAttribute> listAttributes =
        AttributeHome.findPluginAttributes(DatabasePlugin.PLUGIN_NAME, locale, myLutecePlugin);

    for (IAttribute attribute : listAttributes) {
      List<MyLuteceUserField> userFields = attribute.getUserFieldsData(request, nIdUser);
      doCreateUserFields(nIdUser, userFields, locale);
    }
  }
  /**
   * Get th list of filteredUsers
   *
   * @param request the HTTP request
   * @param duFilter the filter
   * @param listUsers the list of users
   * @return a list of {@link DatabaseUser}
   */
  public List<DatabaseUser> getListFilteredUsers(
      HttpServletRequest request, DatabaseUserFilter duFilter, List<DatabaseUser> listUsers) {
    Plugin plugin = PluginService.getPlugin(DatabasePlugin.PLUGIN_NAME);

    List<DatabaseUser> listFilteredUsers =
        DatabaseUserHome.findDatabaseUsersListByFilter(duFilter, plugin);
    List<DatabaseUser> listAvailableUsers = new ArrayList<DatabaseUser>();

    for (DatabaseUser filteredUser : listFilteredUsers) {
      for (DatabaseUser user : listUsers) {
        if (filteredUser.getUserId() == user.getUserId()) {
          listAvailableUsers.add(user);
        }
      }
    }

    Plugin myLutecePlugin = PluginService.getPlugin(MyLutecePlugin.PLUGIN_NAME);
    List<DatabaseUser> filteredUsers = new ArrayList<DatabaseUser>();

    MyLuteceUserFieldFilter mlFieldFilter = new MyLuteceUserFieldFilter();
    mlFieldFilter.setMyLuteceUserFieldFilter(request, request.getLocale());

    List<Integer> listFilteredUserIdsByUserFields =
        MyLuteceUserFieldHome.findUsersByFilter(mlFieldFilter, myLutecePlugin);

    if (listFilteredUserIdsByUserFields != null) {
      for (DatabaseUser filteredUser : listAvailableUsers) {
        for (Integer nFilteredUserIdByUserField : listFilteredUserIdsByUserFields) {
          if (filteredUser.getUserId() == nFilteredUserIdByUserField) {
            filteredUsers.add(filteredUser);
          }
        }
      }
    } else {
      filteredUsers = listAvailableUsers;
    }

    return filteredUsers;
  }
  /**
   * Get the max number
   *
   * @param entry the entry
   * @return the max number
   */
  public int getMaxNumber(IEntry entry) {
    int nMaxNumber = 1;

    if (entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeNumbering
        && (entry.getEntryType() != null)
        && (entry.getDirectory() != null)) {
      Plugin pluginDirectory = PluginService.getPlugin(DirectoryPlugin.PLUGIN_NAME);
      nMaxNumber =
          RecordFieldHome.findMaxNumber(
              entry.getIdEntry(), entry.getDirectory().getIdDirectory(), pluginDirectory);
    }

    return nMaxNumber;
  }
  /** {@inheritDoc} */
  @Override
  public void doCreateUserFields(
      int nIdUser, List<MyLuteceUserField> listUserFields, Locale locale) {
    Plugin myLutecePlugin = PluginService.getPlugin(MyLutecePlugin.PLUGIN_NAME);

    for (MyLuteceUserField userField : listUserFields) {
      if ((userField != null) && !userField.getValue().equals(EMPTY_STRING)) {
        // Change the value of the user field
        // Instead of having the ID of the attribute field, we put the attribute field title
        // which represents the locale
        userField.setValue(userField.getAttributeField().getTitle());
        MyLuteceUserFieldHome.create(userField, myLutecePlugin);
      }
    }
  }
  /**
   * Build the advanced parameters management
   *
   * @param user the admin user
   * @return The model for the advanced parameters
   */
  public Map<String, Object> getManageAdvancedParameters(AdminUser user) {
    Map<String, Object> model = new HashMap<String, Object>();
    Plugin plugin = PluginService.getPlugin(DatabasePlugin.PLUGIN_NAME);

    if (RBACService.isAuthorized(
        DatabaseResourceIdService.RESOURCE_TYPE,
        RBAC.WILDCARD_RESOURCES_ID,
        DatabaseResourceIdService.PERMISSION_MANAGE,
        user)) {
      // Encryption Password
      String strAlgorithms = AppPropertiesService.getProperty(PROPERTY_ENCRYPTION_ALGORITHMS_LIST);

      if (StringUtils.isNotBlank(strAlgorithms)) {
        String[] listAlgorithms = strAlgorithms.split(COMMA);

        model.put(MARK_ENCRYPTION_ALGORITHMS_LIST, listAlgorithms);
        model.put(MARK_IS_PLUGIN_JCAPTCHA_ENABLE, isPluginJcaptchaEnable());

        if (isPluginJcaptchaEnable()) {
          model.put(
              MARK_ENABLE_JCAPTCHA,
              SecurityUtils.getBooleanSecurityParameter(
                  _userParamService, plugin, MARK_ENABLE_JCAPTCHA));
        }
      }

      model.put(
          PARAMETER_ACCOUNT_CREATION_VALIDATION_EMAIL,
          SecurityUtils.getBooleanSecurityParameter(
              _userParamService, plugin, PARAMETER_ACCOUNT_CREATION_VALIDATION_EMAIL));

      model.put(
          PARAMETER_AUTO_LOGIN_AFTER_VALIDATION_EMAIL,
          SecurityUtils.getBooleanSecurityParameter(
              _userParamService, plugin, PARAMETER_AUTO_LOGIN_AFTER_VALIDATION_EMAIL));

      model.put(
          MARK_BANNED_DOMAIN_NAMES,
          SecurityUtils.getLargeSecurityParameter(
              _userParamService, plugin, MARK_BANNED_DOMAIN_NAMES));

      model = SecurityUtils.checkSecurityParameters(_userParamService, model, plugin);
    }

    return model;
  }
  /**
   * Get the filtered list of database users
   *
   * @param duFilter The filter
   * @param bIsSearch True if the user used search filters, false otherwise
   * @param listUsers the initial list to filter
   * @param request HttpServletRequest
   * @param model Map
   * @param url UrlItem
   * @return the filtered list
   */
  public List<DatabaseUser> getFilteredUsersInterface(
      DatabaseUserFilter duFilter,
      boolean bIsSearch,
      List<DatabaseUser> listUsers,
      HttpServletRequest request,
      Map<String, Object> model,
      UrlItem url) {
    Plugin myLutecePlugin = PluginService.getPlugin(MyLutecePlugin.PLUGIN_NAME);
    List<DatabaseUser> filteredUsers = getListFilteredUsers(request, duFilter, listUsers);
    MyLuteceUserFieldFilter mlFieldFilter = new MyLuteceUserFieldFilter();
    mlFieldFilter.setMyLuteceUserFieldFilter(request, request.getLocale());

    List<IAttribute> listAttributes = AttributeHome.findAll(request.getLocale(), myLutecePlugin);

    for (IAttribute attribute : listAttributes) {
      List<AttributeField> listAttributeFields =
          AttributeFieldHome.selectAttributeFieldsByIdAttribute(
              attribute.getIdAttribute(), myLutecePlugin);
      attribute.setListAttributeFields(listAttributeFields);
    }

    String strSortSearchAttribute = StringUtils.EMPTY;

    if (bIsSearch) {
      duFilter.setUrlAttributes(url);

      if (duFilter.getUrlAttributes() != StringUtils.EMPTY) {
        strSortSearchAttribute = AMPERSAND + duFilter.getUrlAttributes();
      }

      mlFieldFilter.setUrlAttributes(url);

      if (mlFieldFilter.getUrlAttributes() != StringUtils.EMPTY) {
        strSortSearchAttribute += (AMPERSAND + mlFieldFilter.getUrlAttributes());
      }
    }

    model.put(MARK_SEARCH_IS_SEARCH, bIsSearch);
    model.put(MARK_SEARCH_USER_FILTER, duFilter);
    model.put(MARK_SORT_SEARCH_ATTRIBUTE, strSortSearchAttribute);
    model.put(MARK_SEARCH_MYLUTECE_USER_FIELD_FILTER, mlFieldFilter);
    model.put(MARK_ATTRIBUTES_LIST, listAttributes);

    return filteredUsers;
  }
  /** {@inheritDoc} */
  @Override
  public boolean canBeRemoved(String strId) {
    if (strId == null) {
      return true;
    }

    List<Directory> listForms =
        DirectoryHome.getDirectoryList(
            new DirectoryFilter(), PluginService.getPlugin(DirectoryPlugin.PLUGIN_NAME));

    for (Directory form : listForms) {
      if ((form.getWorkgroup() != null) && form.getWorkgroup().equals(strId)) {
        return false;
      }
    }

    return true;
  }
  /**
   * Get the number to insert to the entry type numbering.
   *
   * @param entry the entry type numbering
   * @param strNumber the number to insert
   * @return the number
   * @throws DirectoryErrorException exception if the number already exists on an another record
   *     field
   */
  public int getNumber(IEntry entry, String strNumber) throws DirectoryErrorException {
    int nNumber = DirectoryUtils.CONSTANT_ID_NULL;

    if (entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeNumbering
        && (entry.getFields() != null)
        && (entry.getFields().size() > 0)
        && (entry.getEntryType() != null)
        && (entry.getDirectory() != null)) {
      nNumber = buildNumber(entry, strNumber);

      if (nNumber != DirectoryUtils.CONSTANT_ID_NULL) {
        Plugin pluginDirectory = PluginService.getPlugin(DirectoryPlugin.PLUGIN_NAME);

        if (RecordFieldHome.isNumberOnARecordField(
            entry.getIdEntry(), entry.getDirectory().getIdDirectory(), nNumber, pluginDirectory)) {
          throw new DirectoryErrorException(
              entry.getTitle(),
              "Directory Error - The number already exists in an " + "another record field.");
        }
      }
    }

    return nNumber;
  }
  /**
   * Get a XML string describing a given user
   *
   * @param user The user to get the XML of.
   * @param bExportRoles True to export roles of the user, false otherwise.
   * @param bExportGroups True to export groups of the user, false otherwise.
   * @param bExportAttributes True to export attributes of the user, false otherwise.
   * @param listAttributes The list of attributes to export.
   * @param locale The locale
   * @return A string of XML with the information of the user.
   */
  public String getXmlFromUser(
      DatabaseUser user,
      boolean bExportRoles,
      boolean bExportGroups,
      boolean bExportAttributes,
      List<IAttribute> listAttributes,
      Locale locale) {
    Plugin databasePlugin = PluginService.getPlugin(DatabasePlugin.PLUGIN_NAME);
    Plugin mylutecePlugin = PluginService.getPlugin(MyLutecePlugin.PLUGIN_NAME);
    StringBuffer sbXml = new StringBuffer();
    DateFormat dateFormat = new SimpleDateFormat();

    XmlUtil.beginElement(sbXml, CONSTANT_XML_USER);
    XmlUtil.addElement(sbXml, CONSTANT_XML_ACCESS_CODE, user.getLogin());
    XmlUtil.addElement(sbXml, CONSTANT_XML_LAST_NAME, user.getLastName());
    XmlUtil.addElement(sbXml, CONSTANT_XML_FIRST_NAME, user.getFirstName());
    XmlUtil.addElement(sbXml, CONSTANT_XML_EMAIL, user.getEmail());
    XmlUtil.addElement(sbXml, CONSTANT_XML_STATUS, Integer.toString(user.getStatus()));

    String strPasswordMaxValidDate = StringUtils.EMPTY;

    if (user.getPasswordMaxValidDate() != null) {
      strPasswordMaxValidDate = dateFormat.format(user.getPasswordMaxValidDate());
    }

    XmlUtil.addElement(sbXml, CONSTANT_XML_PASSWORD_MAX_VALID_DATE, strPasswordMaxValidDate);

    String strAccountMaxValidDate = StringUtils.EMPTY;

    if (user.getAccountMaxValidDate() != null) {
      strAccountMaxValidDate = dateFormat.format(user.getAccountMaxValidDate());
    }

    XmlUtil.addElement(sbXml, CONSTANT_XML_ACCOUNT_MAX_VALID_DATE, strAccountMaxValidDate);

    if (bExportRoles) {
      List<String> listRoles = DatabaseHome.findUserRolesFromLogin(user.getLogin(), databasePlugin);
      XmlUtil.beginElement(sbXml, CONSTANT_XML_ROLES);

      for (String strRole : listRoles) {
        XmlUtil.addElement(sbXml, CONSTANT_XML_ROLE, strRole);
      }

      XmlUtil.endElement(sbXml, CONSTANT_XML_ROLES);
    }

    if (bExportGroups) {
      List<String> listGroups =
          DatabaseHome.findUserGroupsFromLogin(user.getLogin(), databasePlugin);
      XmlUtil.beginElement(sbXml, CONSTANT_XML_GROUPS);

      for (String strGoup : listGroups) {
        XmlUtil.addElement(sbXml, CONSTANT_XML_GROUP, strGoup);
      }

      XmlUtil.endElement(sbXml, CONSTANT_XML_GROUPS);
    }

    if (bExportAttributes) {
      XmlUtil.beginElement(sbXml, CONSTANT_XML_ATTRIBUTES);

      for (IAttribute attribute : listAttributes) {
        List<MyLuteceUserField> listUserFields =
            MyLuteceUserFieldHome.selectUserFieldsByIdUserIdAttribute(
                user.getUserId(), attribute.getIdAttribute(), mylutecePlugin);

        for (MyLuteceUserField userField : listUserFields) {
          XmlUtil.beginElement(sbXml, CONSTANT_XML_ATTRIBUTE);
          XmlUtil.addElement(
              sbXml, CONSTANT_XML_ATTRIBUTE_ID, Integer.toString(attribute.getIdAttribute()));
          XmlUtil.addElement(
              sbXml, CONSTANT_XML_ATTRIBUTE_FIELD_ID, userField.getAttributeField().getIdField());
          XmlUtil.addElement(sbXml, CONSTANT_XML_ATTRIBUTE_VALUE, userField.getValue());
          XmlUtil.endElement(sbXml, CONSTANT_XML_ATTRIBUTE);
        }
      }

      XmlUtil.endElement(sbXml, CONSTANT_XML_ATTRIBUTES);
    }

    XmlUtil.endElement(sbXml, CONSTANT_XML_USER);

    return sbXml.toString();
  }
  /**
   * Get the list of record fields from a given Filter
   *
   * @param recordFieldFilter the filter
   * @return a map of (user attribute name, user attribute value)
   */
  public List<RecordField> getRecordFieldByFilter(RecordFieldFilter recordFieldFilter) {
    Plugin plugin = PluginService.getPlugin(DirectoryPlugin.PLUGIN_NAME);

    return RecordFieldHome.getRecordFieldList(recordFieldFilter, plugin);
  }
  /**
   * Get the list of fields from a given id entry
   *
   * @param nIdEntry the id entry
   * @return a list of fields
   */
  public List<Field> getFieldsListFromIdEntry(int nIdEntry) {
    Plugin plugin = PluginService.getPlugin(DirectoryPlugin.PLUGIN_NAME);

    return FieldHome.getFieldListByIdEntry(nIdEntry, plugin);
  }