package speiger.src.coreengine.assets.api;

import java.nio.file.Path;
import java.util.Objects;

public record ID(String domain, String path) implements Comparable<ID> {
	
	public ID {
		if(!isValidDomain(Objects.requireNonNull(domain))) throw new IllegalArgumentException("Non [a-zA-Z0-9_.-] Character found in domain of location ["+domain+":"+path+"]");
		if(!isValidPath(Objects.requireNonNull(path))) throw new IllegalArgumentException("Non [a-zA-Z0-9/_.-] Character found in path of location ["+domain+":"+path+"]");
	}
	
	public ID prefix(String prefix) { return of(domain, prefix+"/"+path); }
	public ID suffix(String suffix) { return of(domain, path+"/"+suffix); }
	public ID suffix(Path path) { return suffix(path.toString().replace("\\", "/")); }
	public ID alternate(String alterversion) { return of(domain, path+"."+alterversion); }
	
	public String fileLocation() { return domain+"/"+path; }
	public boolean isRoot() { return !path.contains("/"); }
	public boolean isRootFolder(String folder) { return path.indexOf('/', folder.length()+1) == -1; }
	public boolean endsWith(String suffix) { return path.endsWith(suffix); }
	public boolean startsWith(String prefix) { return path.startsWith(prefix); }
	
	@Override
	public final String toString() {
		return domain+":"+path;
	}
	
	@Override
	public int compareTo(ID o) {
		int result = domain.compareToIgnoreCase(o.domain);
		return result != 0 ? result : path.compareToIgnoreCase(path);
	}
	
	public boolean matches(ID id) {
		return id.domain.equals(domain) && id.path.equals(path);
	}
	
	public static final ID of(String domain, String path) {
		return new ID((domain == null || domain.isBlank() ? "base" : domain), path);
	}
	
	public static final ID of(String location) {
		Objects.requireNonNull(location);
		int index = location.indexOf(":");
		String domain = index == -1 ? "base" : location.substring(0, index);
		String path = index == -1 ? location : location.substring(index + 1);
		if(!isValidDomain(domain)) throw new IllegalArgumentException("Non [a-zA-Z0-9_.-] Character found in domain of location ["+domain+":"+path+"]");
		if(!isValidPath(path)) throw new IllegalArgumentException("Non [a-zA-Z0-9/_.-] Character found in path of location ["+domain+":"+path+"]");
		return new ID(domain, path);
	}
	
	public static final ID of(Path path) {
		return of(path.getName(0).toString(), path.subpath(1, path.getNameCount()).toString().replace("\\", "/"));
	}
	
	public static final ID tryOf(String location) {
		try { return of(location); }
		catch(Exception e) { return null; }
	}
	
	private static boolean isValidDomain(String s) {
		for(int i = 0,m=s.length();i<m;i++) {
			if(!isValidDomainChar(s.charAt(i))) return false;
		}
		return true;
	}
	
	private static boolean isValidPath(String s) {
		for(int i = 0,m=s.length();i<m;i++) {
			if(!isValidPathChar(s.charAt(i))) return false;
		}
		return true;
	}
	
	private static boolean isValidPathChar(char c) {
		return c == '/' || isValidDomainChar(c);
	}
	
	private static boolean isValidDomainChar(char c) {
		return c == '_' || c == '-' || c == '.' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9');
	}
}
