/**
   * @param clientId
   * @param clientType
   * @param tenantDomain
   * @return
   * @throws IdentityApplicationManagementException
   */
  @Override
  public String getServiceProviderNameByClientId(
      String clientId, String clientType, String tenantDomain)
      throws IdentityApplicationManagementException {

    String name;

    ApplicationDAO appDAO = ApplicationMgtSystemConfig.getInstance().getApplicationDAO();
    name = appDAO.getServiceProviderNameByClientId(clientId, clientType, tenantDomain);

    if (name == null) {
      name =
          new FileBasedApplicationDAO()
              .getServiceProviderNameByClientId(clientId, clientType, tenantDomain);
    }

    if (name == null) {
      ServiceProvider defaultSP =
          ApplicationManagementServiceComponent.getFileBasedSPs()
              .get(IdentityApplicationConstants.DEFAULT_SP_CONFIG);
      name = defaultSP.getApplicationName();
    }

    return name;
  }
  /**
   * @param serviceProviderName
   * @param tenantDomain
   * @return
   * @throws IdentityApplicationManagementException
   */
  @Override
  public ServiceProvider getServiceProvider(String serviceProviderName, String tenantDomain)
      throws IdentityApplicationManagementException {

    startTenantFlow(tenantDomain);
    ApplicationDAO appDAO = ApplicationMgtSystemConfig.getInstance().getApplicationDAO();
    ServiceProvider serviceProvider = appDAO.getApplication(serviceProviderName, tenantDomain);

    if (serviceProvider != null) {
      loadApplicationPermissions(serviceProviderName, serviceProvider);
    }

    if (serviceProvider == null
        && ApplicationManagementServiceComponent.getFileBasedSPs()
            .containsKey(serviceProviderName)) {
      serviceProvider =
          ApplicationManagementServiceComponent.getFileBasedSPs().get(serviceProviderName);
    }
    endTenantFlow();
    return serviceProvider;
  }
  /**
   * [local-idp-claim-uri,sp-claim-uri]
   *
   * @param serviceProviderName
   * @param tenantDomain
   * @return
   * @throws IdentityApplicationManagementException
   */
  @Override
  public Map<String, String> getLocalIdPToServiceProviderClaimMapping(
      String serviceProviderName, String tenantDomain)
      throws IdentityApplicationManagementException {

    ApplicationDAO appDAO = ApplicationMgtSystemConfig.getInstance().getApplicationDAO();
    Map<String, String> claimMap =
        appDAO.getLocalIdPToServiceProviderClaimMapping(serviceProviderName, tenantDomain);

    if (claimMap == null
        || claimMap.isEmpty()
            && ApplicationManagementServiceComponent.getFileBasedSPs()
                .containsKey(serviceProviderName)) {
      return new FileBasedApplicationDAO()
          .getLocalIdPToServiceProviderClaimMapping(serviceProviderName, tenantDomain);
    }
    return claimMap;
  }
  /**
   * Returns back the requested set of claims by the provided service provider in local idp claim
   * dialect.
   *
   * @param serviceProviderName
   * @param tenantDomain
   * @return
   * @throws IdentityApplicationManagementException
   */
  @Override
  public List<String> getAllRequestedClaimsByServiceProvider(
      String serviceProviderName, String tenantDomain)
      throws IdentityApplicationManagementException {

    ApplicationDAO appDAO = ApplicationMgtSystemConfig.getInstance().getApplicationDAO();
    List<String> reqClaims =
        appDAO.getAllRequestedClaimsByServiceProvider(serviceProviderName, tenantDomain);

    if (reqClaims == null
        || reqClaims.isEmpty()
            && ApplicationManagementServiceComponent.getFileBasedSPs()
                .containsKey(serviceProviderName)) {
      return new FileBasedApplicationDAO()
          .getAllRequestedClaimsByServiceProvider(serviceProviderName, tenantDomain);
    }

    return reqClaims;
  }
  /**
   * @param clientId
   * @param clientType
   * @param tenantDomain
   * @return
   * @throws IdentityApplicationManagementException
   */
  @Override
  public ServiceProvider getServiceProviderByClientId(
      String clientId, String clientType, String tenantDomain)
      throws IdentityApplicationManagementException {

    // client id can contain the @ to identify the tenant domain.
    if (clientId != null && clientId.contains("@")) {
      clientId = clientId.split("@")[0];
    }

    String serviceProviderName;
    ServiceProvider serviceProvider = null;

    serviceProviderName = getServiceProviderNameByClientId(clientId, clientType, tenantDomain);

    try {
      startTenantFlow(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);

      IdentityServiceProviderCacheKey cacheKey =
          new IdentityServiceProviderCacheKey(tenantDomain, serviceProviderName);
      IdentityServiceProviderCacheEntry entry =
          ((IdentityServiceProviderCacheEntry)
              IdentityServiceProviderCache.getInstance().getValueFromCache(cacheKey));

      if (entry != null) {
        return entry.getServiceProvider();
      }

    } finally {
      endTenantFlow();
      startTenantFlow(tenantDomain);
    }

    if (serviceProviderName != null) {
      ApplicationDAO appDAO = ApplicationMgtSystemConfig.getInstance().getApplicationDAO();
      serviceProvider = appDAO.getApplication(serviceProviderName, tenantDomain);

      if (serviceProvider != null) {
        // if "Authentication Type" is "Default" we must get the steps from the default SP
        AuthenticationStep[] authenticationSteps =
            serviceProvider.getLocalAndOutBoundAuthenticationConfig().getAuthenticationSteps();

        loadApplicationPermissions(serviceProviderName, serviceProvider);

        if (authenticationSteps == null || authenticationSteps.length == 0) {
          ServiceProvider defaultSP =
              ApplicationManagementServiceComponent.getFileBasedSPs()
                  .get(IdentityApplicationConstants.DEFAULT_SP_CONFIG);
          authenticationSteps =
              defaultSP.getLocalAndOutBoundAuthenticationConfig().getAuthenticationSteps();
          serviceProvider
              .getLocalAndOutBoundAuthenticationConfig()
              .setAuthenticationSteps(authenticationSteps);
        }
      }
    }

    if (serviceProvider == null
        && serviceProviderName != null
        && ApplicationManagementServiceComponent.getFileBasedSPs()
            .containsKey(serviceProviderName)) {
      serviceProvider =
          ApplicationManagementServiceComponent.getFileBasedSPs().get(serviceProviderName);
    }

    endTenantFlow();

    try {
      startTenantFlow(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);

      IdentityServiceProviderCacheKey cacheKey =
          new IdentityServiceProviderCacheKey(tenantDomain, serviceProviderName);
      IdentityServiceProviderCacheEntry entry = new IdentityServiceProviderCacheEntry();
      entry.setServiceProvider(serviceProvider);
      IdentityServiceProviderCache.getInstance().addToCache(cacheKey, entry);
    } finally {
      endTenantFlow();
    }
    return serviceProvider;
  }