package com.armundia.core;

import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;

import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.ext.Provider;

import com.armundia.v2.shared.security.CorsFilter;

@Provider
public class CORSFeature implements Feature {

	private static final String DEFAULT_ALLOWED_HTTP_HEADERS = "Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers, server-id, encoded, request-id";

	public final static Logger log = Logger.getLogger(CORSFeature.class.getName());

	private static final String DEFAULT_ALLOWED_HTTP_METHODS = "GET,POST,HEAD,OPTIONS";

	//The Access-Control-Max-Age response header indicates how long the results of a preflight request (that is the information contained in the Access-Control-Allow-Methods and Access-Control-Allow-Headers headers) can be cached.
	//600 = 10 minuti
	private static final String DEFAULT_PREFLIGHT_MAXAGE = "600";

	//Credentials are cookies, authorization headers or TLS client certificates.
	private static final String DEFAULT_ALLOW_CREDENTIALS = "true";

	@Override
	public boolean configure(FeatureContext context) {
		CorsFilter corsFilter = new CorsFilter();

		String allowedOrigins = System.getProperty("CORS.ALLOWED_ORIGINS");
		corsFilter.getAllowedOrigins().clear();
		if (allowedOrigins == null || allowedOrigins.trim().equals("")) {
			allowedOrigins = "*";
			corsFilter.getAllowedOrigins().add("*");
		} else {
			Set<String> setAllowedOrigins = parseStringToSet(allowedOrigins);
			corsFilter.getAllowedOrigins().addAll(setAllowedOrigins);
		}
		log.info(String.format("[CORS.ALLOWED_ORIGINS] " + allowedOrigins));

		String allowedHttpHeaders = System.getProperty("CORS.ALLOWED_HTTP_HEADERS");
		if (allowedHttpHeaders == null || allowedHttpHeaders.trim().equals("")) {
			allowedHttpHeaders = DEFAULT_ALLOWED_HTTP_HEADERS;
		}
		log.info(String.format("[CORS.ALLOWED_HTTP_HEADERS] " + allowedHttpHeaders));
		corsFilter.setAllowedHeaders(allowedHttpHeaders);

		String allowedMethods = System.getProperty("CORS.ALLOWED_METHODS");
		if (allowedMethods == null || allowedMethods.trim().equals("")) {
			allowedMethods = DEFAULT_ALLOWED_HTTP_METHODS;
		}
		log.info(String.format("[CORS.ALLOWED_METHODS] " + allowedMethods));
		corsFilter.setAllowedMethods(allowedMethods);

		String maxAge = System.getProperty("CORS.MAX_AGE");
		if (maxAge == null || maxAge.trim().equals("")) {
			maxAge = DEFAULT_PREFLIGHT_MAXAGE;
		}
		log.info(String.format("[CORS.MAX_AGE] " + maxAge));
		corsFilter.setCorsMaxAge(Integer.parseInt(maxAge));

		String allowCredentials = System.getProperty("CORS.ALLOW_CREDENTIALS");
		if (allowCredentials == null || allowCredentials.trim().equals("")) {
			allowCredentials = DEFAULT_ALLOW_CREDENTIALS;
		}
		log.info(String.format("[CORS.ALLOW_CREDENTIALS] " + allowCredentials));
		// For any value other then 'true' this will be false.
		corsFilter.setAllowCredentials(Boolean.parseBoolean(allowCredentials));

		//Di default solo 7 response headers sono esposti al client (javascript):
		//Cache-control
		//Content-Language
		//Content-Length
		//Content-Type
		//Expires
		//Last-Modified
		//Pragma
		//If you want clients to be able to access other headers, you have to list them using the Access-Control-Expose-Headers header.
		corsFilter.setExposedHeaders("Content-Disposition");
		context.register(corsFilter);
		return true;
	}

	private Set<String> parseStringToSet(final String data) {
		String[] splits;

		if (data != null && data.length() > 0) {
			splits = data.split(",");
		} else {
			splits = new String[] {};
		}

		Set<String> set = new HashSet<String>();
		if (splits.length > 0) {
			for (String split : splits) {
				set.add(split.trim());
			}
		}

		return set;
	}

}