/*
 * The Pennsylvania State University © 2016
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.directory.scim.client.rest;

import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;

import jakarta.ws.rs.ProcessingException;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.GenericType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import jakarta.ws.rs.core.Response.Status.Family;

public final class RestClientUtil {

  private RestClientUtil() {

  }

  public static void checkForSuccess(Response response) throws RestException{
    if (!isSuccessful(response)) {
      throw new RestException(response);
    }
  }
  
  public static boolean checkForFourOhFour(WebTarget target, Response response) {
    try {
      verifyNotFourOhFour(target, response);
      return false;
    } catch (RestException e) {
      return true;
    }
  }
  
  public static void verifyNotFourOhFour(WebTarget target, Response response) throws RestException {
    if (response.getStatus() == Status.NOT_FOUND.getStatusCode()) {
      throw new RestException(response);
    }
  }

  public static boolean isSuccessful(Response response) {
    boolean isSuccessful;
    Family responseFamily = response.getStatusInfo()
                                    .getFamily();
    isSuccessful = responseFamily != Family.CLIENT_ERROR && responseFamily != Family.SERVER_ERROR;

    return isSuccessful;
  }

  /**
   * Closes <code>response</code> and suppresses any known/expected exceptions
   * from closing it.
   * 
   * @param response
   */
  public static void close(Response response) {
    try {
      response.close();
    } catch (ProcessingException ignored) {
    }
  }

  /**
   * Closes <code>response</code> and passes any known/expected exceptions from
   * closing it to <code>consumer</code> (e.g. for logging).
   * 
   * @param response
   * @param consumer
   */
  public static void close(Response response, Consumer<Throwable> consumer) {
    try {
      response.close();
    } catch (ProcessingException processingException) {
      consumer.accept(processingException);
    }
  }

  /**
   * Read an entity from the response if it was found and returned.
   * 
   * @param response
   *          the {@link Response} to read from
   * @param entityType
   *          the type of entity
   * @return <code>Optional.empty()</code> if <b>Not Found</b> or empty
   *         response, otherwise <code>Optional.ofNullable(T)</code>
   * @throws RestException
   *           if <code>response</code> is an error response other than
   *           <code>404 Not Found</code>
   * @throws ProcessingException
   *           see {@link Response#readEntity(Class)}
   * @throws IllegalStateException
   *           see {@link Response#readEntity(Class)}
   * @throws RestException
   */
  public <T> Optional<T> tryReadEntity(Response response, Class<T> entityType) throws RestException, ProcessingException, IllegalStateException{
    return readEntity(response, entityType, response::readEntity, Optional::ofNullable);
  }

  /**
   * Read an entity from the response if it was found and returned.
   * 
   * @param response
   *          the {@link Response} to read from
   * @param entityType
   *          the type of entity
   * @return <code>Optional.empty()</code> if <code>Not Found</code> or empty
   *         response, otherwise <code>Optional.ofNullable(T)</code>
   * @throws RestException
   *           if <code>response</code> is an error response other than
   *           <code>404 Not Found</code>
   * @throws ProcessingException
   *           see {@link Response#readEntity(GenericType)}
   * @throws IllegalStateException
   *           see {@link Response#readEntity(GenericType)}
   * @throws RestException
   */
  public <T> Optional<T> tryReadEntity(Response response, GenericType<T> entityType) throws RestException, ProcessingException, IllegalStateException {
    return readEntity(response, entityType, response::readEntity, Optional::ofNullable);
  }

  /**
   * <p>
   * Read an entity from the response if it was found.
   * </p>
   * <p>
   * Useful for REST endpoints that <b>MUST</b> return an entity.
   * </p>
   * 
   * @param response
   *          the {@link Response} to read from
   * @param entityType
   *          the type of entity
   * @return <code>Optional.empty()</code> if <code>Not Found</code>, otherwise
   *         <code>Optional.of(T)</code>
   * @throws RestException
   *           if <code>response</code> is an error response other than
   *           <code>404 Not Found</code>
   * @throws ProcessingException
   *           see {@link Response#readEntity(Class)}
   * @throws IllegalStateException
   *           see {@link Response#readEntity(Class)}
   * @throws RestException
   */
  public static <T> Optional<T> readEntity(Response response, Class<T> entityType) throws RestException, ProcessingException, IllegalStateException{
    return readEntity(response, entityType, response::readEntity, Optional::of);
  }

  /**
   * <p>
   * Read an entity from the response if it was found.
   * </p>
   * <p>
   * Useful for REST endpoints that <b>MUST</b> return an entity.
   * </p>
   * 
   * @param response
   *          the {@link Response} to read from
   * @param entityType
   *          the type of entity
   * @return <code>Optional.empty()</code> if <code>Not Found</code>, otherwise
   *         <code>Optional.of(T)</code>
   * @throws RestException
   *           if <code>response</code> is an error response other than
   *           <code>404 Not Found</code>
   * @throws ProcessingException
   *           see {@link Response#readEntity(GenericType)}
   * @throws IllegalStateException
   *           see {@link Response#readEntity(GenericType)}
   * @throws RestException
   */
  public static <T> Optional<T> readEntity(Response response, GenericType<T> entityType) throws RestException, ProcessingException, IllegalStateException{
    return readEntity(response, entityType, response::readEntity, Optional::of);
  }

  private static <T, E> Optional<E> readEntity(Response response, T entityType, Function<T, E> readEntity, Function<E, Optional<E>> optionalOf) throws RestException, ProcessingException, IllegalStateException{
    Optional<E> result;

    if (response.getStatus() == Status.NOT_FOUND.getStatusCode()) {
      result = Optional.empty();
    } else {
      checkForSuccess(response);

      E responseEntity = readEntity.apply(entityType);
      result = optionalOf.apply(responseEntity);
    }
    return result;
  }
  
  public static Optional<String> extractIdFromLocationTag(Response response) {
    String location = response.getHeaderString("Location");
    if (location == null) {
      return Optional.empty();
    }
    
    String[] uriParts = location.split("/");
    Integer nbrParts = uriParts.length;
    return Optional.of(uriParts[nbrParts - 1]);
  }
}
