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

import com.eactive.eai.common.util.UUIDGenerator;
import com.eactive.eai.rms.common.context.MonitoringContext;
import com.eactive.eai.rms.common.converter.ElinkObjectMapper;
import com.eactive.eai.rms.common.datasource.DataSourceContextHolder;
import com.eactive.eai.rms.common.datasource.DataSourceType;
import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
import com.eactive.eai.rms.onl.common.util.FileWriteUtil;
import com.eactive.eai.rms.onl.loader.dao.LoaderDao;
import com.eactive.eai.rms.onl.loader.intf.InterfaceDeployService;
import com.eactive.eai.rms.onl.loader.intf.deploy.EAIMessageDeploy;
import com.eactive.eai.rms.onl.loader.layout.LayoutDeployService;
import com.eactive.eai.rms.onl.loader.layout.deploy.LayoutDeploy;
import com.eactive.eai.rms.onl.loader.service.enm.ResourceType;
import com.eactive.eai.rms.onl.loader.transform.TransformDeployService;
import com.eactive.eai.rms.onl.loader.transform.deploy.TransformDeploy;
import com.eactive.eai.rms.onl.loader.vo.RuleFileResource;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

@Service
public class DeployResourceDownloadOnlineService extends DeployResourceDownloadService {

   @Autowired
   @Qualifier("loaderDao")
   private LoaderDao dao;

	@Autowired
	@Qualifier("monitoringContext")
	private MonitoringContext monitoringContext;

	@Autowired
   @Qualifier("deployJsonServiceOnline")
   private TransactionDeployJsonService loaderService;

   @Autowired
   private InterfaceDeployService interfaceDeployService;

   @Autowired
   private LayoutDeployService layoutDeployService;

   @Autowired
   private TransformDeployService transformDeployService;

	private ElinkObjectMapper mapper;

	@PostConstruct
	public void startup() {
		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();
	}

	@Override
	public boolean supportsType(String serviceType) {
		return Objects.requireNonNull(DataSourceTypeManager.getDataSourceType(serviceType)).isOnline();
	}

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

		DataSourceType dt = DataSourceTypeManager.getDataSourceType(serviceType.toUpperCase());
		DataSourceContextHolder.setDataSourceType(dt);

		switch (resourceType) {
		case INTERFACE:
         return getInterfaceResource(dt, resourceName);
		case LAYOUT:
         return getLayoutResource(dt, resourceName);
		case TRANSFORM:
         return getTransformResource(dt, resourceName);
		default:
			throw new IllegalArgumentException("Unexpected value: " + resourceType);
		}

	}

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

		final String tempFilePath = monitoringContext.getStringProperty(MonitoringContext.IOMAP_DOWNLOAD_PATH);

		Path tempFileUuidDirectory = Paths
				.get(tempFilePath + File.separator + UUIDGenerator.getUUID() + File.separator);
		Files.createDirectories(tempFileUuidDirectory);

		try {

			for (Map<String, String> row : paramGridRows) {

				ResourceType resourceTypeEnum = ResourceType.valueOf(row.get("resourceType").toUpperCase());
				String resourceType = row.get("resourceType");
				String resourceName = row.get("resourceName").substring(0, row.get("resourceName").lastIndexOf("."));
				String resourceApp = row.get("resourceApp");

				RuleFileResource fileContent = null;

				switch (resourceTypeEnum) {
				case INTERFACE:
               fileContent = getInterfaceResource(DataSourceContextHolder.getDataSourceType(), resourceName);
					break;
				case LAYOUT:
               fileContent = getLayoutResource(DataSourceContextHolder.getDataSourceType(), resourceName);
					break;
				case TRANSFORM:
               fileContent = getTransformResource(DataSourceContextHolder.getDataSourceType(), resourceName);
					break;
				default:
					throw new IllegalArgumentException("Unexpected value: " + resourceType);
				}

				Files.createDirectories(Paths.get(tempFileUuidDirectory + File.separator + resourceApp + File.separator
						+ resourceType + File.separator));
				Files.write(Paths.get(tempFileUuidDirectory + File.separator + resourceApp + File.separator
						+ resourceType + File.separator + fileContent.getFileName()),
						fileContent.getFileContent().getBytes());

			}

			byte[] pathToZipFile = pathToZipFile(tempFileUuidDirectory);

			return pathToZipFile;

		} finally {
			deleteDirectoryRecursively(tempFileUuidDirectory);
		}

	}

   private RuleFileResource getInterfaceResource(DataSourceType dt, String eaiSvcName) throws Exception {
      EAIMessageDeploy eaiMessageDeploy = interfaceDeployService.selectDeploy(eaiSvcName);
      String json = mapper.writeValueAsString(eaiMessageDeploy);
		return new RuleFileResource(eaiSvcName + ".txt", json);
	}

   private RuleFileResource getLayoutResource(DataSourceType dt, String loutName) throws Exception {
      LayoutDeploy layoutDeploy = layoutDeployService.selectDeploy(loutName);
      String json = mapper.writeValueAsString(layoutDeploy);
		return new RuleFileResource(loutName + ".txt", json);
	}

   private RuleFileResource getTransformResource(DataSourceType dt, String cnvsnName) throws Exception {
      TransformDeploy transformDeploy = transformDeployService.selectDeploy(cnvsnName);
      String json = mapper.writeValueAsString(transformDeploy);
		return new RuleFileResource(cnvsnName + ".txt", json);
	}

//   public byte[] generateZipWithFileSystem(String serviceType) throws IOException {
//
//      DataSourceType dt = DataSourceTypeManager.getDataSourceType(serviceType.toUpperCase());
//      DataSourceContextHolder.setDataSourceType(dt);
//
//      final String localFilePath = monitoringContext.getStringProperty(MonitoringContext.IOMAP_DOWNLOAD_PATH);
//
//      List<String> errorResourcesAlert = new ArrayList<>();
//
//      try {
//         generateAllInterfaceInLocalFilePath(dt, serviceType, localFilePath, errorResourcesAlert);
//         generateAllLayoutInLocalFilePath(dt, serviceType, localFilePath, errorResourcesAlert);
//         generateAllTransformInLocalFilePath(dt, serviceType, localFilePath, errorResourcesAlert);
//      } catch (Exception e) {
//         logger.error(String.valueOf(e));
//         throw e;
//      }
//
//      if (errorResourcesAlert.size() > 0) {
//         StringBuilder sb = new StringBuilder();
//         sb.append("Resource Validation Error:").append(System.lineSeparator());
//         errorResourcesAlert.forEach(msg -> sb.append(msg).append(System.lineSeparator()));
//         throw new RuntimeException(sb.toString());
//      }
//
//      Path folderPath = Paths.get(localFilePath + File.separator + serviceType);
//
//      byte[] file = pathToZipFile(folderPath);
//
//      deleteDirectoryRecursively(folderPath);
//
//      return file;
//   }
//
//   private void generateAllInterfaceInLocalFilePath(DataSourceType dt, String serviceType, String iomapPath,
//         List<String> errorResourcesAlert) {
//      List<LinkedHashMap> list = dao.selectTableDataLike(dt, "TSEAIHE01", "EAISvcName", "%");
//      for (int i = 0; i < list.size(); i++) {
//         LinkedHashMap lm = list.get(i);
//         try {
//            String eaiSvcName = (String) lm.get("EAISVCNAME");
//            String bzwkDstcd = ((String) lm.get("EAIBZWKDSTCD")).trim();
//            String path = iomapPath + serviceType + File.separator + bzwkDstcd + File.separator
//                  + FileWriteUtil.INTERFACE + File.separator;
//            loaderService.interfaceDownLoading(path, eaiSvcName);
//         } catch (Exception e) {
//            logger.warn(String.valueOf(lm), e);
//            errorResourcesAlert.add(e.getMessage() + " [RESOURCE]:" + lm.toString());
//         }
//      }
//   }
//
//   private void generateAllLayoutInLocalFilePath(DataSourceType dt, String serviceType, String iomapPath,
//         List<String> errorResourcesAlert) {
//      List<LinkedHashMap> list = dao.selectTableDataLike(dt, "TSEAITR07", "LoutName", "%");
//      for (int i = 0; i < list.size(); i++) {
//         LinkedHashMap lm = list.get(i);
//         try {
//            String loutName = (String) lm.get("LOUTNAME");
//            String bzwkDstcd = ((String) lm.get("EAIBZWKDSTCD")).trim();
//            String path = iomapPath + serviceType + File.separator + bzwkDstcd + File.separator
//                  + FileWriteUtil.LAYOUT + File.separator;
//            loaderService.layoutDownLoading(path, loutName);
//         } catch (Exception e) {
//            logger.warn(String.valueOf(lm), e);
//            errorResourcesAlert.add(e.getMessage() + " [RESOURCE]:" + lm.toString());
//         }
//      }
//   }
//
//   private void generateAllTransformInLocalFilePath(DataSourceType dt, String serviceType, String iomapPath, List<String> errorResourcesAlert) {
//      List<LinkedHashMap> list = dao.selectTableDataLike(dt, "TSEAITR01", "CnvsnName", "%");
//      for (int i = 0; i < list.size(); i++) {
//         LinkedHashMap lm = list.get(i);
//         try {
//            String cnvsnName = (String) lm.get("CNVSNNAME");
//            String bzwkDstcd = cnvsnName.substring(10, 13);
//            String path = iomapPath + serviceType + File.separator + bzwkDstcd + File.separator
//                  + FileWriteUtil.TRANSFORM + File.separator;
//            loaderService.transformDownLoading(path, cnvsnName);
//         } catch (Exception e) {
//            logger.warn(String.valueOf(lm), e);
//            errorResourcesAlert.add(e.getMessage() + " [RESOURCE]:" + lm.toString());
//         }
//      }
//   }

}