package org.apereo.cas.configuration.model.core.authentication;

import org.apereo.cas.configuration.support.RequiredProperty;
import org.apereo.cas.configuration.support.RequiresModule;
import org.apereo.cas.configuration.support.RestEndpointProperties;
import org.apereo.cas.configuration.support.SpringResourceProperties;

import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

import java.io.Serializable;

/**
 * This is {@link AdaptiveAuthenticationIPIntelligenceProperties}.
 *
 * @author Misagh Moayyed
 * @since 5.0.0
 */
@RequiresModule(name = "cas-server-core-authentication", automated = true)
@Getter
@Setter
@Accessors(chain = true)
public class AdaptiveAuthenticationIPIntelligenceProperties implements Serializable {

    private static final long serialVersionUID = -9111174229142982880L;

    /**
     * Fetch IP diagnostic information via REST.
     */
    private Rest rest = new Rest();

    /**
     * Fetch IP diagnostic information via Groovy.
     */
    private Groovy groovy = new Groovy();

    /**
     * Fetch IP diagnostic information via <a href="getipintel.net">IP Intel</a>.
     */
    private BlackDot blackDot = new BlackDot();

    @RequiresModule(name = "cas-server-core-authentication", automated = true)
    @Getter
    @Setter
    @Accessors(chain = true)
    public static class Groovy extends SpringResourceProperties {
        private static final long serialVersionUID = 8079027843747126083L;
    }

    @RequiresModule(name = "cas-server-core-authentication", automated = true)
    @Getter
    @Setter
    @Accessors(chain = true)
    public static class Rest extends RestEndpointProperties {
        private static final long serialVersionUID = 3659099897056632608L;
    }

    @RequiresModule(name = "cas-server-core-authentication", automated = true)
    @Getter
    @Setter
    @Accessors(chain = true)
    public static class BlackDot implements Serializable {
        private static final long serialVersionUID = -4655149615297049570L;

        /**
         * URL endpoint of the service to make API calls.
         */
        private String url = "http://check.getipintel.net/check.php?ip=%s";

        /**
         * Include your contact information so you can be notified if a problem arise or if there are core changes.
         */
        @RequiredProperty
        private String emailAddress;

        /**
         * <ul>
         * <li>{@code DYNA_LIST}: If you get a value between 0 - 1, exclusive (like 0.99, 0.99999, 0.97), these values are generated by dynamic
         * checks which looks for characteristics of the given IP. IPs that are either manually banned or seen on a
         * public proxy site will return a value of 1. If you only want manually banned or public proxies, then in your
         * code just look for the value "1". However, there are many IPs that haven't gone through manual review and IPs
         * can change behavior very frequently (which is why dynamic checks exist in the first place). If you only look
         * for the value of "1", then expect to have more proxy / VPN / bad IPs go through your system, however, false
         * positives are less likely if you use the dynamic ban list option. If you wish to use only manually banned and
         * public proxy IPs, append the parameter flags=m, the system will only
         * return a result of 0 or 1. This option is the best to start off with that will have a noticeable impact in bot /
         * proxy / VPN traffic, especially if you don't have any data sets to test with the system.</li>
         *
         * <li>{@code DYNA_CHECK}: In this scenario, you want to use dynamic checks as well but you want to skip additional checks to see if
         * the IP is a bad ip (see What do you mean by "Bad IP"?). In this mode, some bad IPs are still detected but the
         * system does not attempt to go through the full bad IPs check because the time for the extra checks vary wildly
         * (between an extra 200ms to 2 seconds). In this mode, false positives are more likely than dynamic ban lists only.
         * Scores are lower compared to the full IP check (without any flag options) because less attributes are considered.
         * If you wish to use dynamic ban list and dynamic checks only, append the parameter flags=b. This option is the
         * best if dynamic ban lists isn't catching enough IPs but you don't want to run the full check because it takes
         * too long and/or you want to have a predictable execution time.</li>
         *
         * <li>{@code FULL}: Let the system to do a full lookup with one query.</li>
         *
         * </ul>
         */
        private String mode = "DYNA_LIST";
    }
}
