package cz.muni.ics.oidc.server.configurations;

import cz.muni.ics.openid.connect.config.ConfigurationPropertiesBean;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.util.StringUtils;
import org.springframework.web.util.UriComponentsBuilder;

import javax.servlet.ServletContext;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 * Configuration of OIDC server in context of Perun.
 * Logs some interesting facts.
 *
 * @author Martin Kuba <makub@ics.muni.cz>
 */
@Slf4j
@Getter
@Setter
public class PerunOidcConfig implements InitializingBean {

	private static final String OIDC_POM_FILE = "/META-INF/maven/cz.muni.ics/perun-oidc-server-webapp/pom.properties";

	private final Map<String, String> languageMap = new HashMap<>();

	private ConfigurationPropertiesBean configBean;

	private String rpcUrl;

	private String jwk;

	private String jdbcUrl;

	private String theme;

	private String baseURL;

	private String registrarUrl;

	private String samlResourcesURL;

	private String requesterIdPrefix;

	private boolean askPerunForIdpFiltersEnabled;

	private String perunOIDCVersion;

	private String proxyExtSourceName;

	private Set<String> idTokenScopes;

	private boolean fillMissingUserAttrs;

	private boolean addClientIdToAcrs = false;

	private String localizationFilesPath;

	private String webClassesFilePath;

	private String emailContact;

	private String rpcEnabled;

	private String sentryConfigFileLocation;

	private String ga4ghTokenExchangeBrokerUrl;

	private boolean krbTokenExchangeEnabled;

	private String krbTokenExchangeApiUrl;

	private String krbTokenExchangeApiUsername;

	private String krbTokenExchangeApiPassword;

	private Set<String> krbTokenExchangeRequiredScopes;

	private boolean onlyAllowedIdpsEnabled = false;

	private boolean blockedIdpsEnabled = false;

	@Autowired
	private ServletContext servletContext;

	@Autowired
	private Properties coreProperties;

	private boolean logRequestsEnabled;

	public String getPerunOIDCVersion() {
		if (perunOIDCVersion == null) {
			perunOIDCVersion = readPomVersion(OIDC_POM_FILE);
		}
		return perunOIDCVersion;
	}

	private String readPomVersion(String file) {
		try {
			Properties p = new Properties();
			p.load(servletContext.getResourceAsStream(file));
			return p.getProperty("version");
		} catch (IOException e) {
			log.error("cannot read file " + file, e);
			return "UNKNOWN";
		}
	}

	public void setProxyExtSourceName(String proxyExtSourceName) {
		if (!StringUtils.hasText(proxyExtSourceName)) {
			this.proxyExtSourceName = null;
		} else {
			this.proxyExtSourceName = proxyExtSourceName;
		}
	}

	public Set<String> getAvailableLangs() {
		return languageMap.keySet();
	}

	public void setAvailableLangs(List<String> availableLangs) {
		languageMap.clear();
		for (String lang: availableLangs) {
			switch (lang.toLowerCase()) {
				case "en": {
					languageMap.put("en", "English");
				} break;
				case "cs": {
					languageMap.put("cs", "Čeština");
				} break;
			}
		}
	}

	@Override
	public void afterPropertiesSet() {
		if (StringUtils.hasText(samlResourcesURL)) {
			samlResourcesURL = samlResourcesURL.trim();
		} else {
			samlResourcesURL = UriComponentsBuilder.fromHttpUrl(configBean.getIssuer()).replacePath("/proxy").build().toString();
		}
	}

	//called when all beans are initialized, but twice, once for root context and once for spring-servlet
	@EventListener
	public void handleContextRefresh(ContextRefreshedEvent event) {
		if (event.getApplicationContext().getParent() == null) {
			//log info
			log.info("Perun OIDC initialized");
			log.info("Mitreid config URL: {}", configBean.getIssuer());
			log.info("RPC URL: {}", rpcUrl);
			log.info("JSON Web Keys: {}", jwk);
			log.info("JDBC URL: {}", jdbcUrl);
			log.info("LDAP: ldaps://{}/{}", coreProperties.getProperty("ldap.host"), coreProperties.getProperty("ldap.baseDN"));
			log.info("FILL MISSING USER ATTRS: {}", fillMissingUserAttrs);
			log.info("THEME: {}", theme);
			log.info("baseURL: {}", baseURL);
			log.info("samlResourcesURL: {}", samlResourcesURL);
			log.info("Registrar URL: {}", registrarUrl);
			log.info("accessTokenClaimsModifier: {}", coreProperties.getProperty("accessTokenClaimsModifier"));
			log.info("Proxy EXT_SOURCE name: {}", proxyExtSourceName);
			log.info("Available languages: {}", languageMap.keySet());
			log.info("Localization files path: {}", localizationFilesPath);
			log.info("Email contact: {}", emailContact);
			log.info("Sentry enabled: {}", StringUtils.hasText(sentryConfigFileLocation));
			log.info("OnlyAllowedIdPs ACR enabled: {}", onlyAllowedIdpsEnabled);
			log.info("BlockedIdPs ACR enabled: {}", blockedIdpsEnabled);
			log.info("Perun OIDC version: {}", getPerunOIDCVersion());
		}
	}

}
