package org.greenstone.gsdl3.util;

import javax.servlet.http.HttpServletRequest;

public class HttpHeaderUtil
{
    public static String headerFirst(HttpServletRequest request, String name) {
	String v = request.getHeader(name);
	if (v == null) return null;
	// proxies sometimes send comma-separated lists
	int comma = v.indexOf(',');
	return (comma >= 0) ? v.substring(0, comma).trim() : v.trim();
    }
    
    public static int parseIntOrDefault(String s, int def) {
	try { return (s == null) ? def : Integer.parseInt(s.trim()); }
	catch (Exception e) { return def; }
    }
    
    public static String normalisePathPrefix(String p) {
	if (p == null) return "";
	String x = p.trim();
	if (x.isEmpty() || "/".equals(x)) return "";
	if (!x.startsWith("/")) x = "/" + x;
	while (x.endsWith("/") && x.length() > 1) x = x.substring(0, x.length() - 1);
	return x;
    }
    
    public static String getExternalContext(HttpServletRequest request) {

	String xfPrefix = headerFirst(request, "X-Forwarded-Prefix");
	// Apache2 config typically configured to forward this in cases where
	// public-facing context is different to the usual /greenstone3
	String externalPrefix = normalisePathPrefix(xfPrefix); 

	if ((externalPrefix == null) || externalPrefix.equals("")) {
	    return request.getContextPath(); // the internal context
	}
	return externalPrefix;
    }
	
    public static String computeExternalBaseContextURL(HttpServletRequest request) {
	// 1) scheme
	String xfProto = headerFirst(request, "X-Forwarded-Proto");
	String scheme = (xfProto != null && !xfProto.isBlank()) ? xfProto : request.getScheme();
	
	// 2) host (may include port)
	String xfHost = headerFirst(request, "X-Forwarded-Host");
	String host = (xfHost != null && !xfHost.isBlank()) ? xfHost : request.getServerName();
	
	// 3) port (only if host doesn't already include it and it's non-default)
	String xfPort = headerFirst(request, "X-Forwarded-Port");
	int port = parseIntOrDefault(xfPort, request.getServerPort());
	boolean hostHasPort = host.contains(":");
	
	// 4) prefix (external context)
	String xfPrefix = headerFirst(request, "X-Forwarded-Prefix");
	// Apache2 config typically configured to forward this in cases where
	// public-facing context is different to the usual /greenstone3
	String externalPrefix = normalisePathPrefix(xfPrefix); 
	
	// 5) internal context (/greenstone3)
	String internalContext = request.getContextPath(); // "/greenstone3"
	
	// 6) request URI includes internal context; strip it then add external prefix
	String uri = request.getRequestURI();              // "/greenstone3/library/..."
	String pathRemainder = uri.startsWith(internalContext)
            ? uri.substring(internalContext.length())  // "/library/..."
            : uri;
	
	StringBuilder base = new StringBuilder();
	base.append(scheme).append("://").append(host);
	
	if (!hostHasPort && port > 0) {
	    boolean defaultPort = ("http".equalsIgnoreCase(scheme) && port == 80)
		|| ("https".equalsIgnoreCase(scheme) && port == 443);
        if (!defaultPort) base.append(':').append(port);
	}

	if ((externalPrefix == null) || externalPrefix.equals("")) {
	    base.append(internalContext);
	}
	else {
	    base.append(externalPrefix);
	}

	//System.err.println("scheme="+scheme+", port="+port+", external = "+externalPrefix+", internalContext="+internalContext+", remainder="+pathRemainder);
	return base.toString();
    }
    
    public static String externalRequestedURL(HttpServletRequest request) {
	String base = computeExternalBaseContextURL(request);
	
	String internalContext = request.getContextPath();
	String uri = request.getRequestURI();
	String remainder = uri.startsWith(internalContext)
            ? uri.substring(internalContext.length())
            : uri;
	//System.err.println("base = "+base+", internal="+internalContext+", remainder="+remainder);
	return base + remainder;
    }

    public static String externalRequestedURI(HttpServletRequest request) {

		
	// prefix (external context)
	String xfPrefix = headerFirst(request, "X-Forwarded-Prefix");
	// Apache2 config typically configured to forward this in cases where
	// public-facing context is different to the usual /greenstone3
	String externalPrefix = normalisePathPrefix(xfPrefix); 

	if (externalPrefix == null || externalPrefix.equals("")) {
	    return request.getRequestURI();
	}
	
	// internal context (/greenstone3)
	String internalContext = request.getContextPath(); // "/greenstone3"
	
	// 6) request URI includes internal context; strip it then add external prefix
	String uri = request.getRequestURI();              // "/greenstone3/library/..."
	String pathRemainder = uri.startsWith(internalContext)
            ? uri.substring(internalContext.length())  // "/library/..."
            : uri;

	return externalPrefix +pathRemainder;
    }

}
