package speiger.src.coreengine.assets.oldImpl;

import java.io.IOException;
import java.nio.file.DirectoryStream;
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.FileTime;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.stream.Stream;

import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.assets.base.IAssetPackage;
import speiger.src.coreengine.utils.collections.iterators.IterableWrapper;

public class ZipAssetPackage implements IAssetPackage {
	Path baseFolder;
	FileSystem cache;
	
	public ZipAssetPackage(Path baseFolder) {
		this.baseFolder = baseFolder;
	}
	
	@Override
	public void close() {
		if(cache != null) {
			try { cache.close(); }
			catch(Exception e) { e.printStackTrace(); }
			cache = null;
		}
	}
	
	@Override
	public void getModifiedTime(String domain, BiConsumer<AssetLocation, FileTime> accept) {
		try {
			try(FileSystem system = FileSystems.newFileSystem(baseFolder)) {
				Path start = system.getPath("assets");
				for(Path path : IterableWrapper.wrap(Files.walk(start.resolve(domain)).filter(Files::isRegularFile).iterator())) {
					accept.accept(AssetLocation.of(domain, start.relativize(path).toString().replace("\\", "/")), Files.getLastModifiedTime(path));
				}
			}
		}
		catch(IOException e) { e.printStackTrace(); }
	}
	
	protected FileSystem getReference() throws IOException {
		if(cache == null) cache = FileSystems.newFileSystem(baseFolder);
		return cache;
	}
	
	@Override
	public List<String> getDomains() {
		List<String> domains = new ObjectArrayList<>();
		try(FileSystem system = FileSystems.newFileSystem(baseFolder)) {
			try(DirectoryStream<Path> dirs = Files.newDirectoryStream(system.getPath("assets"))) {
				for(Path path : dirs) {
					String s = path.getFileName().toString();
					domains.add(s.substring(0, s.length()));
				}
			}
			catch(Exception e) {
				e.printStackTrace();
			}
		}
		catch(Exception e) {
			e.printStackTrace();
		}
		return domains;
	}
	
	@Override
	public IAsset getAsset(AssetLocation location) {
		try {
			Path path = getReference().getPath(location.actualLocation());
			return Files.exists(path) ? new SimpleAsset(location, this, path) : null;
		}
		catch(Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	@Override
	public void gatherAssets(AssetLocation folder, BiConsumer<AssetLocation, IAsset> result) {
		try {
			FileSystem system = getReference();
			Path start = system.getPath(folder.actualLocation());
			if(Files.notExists(start)) return;
			try(Stream<Path> stream = Files.walk(start).filter(Files::isRegularFile)) {
				for(Path path : IterableWrapper.wrap(stream.iterator())) {
					AssetLocation location = folder.subAsset(start.relativize(path).toString().replace("\\", "/"));
					result.accept(location, new SimpleAsset(location, this, path));
				}
			}
			catch(IOException e) {
				e.printStackTrace();
			}
		}
		catch(Exception e) {
			e.printStackTrace();
		}
	}
}