package speiger.src.coreengine.assets;

import java.util.Map;
import java.util.Objects;
import java.util.function.Function;

import speiger.src.collections.objects.maps.impl.hash.Object2ObjectOpenHashMap;
import speiger.src.collections.objects.utils.maps.Object2ObjectMaps;

public final class AssetLocation implements Comparable<AssetLocation>
{
	static final Map<String, AssetLocation> LOCATION = Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<>());
	static final Function<String, AssetLocation> BUILDER = AssetLocation::compute;
	final String domain;
	final String location;
	
	private AssetLocation() {throw new UnsupportedOperationException("use AssetLocation.of instead");}
	
	private AssetLocation(String domain, String location)
	{
		this.domain = domain;
		this.location = location;
	}
	
	public String getDomain()
	{
		return domain;
	}
	
	public String getLocation()
	{
		return location;
	}
	
	public String getActualLocation()
	{
		return "assets/"+domain+"/"+location;
	}
	
	public AssetLocation subAsset(String subPath)
	{
		return of(domain+":"+location + "/" + subPath);
	}
	
	public AssetLocation alternate(String alterversion)
	{
		return of(domain+":"+location+"."+alterversion);
	}
	
	@Override
	public String toString()
	{
		return domain+":"+location;
	}
	
	@Override
	public int hashCode()
	{
		return Objects.hash(domain, location);
	}
	
	@Override
	public boolean equals(Object obj)
	{
		if(obj == this)
		{
			return true;
		}
		if(obj instanceof AssetLocation)
		{
			AssetLocation location = (AssetLocation)obj;
			return location.domain.equals(domain) && location.location.equals(this.location);
		}
		return false;
	}
	
	@Override
	public int compareTo(AssetLocation o)
	{
		int result = domain.compareToIgnoreCase(o.domain);
		return result != 0 ? result : location.compareToIgnoreCase(location);
	}
	
	public boolean matches(AssetLocation location)
	{
		return location.domain.equals(domain) && location.location.equals(this.location);
	}
	
	public static final AssetLocation of(String domain, String location)
	{
		return of((domain == null || domain.isEmpty() ? "base" : domain)+":"+location);
	}
	
	public static final AssetLocation of(String location)
	{
		return LOCATION.computeIfAbsent(location.indexOf(":") == -1 ? "base:"+location : location, BUILDER);
	}
	
	private static final AssetLocation compute(String s)
	{
		int index = s.indexOf(":");
		return new AssetLocation(s.substring(0, index), s.substring(index+1, s.length()));
	}
}
