package com.eactive.eai.rms.onl.loader.service;

import com.eactive.eai.rms.common.converter.ElinkObjectMapper;
import com.eactive.eai.rms.onl.loader.service.enm.ResourceType;
import com.eactive.eai.rms.onl.loader.vo.RuleFileResource;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.apache.log4j.Logger;

import javax.annotation.PostConstruct;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public abstract class DeployResourceDownloadService {

	protected final Logger logger = Logger.getLogger(getClass());

	public abstract boolean supportsType(String serviceType);

	public abstract RuleFileResource getResource(String serviceType, ResourceType resourceType, String resourceName) throws Exception;

	public abstract byte[] getResourcesZip(Map<String, String>[] paramGridRows) throws Exception;

//	public abstract byte[] generateZipWithFileSystem(String serviceType) throws IOException;

    protected final ElinkObjectMapper mapper;

    DeployResourceDownloadService() {
        mapper = new ElinkObjectMapper();
        mapper.enable(SerializationFeature.WRITE_SELF_REFERENCES_AS_NULL);
        mapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        mapper.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
        mapper.writerWithDefaultPrettyPrinter();
    }

	protected byte[] pathToZipFile(Path folderPath) throws IOException {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		try (ZipOutputStream zos = new ZipOutputStream(baos)) {
			Files.walk(folderPath).filter(path -> !Files.isDirectory(path)).forEach(path -> {
				ZipEntry zipEntry = new ZipEntry(folderPath.relativize(path).toString());
				try {
					zos.putNextEntry(zipEntry);
					Files.copy(path, zos);
					zos.closeEntry();
				} catch (IOException e) {
					throw new RuntimeException("Error packaging file: " + path, e);
				}
			});
		}
		return baos.toByteArray();
	}

	protected void deleteDirectoryRecursively(Path path) throws IOException {
		Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
			@Override
			public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
				Files.delete(file);
				return FileVisitResult.CONTINUE;
			}

			@Override
			public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
				Files.delete(dir);
				return FileVisitResult.CONTINUE;
			}
		});
	}

}