package org.apereo.cas.support.geo.config;

import org.apereo.cas.authentication.adaptive.geo.GeoLocationService;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.configuration.model.support.geo.maxmind.MaxmindProperties;
import org.apereo.cas.support.geo.maxmind.MaxmindDatabaseGeoLocationService;

import com.maxmind.db.CHMCache;
import com.maxmind.geoip2.DatabaseReader;
import lombok.SneakyThrows;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;

/**
 * This is {@link CasGeoLocationConfiguration}.
 *
 * @author Misagh Moayyed
 * @since 5.0.0
 */
@Configuration("casGeoLocationConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
public class CasGeoLocationConfiguration {

    @Autowired
    private CasConfigurationProperties casProperties;

    @Bean
    @RefreshScope
    @SneakyThrows
    public GeoLocationService geoLocationService() {
        val properties = casProperties.getMaxmind();
        val cityDatabase = readCityDatabase(properties);
        val countryDatabase = readCountryDatabase(properties);

        if (cityDatabase == null && countryDatabase == null) {
            throw new IllegalArgumentException("No geolocation services have been defined for Maxmind");
        }

        val svc = new MaxmindDatabaseGeoLocationService(cityDatabase, countryDatabase);
        svc.setIpStackAccessKey(properties.getIpStackApiAccessKey());
        return svc;
    }

    private DatabaseReader readCountryDatabase(final MaxmindProperties properties) throws IOException {
        if (properties.getCountryDatabase().exists()) {
            return new DatabaseReader.Builder(properties.getCountryDatabase().getFile()).withCache(new CHMCache()).build();
        }
        return null;
    }

    private DatabaseReader readCityDatabase(final MaxmindProperties properties) throws IOException {
        if (properties.getCityDatabase().exists()) {
            return new DatabaseReader.Builder(properties.getCityDatabase().getFile()).withCache(new CHMCache()).build();
        }
        return null;
    }
}

@@ -175,89 +175,8 @@
 es;%0A
-import org.apereo.cas.configuration.model.support.geo.maxmind.MaxmindProperties;%0A
 impo
@@ -248,16 +248,16 @@
 ervice;%0A
+
 %0Aimport 
@@ -700,16 +700,61 @@
 uration;
+%0Aimport org.springframework.core.io.Resource;
 %0A%0Aimport
@@ -1036,23 +1036,8 @@
  %7B%0A%0A
-    @Autowired%0A
     
@@ -1087,16 +1087,171 @@
 rties;%0A%0A
+    @Autowired%0A    public CasGeoLocationConfiguration(final CasConfigurationProperties casProperties) %7B%0A        this.casProperties = casProperties;%0A    %7D%0A%0A
     @Bea
@@ -1421,28 +1421,24 @@
 abase = read
-City
 Database(pro
@@ -1444,16 +1444,34 @@
 operties
+.getCityDatabase()
 );%0A     
@@ -1495,31 +1495,24 @@
 abase = read
-Country
 Database(pro
@@ -1518,16 +1518,37 @@
 operties
+.getCountryDatabase()
 );%0A%0A    
@@ -1938,23 +1938,16 @@
 der read
-Country
 Database
@@ -1957,36 +1957,32 @@
 nal 
-MaxmindProperties properties
+Resource maxmindDatabase
 ) th
@@ -2016,353 +2016,50 @@
 if (
-properties.getCountryDatabase().exists()) %7B%0A            return new DatabaseReader.Builder(properties.getCountryDatabase().getFile()).withCache(new CHMCache()).build();%0A        %7D%0A        return null;%0A    %7D%0A%0A    private DatabaseReader readCityDatabase(final MaxmindProperties properties) throws IOException %7B%0A        if (properties.getCity
+maxmindDatabase != null && maxmind
 Database
 ().e
@@ -2054,18 +2054,16 @@
 Database
-()
 .exists(
@@ -2117,34 +2117,23 @@
 der(
-properties.getCity
+maxmind
 Database
 ().g
@@ -2128,18 +2128,16 @@
 Database
-()
 .getFile

Fix possible NPE in configuration when no db props are provided (#3434)