package de.ivu.elect.business.security.control;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.security.UseCasePermission;


import static de.ivu.elect.business.ElectSystemProperties.ELECT_USECASE_ALLOWLIST_GLOBAL_DEAKTIVIERT;

public interface UseCasePermissionAllowlist {

  Logger LOG = LoggerFactory.getLogger(UseCasePermissionAllowlist.class);

  Set<UseCasePermission> ALLOWLIST = read("usecase_allowlist.txt", false);

  Set<UseCasePermission> DENYLIST = read("usecase_denylist.txt", false);

  boolean DEAKTIVIERT =
      (ALLOWLIST.isEmpty() && DENYLIST.isEmpty()) || Boolean.TRUE.toString().equalsIgnoreCase(System.getProperty(ELECT_USECASE_ALLOWLIST_GLOBAL_DEAKTIVIERT));

  static Set<UseCasePermission> read(String resourceName, boolean mustExists) {
    try {
      try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(resourceName)) {
        if (is == null) {
          if (mustExists) {
            throw new IllegalStateException("Resource nicht gefunden: '" + resourceName + "'");
          }
          return Collections.emptySet();
        }
        Set<UseCasePermission> set = new HashSet<>();
        try (BufferedReader buffer = new BufferedReader(new InputStreamReader(is))) {
          buffer.lines().filter(UseCasePermissionAllowlist::matches).map(UseCasePermission::valueOf).forEach(set::add);
        }
        if (set.isEmpty()) {
          return Collections.emptySet();
        }
        return EnumSet.copyOf(set);
      }
    } catch (IOException e) {
      throw new RuntimeException(e.getMessage(), e);
    }
  }

  static boolean matches(String line) {
    if (StringUtils.isBlank(line)) {
      return false;
    }
    // Kommentare ignorieren
    if (line.startsWith("#") || line.startsWith("/")) {
      return false;
    }

    try {
      UseCasePermission.valueOf(line);
      return true;
    } catch (Exception e) {
      LOG.warn("Unbekannte UseCasePermission: '" + line + "'");
      return false;
    }

  }

}
