/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.server.utility;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import jakarta.enterprise.context.ApplicationScoped;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.directory.scim.server.exception.AttributeDoesNotExistException;
import org.apache.directory.scim.server.rest.ScimResourceDeserializer;
import org.apache.directory.scim.server.schema.Registry;
import org.apache.directory.scim.spec.json.ObjectMapperFactory;
import org.apache.directory.scim.spec.protocol.attribute.AttributeReference;
import org.apache.directory.scim.spec.resources.ScimExtension;
import org.apache.directory.scim.spec.resources.ScimGroup;
import org.apache.directory.scim.spec.resources.ScimResource;
import org.apache.directory.scim.spec.resources.ScimUser;
import org.apache.directory.scim.spec.schema.AttributeContainer;
import org.apache.directory.scim.spec.schema.Schema;
import org.apache.directory.scim.spec.schema.Schema.Attribute;
import org.apache.directory.scim.spec.schema.Schema.Attribute.Returned;
import org.apache.directory.scim.spec.schema.Schema.Attribute.Type;

import jakarta.inject.Inject;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Function;

@Slf4j
@ApplicationScoped
public class AttributeUtil {

  Registry registry;

  ObjectMapper objectMapper;

  @Inject
  public AttributeUtil(Registry registry) {
    this.registry = registry;

    // TODO move this to a CDI producer
    objectMapper = ObjectMapperFactory.getObjectMapper();
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    objectMapper.setSerializationInclusion(Include.NON_NULL);

    SimpleModule module = new SimpleModule();
    module.addDeserializer(ScimResource.class, new ScimResourceDeserializer(this.registry, this.objectMapper));
    objectMapper.registerModule(module);
  }

  AttributeUtil() {}

  public <T extends ScimResource> T keepAlwaysAttributesForDisplay(T resource) throws IllegalArgumentException, IllegalAccessException, AttributeDoesNotExistException, IOException {
    return setAttributesForDisplayInternal(resource, Returned.DEFAULT, Returned.REQUEST, Returned.NEVER);
  }
  
  public <T extends ScimResource> T setAttributesForDisplay(T resource) throws IllegalArgumentException, IllegalAccessException, AttributeDoesNotExistException, IOException {
    return setAttributesForDisplayInternal(resource, Returned.REQUEST, Returned.NEVER);
  }
  
  private <T extends ScimResource> T setAttributesForDisplayInternal(T resource, Returned ... removeAttributesOfTypes) throws IllegalArgumentException, IllegalAccessException, AttributeDoesNotExistException, IOException {
    T copy = cloneScimResource(resource);
    String resourceType = copy.getResourceType();
    Schema schema = registry.getBaseSchemaOfResourceType(resourceType);

    // return always and default, exclude never and requested
    for (Returned removeAttributesOfType : removeAttributesOfTypes) {
      removeAttributesOfType(copy, schema, removeAttributesOfType);
    }

    for (Entry<String, ScimExtension> extensionEntry : copy.getExtensions().entrySet()) {
      String extensionUrn = extensionEntry.getKey();
      ScimExtension scimExtension = extensionEntry.getValue();

      Schema extensionSchema = registry.getSchema(extensionUrn);

      for (Returned removeAttributesOfType : removeAttributesOfTypes) {
        removeAttributesOfType(scimExtension, extensionSchema, removeAttributesOfType);
      }
    }
    return copy;
  }

  public <T extends ScimResource> T setAttributesForDisplay(T resource, Set<AttributeReference> attributes) throws IllegalArgumentException, IllegalAccessException, AttributeDoesNotExistException, IOException {
    if (attributes.isEmpty()) {
      return setAttributesForDisplay(resource);
    } else {
      T copy = cloneScimResource(resource);
      
      String resourceType = copy.getResourceType();
      Schema schema = registry.getBaseSchemaOfResourceType(resourceType);

      // return always and specified attributes, exclude never
      Set<Attribute> attributesToKeep = resolveAttributeReferences(attributes, true);
      Set<String> extensionsToRemove = new HashSet<>();
      removeAttributesOfType(copy, schema, Returned.DEFAULT, attributesToKeep);
      removeAttributesOfType(copy, schema, Returned.REQUEST, attributesToKeep);
      removeAttributesOfType(copy, schema, Returned.NEVER);

      for (Entry<String, ScimExtension> extensionEntry : copy.getExtensions().entrySet()) {
        String extensionUrn = extensionEntry.getKey();
        ScimExtension scimExtension = extensionEntry.getValue();
        boolean removeExtension = true;

        for (Attribute attributeToKeep : attributesToKeep) {
          if (extensionUrn.equalsIgnoreCase(attributeToKeep.getUrn())) {
            removeExtension = false;

            break;
          }
        }
        if (removeExtension) {
          extensionsToRemove.add(extensionUrn);

          continue;
        }
        Schema extensionSchema = registry.getSchema(extensionUrn);

        removeAttributesOfType(scimExtension, extensionSchema, Returned.DEFAULT, attributesToKeep);
        removeAttributesOfType(scimExtension, extensionSchema, Returned.REQUEST, attributesToKeep);
        removeAttributesOfType(scimExtension, extensionSchema, Returned.NEVER);
      }
      for (String extensionUrn : extensionsToRemove) {
        copy.removeExtension(extensionUrn);
      }
      return copy;
    }
  }

  public <T extends ScimResource> T setExcludedAttributesForDisplay(T resource, Set<AttributeReference> excludedAttributes) throws IllegalArgumentException, IllegalAccessException, AttributeDoesNotExistException, IOException {

    if (excludedAttributes.isEmpty()) {
      return setAttributesForDisplay(resource);
    } else {
      T copy = cloneScimResource(resource);

      String resourceType = copy.getResourceType();
      Schema schema = registry.getBaseSchemaOfResourceType(resourceType);

      // return always and default, exclude never and specified attributes
      Set<Attribute> attributesToRemove = resolveAttributeReferences(excludedAttributes, false);
      removeAttributesOfType(copy, schema, Returned.REQUEST);
      removeAttributesOfType(copy, schema, Returned.NEVER);
      removeAttributes(copy, schema, attributesToRemove);

      for (Entry<String, ScimExtension> extensionEntry : copy.getExtensions().entrySet()) {
        String extensionUrn = extensionEntry.getKey();
        ScimExtension scimExtension = extensionEntry.getValue();

        Schema extensionSchema = registry.getSchema(extensionUrn);

        removeAttributesOfType(scimExtension, extensionSchema, Returned.REQUEST);
        removeAttributesOfType(scimExtension, extensionSchema, Returned.NEVER);
        removeAttributes(scimExtension, extensionSchema, attributesToRemove);
      }
      return copy;
    }
  }

  @SuppressWarnings("unchecked")
  private <T extends ScimResource> T cloneScimResource(T original) throws IOException {
    ByteArrayOutputStream boas = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(boas);
    oos.writeObject(original);

    ByteArrayInputStream bais = new ByteArrayInputStream(boas.toByteArray());
    ObjectInputStream ois = new ObjectInputStream(bais);
    T copy = null;
    try {
      copy = (T) ois.readObject();
    } catch (ClassNotFoundException e) {
      // Should never happen
      log.error("", e);
    }
    return copy;
  }

  private void removeAttributesOfType(Object object, AttributeContainer attributeContainer, Returned returned) throws IllegalArgumentException, IllegalAccessException {
    Function<Attribute, Boolean> function = (attribute) -> returned == attribute.getReturned();
    processAttributes(object, attributeContainer, function);
  }

  private void removeAttributesOfType(Object object, AttributeContainer attributeContainer, Returned returned, Set<Attribute> attributesToKeep) throws IllegalArgumentException, IllegalAccessException {
    Function<Attribute, Boolean> function = (attribute) -> !attributesToKeep.contains(attribute) && returned == attribute.getReturned();
    processAttributes(object, attributeContainer, function);
  }

  private void removeAttributes(Object object, AttributeContainer attributeContainer, Set<Attribute> attributesToRemove) throws IllegalArgumentException, IllegalAccessException {
    Function<Attribute, Boolean> function = (attribute) -> attributesToRemove.contains(attribute);
    processAttributes(object, attributeContainer, function);
  }

  private void processAttributes(Object object, AttributeContainer attributeContainer, Function<Attribute, Boolean> function) throws IllegalArgumentException, IllegalAccessException {
    if (attributeContainer != null && object != null) {
      for (Attribute attribute : attributeContainer.getAttributes()) {
        Field field = attribute.getField();
        if (function.apply(attribute)) {
          field.setAccessible(true);
          if (!field.getType().isPrimitive()) {
            Object obj = field.get(object);
            if (obj == null) {
              continue;
            }
            
            log.info("field to be set to null = " + field.getType().getName());
            field.set(object, null);
          }
        } else if (!attribute.isMultiValued() && attribute.getType() == Type.COMPLEX) {
          String name = field.getName();
          log.debug("### Processing single value complex field " + name);
          field.setAccessible(true);
          Object subObject = field.get(object);

          if (subObject == null) {
            continue;
          }
          
          Attribute subAttribute = attributeContainer.getAttribute(name);
          log.debug("### container type = " + attributeContainer.getClass().getName());
          if (subAttribute == null) {
            log.debug("#### subattribute == null");
          }
          processAttributes(subObject, subAttribute, function);
        } else if (attribute.isMultiValued() && attribute.getType() == Type.COMPLEX) {
          String name = field.getName();
          log.debug("### Processing multi-valued complex field " + name);
          field.setAccessible(true);
          Object subObject = field.get(object);

          if (subObject == null) {
            continue;
          }

          if (Collection.class.isAssignableFrom(subObject.getClass())) {
            Collection<?> collection = (Collection<?>) subObject;
            for (Object o : collection) {
              Attribute subAttribute = attributeContainer.getAttribute(name);
              processAttributes(o, subAttribute, function);
            }
          } else if (field.getType().isArray()) {
            Object[] array = (Object[]) subObject;

            for (Object o : array) {
              Attribute subAttribute = attributeContainer.getAttribute(name);
              processAttributes(o, subAttribute, function);
            }
          }
        }
      }
    }
  }

  public Set<AttributeReference> getAttributeReferences(String s) {
    Set<AttributeReference> attributeReferences = new HashSet<>();

    String[] split = StringUtils.split(s, ",");

    for (String af : split) {
      AttributeReference attributeReference = new AttributeReference(af);
      attributeReferences.add(attributeReference);
    }

    return attributeReferences;
  }

  private Set<Attribute> resolveAttributeReferences(Set<AttributeReference> attributeReferences, boolean includeAttributeChain) throws AttributeDoesNotExistException {
    Set<Attribute> attributes = new HashSet<>();

    for (AttributeReference attributeReference : attributeReferences) {
      Set<Attribute> findAttributes = findAttribute(attributeReference, includeAttributeChain);
      if (!findAttributes.isEmpty()) {
        attributes.addAll(findAttributes);
      }
    }

    return attributes;
  }

  private Set<Attribute> findAttribute(AttributeReference attributeReference, boolean includeAttributeChain) throws AttributeDoesNotExistException {
    String schemaUrn = attributeReference.getUrn();
    Schema schema = null;
    Set<Attribute> attributes;
    
    if (!StringUtils.isEmpty(schemaUrn)) {
      schema = registry.getSchema(schemaUrn);

      attributes = findAttributeInSchema(schema, attributeReference, includeAttributeChain);
      if (attributes.isEmpty()) {
        log.error("Attribute " + attributeReference.getFullyQualifiedAttributeName() + "not found in schema " + schemaUrn);
        throw new AttributeDoesNotExistException(attributeReference.getFullyQualifiedAttributeName());
      }
      return attributes;
    }

    // Handle unqualified attributes, look in the core schemas
    schema = registry.getSchema(ScimUser.SCHEMA_URI);
    attributes = findAttributeInSchema(schema, attributeReference, includeAttributeChain);
    if (!attributes.isEmpty()) {
      return attributes;
    }

    schema = registry.getSchema(ScimGroup.SCHEMA_URI);
    attributes = findAttributeInSchema(schema, attributeReference, includeAttributeChain);
    if (!attributes.isEmpty()) {
      return attributes;
    }

    log.error("Attribute " + attributeReference.getFullyQualifiedAttributeName() + "not found in any schema.");
    throw new AttributeDoesNotExistException(attributeReference.getFullyQualifiedAttributeName());
  }

  private Set<Attribute> findAttributeInSchema(Schema schema, AttributeReference attributeReference, boolean includeAttributeChain) {
    AttributeContainer attributeContainer = schema;
    if (attributeContainer == null) {
      return Collections.emptySet();
    }
    Set<Attribute> attributes = new HashSet<>();
    String attributeName = attributeReference.getAttributeName();
    String subAttributeName = attributeReference.getSubAttributeName();
    Attribute attribute = attributeContainer.getAttribute(attributeName);

    if (attribute == null) {
      return Collections.emptySet();
    }
    if (includeAttributeChain || subAttributeName == null) {
      attributes.add(attribute);
    }
    if (subAttributeName != null) {
      attribute = attribute.getAttribute(subAttributeName);

      if (attribute == null) {
        return Collections.emptySet();
      }
      attributes.add(attribute);
    }
    if (attribute.getType() == Type.COMPLEX && includeAttributeChain) {
      List<Attribute> remaininAttributes = attribute.getAttributes();
      attributes.addAll(remaininAttributes);
    }
    return attributes;
  }

}
