package com.airlock.iam.plugin.framework.misc.template;

import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.plugin.api.config.LogTypes;
import com.airlock.iam.plugin.framework.application.service.ConfigReader;
import com.airlock.iam.plugin.framework.domain.model.MedusaConfigurationElement;
import com.airlock.iam.plugin.framework.misc.PluginFramework;
import com.airlock.iam.system.config.ConfigFormat;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

public class ConfigTemplateService {
   private static final String CONFIG_FILE_GLOB = "*.xml";
   private static final ELogger LOG = ELoggerFactory.getLogger(ConfigTemplateService.class);
   private final Path templateDirectory;

   public ConfigTemplateService(Path templateDirectory) {
      Objects.requireNonNull(templateDirectory, "template directory null");
      this.templateDirectory = templateDirectory;
   }

   public List<ConfigurationTemplate> listTemplates() {
      if (!Files.isDirectory(this.templateDirectory)) {
         return Collections.emptyList();
      }

      try (DirectoryStream<Path> files = Files.newDirectoryStream(this.templateDirectory, "*.xml")) {
         List<ConfigurationTemplate> templates = new ArrayList<>();
         files.forEach(candidate -> this.addTemplateMetaDataFromConfigFileCandidate(templates, candidate.toFile()));
         Collections.sort(templates);
         return templates;
      } catch (IOException e) {
         LOG.warn(LogTypes.CONFIGURATION_ERROR, "Error accessing config templates: " + e.getMessage(), e);
         return Collections.emptyList();
      }
   }

   private void addTemplateMetaDataFromConfigFileCandidate(List<ConfigurationTemplate> result, File candidate) {
      try {
         MedusaConfigurationElement config = this.readConfigFile(candidate);
         if (config.isTemplate()) {
            result.add(new ConfigurationTemplate(candidate, config.getTemplateMetaData().orElseThrow(IllegalStateException::new)));
         }
      } catch (ConfigReader.ConfigLoaderException e) {
         LOG.info(
            LogTypes.CONFIGURATION_ERROR, "Ignoring possible configuration template file \"" + candidate.getAbsolutePath() + "\" because: " + e.getMessage(), e
         );
      }
   }

   private MedusaConfigurationElement readConfigFile(File candidate) throws ConfigReader.ConfigLoaderException {
      try (InputStream in = Files.newInputStream(candidate.toPath())) {
         return PluginFramework.getConfigReader(ConfigFormat.XML_FORMAT).read(in);
      } catch (IOException e) {
         throw new ConfigReader.ConfigLoaderException(e);
      }
   }
}
