package org.apereo.cas.configuration.model.support.wsfed;

import org.apereo.cas.configuration.model.core.authentication.PersonDirectoryPrincipalResolverProperties;
import org.apereo.cas.configuration.model.support.delegation.DelegationAutoRedirectTypes;
import org.apereo.cas.configuration.support.DurationCapable;
import org.apereo.cas.configuration.support.ExpressionLanguageCapable;
import org.apereo.cas.configuration.support.RequiredProperty;
import org.apereo.cas.configuration.support.RequiresModule;

import com.fasterxml.jackson.annotation.JsonFilter;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.springframework.boot.context.properties.NestedConfigurationProperty;

import java.io.Serial;
import java.io.Serializable;

/**
 * This is {@link WsFederationDelegationProperties}.
 *
 * @author Misagh Moayyed
 * @since 5.0.0
 */
@RequiresModule(name = "cas-server-support-wsfederation-webflow")
@Getter
@Setter
@Accessors(chain = true)
@JsonFilter("WsFederationDelegationProperties")
public class WsFederationDelegationProperties implements Serializable {

    @Serial
    private static final long serialVersionUID = 5743971334977239938L;

    /**
     * The attribute extracted from the assertion and used to construct the CAS principal id.
     */
    @RequiredProperty
    private String identityAttribute = "upn";

    /**
     * The entity id or the identifier of the Wsfed instance.
     */
    @RequiredProperty
    @ExpressionLanguageCapable
    private String identityProviderIdentifier = "http://adfs.example.org/adfs/services/trust";

    /**
     * Wsfed identity provider url.
     */
    @RequiredProperty
    @ExpressionLanguageCapable
    private String identityProviderUrl = "https://adfs.example.org/adfs/ls/";

    /**
     * Locations of signing certificates used to verify assertions.
     * Locations could be specified as static file-system resources(certificates)
     * or they could also be federation XML metadata, either as a URL or an XML file.
     * If federation metadata XML is provided, the signing certificate is extracted
     * from the {@code IDPSSODescriptor}'s key descriptor that is marked for signing.
     */
    @RequiredProperty
    private String signingCertificateResources = "classpath:adfs-signing.crt";

    /**
     * The identifier for CAS (RP) registered with wsfed.
     */
    @RequiredProperty
    @ExpressionLanguageCapable
    private String relyingPartyIdentifier = "urn:cas:localhost";

    /**
     * Tolerance value used to skew assertions to support clock drift.
     */
    @DurationCapable
    private String tolerance = "PT10S";

    /**
     * Indicates how attributes should be recorded into the principal object.
     * Useful if you wish to additionally resolve attributes on top of what wsfed provides.
     * Accepted values are {@code CAS,WSFED,BOTH}.
     */
    private String attributesType = "WSFED";

    /**
     * Whether CAS should enable its own attribute resolution machinery
     * after having received a response from wsfed.
     */
    private boolean attributeResolverEnabled = true;

    /**
     * Whether CAS should auto redirect to this wsfed instance.
     */
    private DelegationAutoRedirectTypes autoRedirectType = DelegationAutoRedirectTypes.SERVER;

    /**
     * The path to the private key used to handle and verify encrypted assertions.
     */
    private String encryptionPrivateKey = "classpath:private.key";

    /**
     * The path to the public key/certificate used to handle and verify encrypted assertions.
     */
    private String encryptionCertificate = "classpath:certificate.crt";

    /**
     * The private key password.
     */
    private String encryptionPrivateKeyPassword = "NONE";

    /**
     * Internal identifier for this wsfed configuration.
     * If undefined, the identifier would be auto-generated by CAS itself.
     * In the event that there is more than on CAS server defined in a clustered
     * deployment, this identifier must be statically defined in the configuration.
     */
    @RequiredProperty
    private String id;

    /**
     * Principal resolution settings.
     */
    @NestedConfigurationProperty
    private PersonDirectoryPrincipalResolverProperties principal = new PersonDirectoryPrincipalResolverProperties();

    /**
     * Name of the authentication handler.
     */
    private String name;

    /**
     * The order of the authentication handler in the chain.
     */
    private int order = Integer.MAX_VALUE;

    /**
     * Path to attribute mutator groovy script
     * that allows one to modify wsfed attributes before
     * establishing a final principal.
     */
    @NestedConfigurationProperty
    private GroovyWsFederationDelegationProperties attributeMutatorScript = new GroovyWsFederationDelegationProperties();

    /**
     * Signing/encryption settings related to managing
     * the cookie that is used to keep track of the session.
     */
    @NestedConfigurationProperty
    private WsFederationDelegatedCookieProperties cookie = new WsFederationDelegatedCookieProperties();

}
