package speiger.src.coreengine.assets.api;

import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

import speiger.src.coreengine.assets.impl.FolderAssetPackage;
import speiger.src.coreengine.assets.impl.FolderWatcher.ChangeType;
import speiger.src.coreengine.assets.impl.ZipAssetPackage;

@NullMarked
public interface IAssetPackage extends AutoCloseable {
	void registerWatchers(IFileWatcher watcher) throws IOException;
	boolean handleChange(Path file, ChangeType type, Consumer<ID> changed) throws IOException;
	List<String> domains();
	@Nullable
	IAsset get(ID location);
	void getAll(ID folder, BiConsumer<ID, IAsset> assets);
	
	public static IAssetPackage asset(Path path) {
		return create(path, "assets");
	}
	
	public static IAssetPackage create(Path path, String baseFolder) {
		if(Files.exists(path)) {
			if(Files.isDirectory(path)) return new FolderAssetPackage(path.resolve(baseFolder));
			if(isZip(path)) return new ZipAssetPackage(path, baseFolder);
		}
		return null;
	}
	
	private static boolean isZip(Path path) {
		try(FileSystem system = FileSystems.newFileSystem(path)) { return "jar".equals(system.provider().getScheme()); }
		catch(Exception _) { return false; }
	}
	
	public record AssetIdentity(long size, FileTime lastModified) {
		
		public AssetIdentity(Path path) throws IOException {
			BasicFileAttributes attributes = Files.readAttributes(path, BasicFileAttributes.class);
			this(attributes.size(), attributes.lastModifiedTime());
		}
		
		public boolean matches(Path path) throws IOException {
			BasicFileAttributes attributes = Files.readAttributes(path, BasicFileAttributes.class);
			return size() == attributes.size() && lastModified().equals(attributes.lastModifiedTime());
		}
	}
}
