/*
* 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);
  }

  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;
  }

}
