
package de.ivu.elect.business.security;

import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;

import javax.annotation.Nullable;

import de.ivu.elect.business.lokalisierung.entity.LokalisierungLocale;


import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;

public enum Customer {

  TEST {
    @Override
    public String getBezeichnung() {
      return "Test";
    }
  },
  MINIMAL {
    @Override
    public String getBezeichnung() {
      return "Minimales System";
    }
  },
  DOKUMENTENGENERATOR {
    @Override
    public String getBezeichnung() {
      return "Dokumentengenerator";
    }
  },
  DOKUMENTENGENERATOR_WOPI(DOKUMENTENGENERATOR) {
    @Override
    public String getBezeichnung() {
      return "Dokumentengenerator (Wopi)";
    }
  },
  SKRIPT_CONSOLE_SUPPORT {
    @Override
    public String getBezeichnung() {
      return "Skript Console";
    }
  },
  VIRUS_SCAN_SUPPORT {
    @Override
    public String getBezeichnung() {
      return "Virus scan";
    }
  },
  BASE(MINIMAL, DOKUMENTENGENERATOR /* , ELECT-12546 SKRIPT_CONSOLE_SUPPORT */) {
    @Override
    public String getBezeichnung() {
      return "Basis Wahl-System";
    }

  },
  ACTIVE_DIRECTORY_SUPPORT(BASE) {
    @Override
    public String getBezeichnung() {
      return "Active Directory Unterstützung";
    }
  },
  TFA_SUPPORT(BASE) {
    @Override
    public String getBezeichnung() {
      return "TFA Unterstützung";
    }

  },
  TAG_SUPPORT(MINIMAL) {
    @Override
    public String getBezeichnung() {
      return "Tag-Support";
    }
  },
  DASHBOARD(MINIMAL) {
    @Override
    public String getBezeichnung() {
      return "Dashboard";
    }
  },
  DASHBOARD_NEWS(DASHBOARD) {
    @Override
    public String getBezeichnung() {
      return "Dashboard News";
    }
  },
  COMMON(BASE) {
    @Override
    public String getBezeichnung() {
      return "WOS-WAS-WUS Common";
    }
  },
  STRASSENVERZEICHNIS(COMMON) {
    @Override
    public String getBezeichnung() {
      return "Straßenverzeichnis";
    }
  },
  AUFGABENVERWALTUNG(COMMON) {
    @Override
    public String getBezeichnung() {
      return "Aufgabenverwaltung";
    }
  },
  MANDANT_EXCHANGE(BASE) {
    @Override
    public String getBezeichnung() {
      return "Mandant-Export";
    }
  },

  MANDANT_INIT /*ELECT-15403*/(BASE) {
    @Override
    public String getBezeichnung() {
      return "Mandant-Init";
    }
  },

  PERSONENREGISTER {
    @Override
    public String getBezeichnung() {
      return "Personenregister";
    }
  },

  COMMON_INTERFACES_MESO(COMMON, PERSONENREGISTER) {
    @Override
    public String getBezeichnung() {
      return "Common Interfaces Meso";
    }
  },
  COMMON_INTERFACES_OK_KOMM_XOEV(COMMON, PERSONENREGISTER) {
    @Override
    public String getBezeichnung() {
      return "Common Interfaces OK.KOMM";
    }
  },
  COMMON_INTERFACES_XTA_XMELD(COMMON, PERSONENREGISTER) {
    @Override
    public String getBezeichnung() {
      return "Common Interfaces XTA XMeld";
    }
  },
  COMMON_INTERFACES_DVDV_PERSONENREGISTER(COMMON, PERSONENREGISTER) {
    @Override
    public String getBezeichnung() {
      return "Common Interfaces DVDV Personenregister";
    }
  },
  // Modul elect-base-extension-mail hinzufügen!
  MAIL_SUPPORT() {
    @Override
    public String getBezeichnung() {
      return "E-Mail-Support";
    }
  },
  CORE(COMMON) {
    @Override
    public String getBezeichnung() {
      return "WAS-WUS Common";
    }
  },
  WUS(CORE) {
    @Override
    public String getBezeichnung() {
      return "Wus";
    }

    @Override
    protected boolean isWusInternal() {
      return true;
    }
  },
  WAS(CORE) {
    @Override
    public String getBezeichnung() {
      return "Was";
    }

    @Override
    protected boolean isWasInternal() {
      return true;
    }
  },
  REPLIKATION_SUPPORT(WAS) {
    @Override
    public String getBezeichnung() {
      return "Replikation Support";
    }
  },
  STIMMENUEBERGABE_SUPPORT(WAS) {
    @Override
    public String getBezeichnung() {
      return "Stimmenübergabe Support";
    }
  },
  WES(MINIMAL, DASHBOARD, DOKUMENTENGENERATOR) {
    @Override
    public String getBezeichnung() {
      return "Wes";
    }

    @Override
    public boolean isMandantUnterstuetzt() {
      return false; // nicht vorgesehen
    }

    @Override
    protected boolean isWesInternal() {
      return true;
    }
  },
  WOS(COMMON, MAIL_SUPPORT, TAG_SUPPORT) {
    @Override
    public String getBezeichnung() {
      return "Wos";
    }

    @Override
    protected boolean isWosInternal() {
      return true;
    }
  },
  WVZ(BASE) {
    @Override
    public String getBezeichnung() {
      return "Wvz";
    }

    @Override
    public boolean isMandantUnterstuetzt() {
      return false; // nicht vorgesehen
    }

    @Override
    protected boolean isWvzInternal() {
      return true;
    }
  },
  WAS_STIMMZETTEL_EINZELERFASSUNG(WAS) {
    @Override
    public String getBezeichnung() {
      return "Stimmzetteleinzelerfassung im WAS";
    }
  },
  WES_UNTERSTUETZUNG(WAS_STIMMZETTEL_EINZELERFASSUNG) {
    @Override
    public String getBezeichnung() {
      return "WES-Funktionalitäten im WAS";
    }
  },
  PRAESENTATION_WUS(WUS) {
    @Override
    public String getBezeichnung() {
      return "Präsentation im WUS vorhanden";
    }
  },
  PRAESENTATION_WAS(WAS) {
    @Override
    public String getBezeichnung() {
      return "Präsentation im WAS vorhanden";
    }
  },
  PERSONENPRUEFUNG(COMMON) {
    @Override
    public String getBezeichnung() {
      return "Personenprüfung Common";
    }
  },
  PERSONENPRUEFUNG_CORE(PERSONENPRUEFUNG, CORE) {
    @Override
    public String getBezeichnung() {
      return "Personenprüfung Core";
    }
  },
  PERSONENPRUEFUNG_WOS(PERSONENPRUEFUNG, WOS) {
    @Override
    public String getBezeichnung() {
      return "Personenprüfung WOS";
    }
  },
  WVP_ANBINDUNG(CORE) {
    @Override
    public String getBezeichnung() {
      return "Wvp-Anbindung";
    }
  },
  DESTATIS_COMMON(COMMON, TFA_SUPPORT, VIRUS_SCAN_SUPPORT) {
    @Override
    protected String getJiraProjektIdInternal() {
      return "10390";
    }

    @Override
    public String getBezeichnung() {
      return "Destatis " + COMMON.getBezeichnung();
    }
  },
  DESTATIS_WUS(DESTATIS_COMMON, WUS, WVP_ANBINDUNG, PERSONENPRUEFUNG_CORE) {
    @Override
    public String getBezeichnung() {
      return "Destatis " + WUS.getBezeichnung();
    }

    @Override
    public Collection<LokalisierungLocale> getUnterstuetzteSprachen() {
      return SPRACHEN_DESTATIS;
    }
  },
  DESTATIS_WUS_EXTERN(DESTATIS_WUS) {
    @Override
    public String getBezeichnung() {
      return DESTATIS_WUS.getBezeichnung() + " (extern)";
    }

    @Override
    public Collection<LokalisierungLocale> getUnterstuetzteSprachen() {
      return SPRACHEN_DESTATIS;
    }
  },
  DESTATIS_WAS(DESTATIS_COMMON, WAS, REPLIKATION_SUPPORT) {
    @Override
    public String getBezeichnung() {
      return "Destatis " + WAS.getBezeichnung();
    }

    @Override
    public Collection<LokalisierungLocale> getUnterstuetzteSprachen() {
      return SPRACHEN_DESTATIS;
    }
  },

  MUC_BASE(BASE) {
    @Override
    public String getBezeichnung() {
      return "München " + BASE.getBezeichnung();
    }
  },
  MUC_COMMON(MUC_BASE, COMMON, PERSONENREGISTER) {
    @Override
    protected String getJiraProjektIdInternal() {
      return "11685";
    }

    @Override
    public String getBezeichnung() {
      return "München " + COMMON.getBezeichnung();

    }
  },
  MUC_CORE(MUC_COMMON) {
    @Override
    public String getBezeichnung() {
      return "München " + CORE.getBezeichnung();
    }
  },
  MUC_WUS(MUC_CORE, WUS, WVP_ANBINDUNG, PRAESENTATION_WUS, PERSONENPRUEFUNG_CORE) {
    @Override
    public String getBezeichnung() {
      return "München " + WUS.getBezeichnung();
    }

    @Override
    public Collection<LokalisierungLocale> getUnterstuetzteSprachen() {
      return SPRACHEN_MUC;
    }
  },
  MUC_WAS(MUC_CORE, WAS, /* WES_UNTERSTUETZUNG, */ PRAESENTATION_WAS, STIMMENUEBERGABE_SUPPORT /* ELECT-12062 */) {
    @Override
    public String getBezeichnung() {
      return "München " + WAS.getBezeichnung();
    }

    @Override
    public Collection<LokalisierungLocale> getUnterstuetzteSprachen() {
      return SPRACHEN_MUC;
    }
  },
  MUC_WOS(MUC_COMMON, WOS, PERSONENPRUEFUNG_WOS) {
    @Override
    public String getBezeichnung() {
      return "München " + WOS.getBezeichnung();
    }

    @Override
    public Collection<LokalisierungLocale> getUnterstuetzteSprachen() {
      return SPRACHEN_MUC;
    }
  },
  MUC_WVZ(MUC_BASE, WVZ) {
    @Override
    public String getBezeichnung() {
      return "München " + WVZ.getBezeichnung();
    }

    @Override
    public Collection<LokalisierungLocale> getUnterstuetzteSprachen() {
      return SPRACHEN_MUC;
    }
  },

  DD_COMMON(COMMON, COMMON_INTERFACES_MESO, ACTIVE_DIRECTORY_SUPPORT) {
    @Override
    protected String getJiraProjektIdInternal() {
      return "12295";
    }

    @Override
    public String getBezeichnung() {
      return "Dresden " + COMMON.getBezeichnung();
    }
  },
  DD_CORE(DD_COMMON) {
    @Override
    protected String getJiraProjektIdInternal() {
      return "12295";
    }

    @Override
    public String getBezeichnung() {
      return "Dresden " + COMMON.getBezeichnung();
    }
  },
  DD_WUS(DD_CORE, WUS, PRAESENTATION_WUS, PERSONENPRUEFUNG_CORE) {
    @Override
    public String getBezeichnung() {
      return "Dresden " + WUS.getBezeichnung();
    }

    @Override
    public Collection<LokalisierungLocale> getUnterstuetzteSprachen() {
      return SPRACHEN_DD;
    }
  },
  DD_WAS(DD_CORE, WAS, PRAESENTATION_WAS, STIMMENUEBERGABE_SUPPORT /*ELECT-12909*/) {
    @Override
    public String getBezeichnung() {
      return "Dresden " + WAS.getBezeichnung();
    }

    @Override
    public Collection<LokalisierungLocale> getUnterstuetzteSprachen() {
      return SPRACHEN_DD;
    }
  },
  DD_WOS(DD_COMMON, WOS, PERSONENPRUEFUNG_WOS) {
    @Override
    public String getBezeichnung() {
      return "Dresden " + WOS.getBezeichnung();
    }

    @Override
    public Collection<LokalisierungLocale> getUnterstuetzteSprachen() {
      return SPRACHEN_DD;
    }
  },
  SL_COMMON(COMMON) {
    @Override
    protected String getJiraProjektIdInternal() {
      return "TODO";
    }

    @Override
    public String getBezeichnung() {
      return "Saarland " + COMMON.getBezeichnung();
    }
  },
  SL_WUS(SL_COMMON, WUS, PRAESENTATION_WUS, PERSONENPRUEFUNG_CORE) {
    @Override
    public String getBezeichnung() {
      return "Saarland " + WUS.getBezeichnung();
    }

    @Override
    public Collection<LokalisierungLocale> getUnterstuetzteSprachen() {
      return SPRACHEN_SL;
    }
  },
  SL_WUS_EXTERN(SL_WUS, WVP_ANBINDUNG) {
    @Override
    public String getBezeichnung() {
      return SL_WUS.getBezeichnung() + " (extern)";
    }
  },

  SL_WAS(SL_COMMON, WAS, PRAESENTATION_WAS, REPLIKATION_SUPPORT, STIMMENUEBERGABE_SUPPORT) {
    @Override
    public String getBezeichnung() {
      return "Saarland " + WAS.getBezeichnung();
    }

    @Override
    public Collection<LokalisierungLocale> getUnterstuetzteSprachen() {
      return SPRACHEN_SL;
    }
  },
  KOM_COMMON(COMMON, COMMON_INTERFACES_MESO, COMMON_INTERFACES_OK_KOMM_XOEV, COMMON_INTERFACES_XTA_XMELD, COMMON_INTERFACES_DVDV_PERSONENREGISTER,
      DASHBOARD_NEWS, MANDANT_EXCHANGE,
      VIRUS_SCAN_SUPPORT) {
    @Override
    public String getBezeichnung() {
      return "KOM " + COMMON.getBezeichnung();
    }

  },
  // ELECT-6886 Das WAS für KOM umfasst alle WUS-Funktionalitäten
  KOM_WAS(KOM_COMMON, WAS, WUS, PRAESENTATION_WUS, PRAESENTATION_WAS, STIMMENUEBERGABE_SUPPORT/* ELECT-12380 */, PERSONENPRUEFUNG_CORE) {
    @Override
    public String getBezeichnung() {
      return "KOM " + WAS.getBezeichnung();
    }

    @Override
    public Collection<LokalisierungLocale> getUnterstuetzteSprachen() {
      return SPRACHEN_KOM;
    }

    @Override
    protected boolean isWusInternal() {
      return super.isWusInternal(); // KOM ist gleichzeitig ein WUS
    }

  },
  KOM_WES(WES) {
    @Override
    public String getBezeichnung() {
      return "KOM " + WES.getBezeichnung();
    }

    @Override
    public Collection<LokalisierungLocale> getUnterstuetzteSprachen() {
      return SPRACHEN_KOM;
    }
  },
  KOM_WOS(KOM_COMMON, WOS, PERSONENPRUEFUNG_WOS) {
    @Override
    public String getBezeichnung() {
      return "KOM " + WOS.getBezeichnung();
    }

    @Override
    public Collection<LokalisierungLocale> getUnterstuetzteSprachen() {
      return SPRACHEN_KOM;
    }
  },
  KOM_BE_WAS(KOM_WAS, TFA_SUPPORT, STIMMENUEBERGABE_SUPPORT /* ELECT-12062 */, STRASSENVERZEICHNIS/*ELECTBB-572*/) {
    @Override
    public String getBezeichnung() {
      return KOM_WAS.getBezeichnung() + " BE";
    }
  },
  KOM_BB_WOS(KOM_WOS, TFA_SUPPORT, MANDANT_INIT /*ELECT-15403*/) {
    @Override
    public String getBezeichnung() {
      return KOM_WOS.getBezeichnung() + " BB";
    }
  },

  KOM_BB_WAS(KOM_WAS, TFA_SUPPORT, STIMMENUEBERGABE_SUPPORT/* ELECT-12062 */, MANDANT_INIT /*ELECT-15403*/) {
    @Override
    public String getBezeichnung() {
      return KOM_WAS.getBezeichnung() + " BB";
    }
  },
  KOM_BY_ALL_WAS(KOM_WAS, WES_UNTERSTUETZUNG, WAS_STIMMZETTEL_EINZELERFASSUNG, STIMMENUEBERGABE_SUPPORT, MANDANT_INIT /*ELECT-15403*/) {
    @Override
    public String getBezeichnung() {
      return KOM_WAS.getBezeichnung() + " BY";
    }
  },
  KOM_BY_ALL_WES(KOM_WES) {
    @Override
    public String getBezeichnung() {
      return KOM_WES.getBezeichnung() + " BY";
    }
  },
  KOM_BY_ALL_WOS(KOM_WOS, MANDANT_INIT /*ELECT-15403*/) {
    @Override
    public String getBezeichnung() {
      return KOM_WOS.getBezeichnung() + " BY";
    }
  },

  KOM_BY_WOS(KOM_BY_ALL_WOS) {
    @Override
    public String getBezeichnung() {
      return KOM_WOS.getBezeichnung() + " BY Komuna";
    }
  },
  KOM_BY_WAS(KOM_BY_ALL_WAS) {
    @Override
    public String getBezeichnung() {
      return KOM_WAS.getBezeichnung() + " BY Komuna";
    }
  },
  KOM_BY_WES(KOM_BY_ALL_WES) {
    @Override
    public String getBezeichnung() {
      return KOM_WES.getBezeichnung() + " BY Komuna";
    }
  },
  KOM_BY_AKDB_WOS(KOM_BY_ALL_WOS, AUFGABENVERWALTUNG) {
    @Override
    public String getBezeichnung() {
      return KOM_WOS.getBezeichnung() + " BY AKDB";
    }
  },
  KOM_BY_AKDB_WAS(KOM_BY_ALL_WAS, AUFGABENVERWALTUNG) {
    @Override
    public String getBezeichnung() {
      return KOM_WAS.getBezeichnung() + " BY AKDB";
    }
  },
  KOM_BY_AKDB_WES(KOM_BY_ALL_WES) {
    @Override
    public String getBezeichnung() {
      return KOM_WES.getBezeichnung() + " BY AKDB";
    }
  },
  KOM_MV_WOS(KOM_WOS) {
    @Override
    public String getBezeichnung() {
      return KOM_WOS.getBezeichnung() + " MV";
    }
  },
  KOM_MV_WAS(KOM_WAS) {
    @Override
    public String getBezeichnung() {
      return KOM_WAS.getBezeichnung() + " MV";
    }
  },
  KOM_NI_WOS(KOM_WOS, ACTIVE_DIRECTORY_SUPPORT) {
    @Override
    public String getBezeichnung() {
      return KOM_WOS.getBezeichnung() + " NI";
    }
  },
  KOM_NI_WAS(KOM_WAS, ACTIVE_DIRECTORY_SUPPORT) {
    @Override
    public String getBezeichnung() {
      return KOM_WAS.getBezeichnung() + " NI";
    }
  },
  KOM_RP_WOS(KOM_WOS, AUFGABENVERWALTUNG/*ELECTKOM-1107*/, MANDANT_INIT /*ELECT-15403*/) {
    @Override
    public String getBezeichnung() {
      return KOM_WOS.getBezeichnung() + " RP";
    }
  },
  KOM_RP_WAS(KOM_WAS, WES_UNTERSTUETZUNG/* ELECTKOM-1107 */, /* DOKUMENTENGENERATOR_WOPI,*/ AUFGABENVERWALTUNG /*ELECT-6559*/, MANDANT_INIT /*ELECT-15403*/,
      TFA_SUPPORT/*ELECTKOM-2472*/) {
    @Override
    public String getBezeichnung() {
      return KOM_WAS.getBezeichnung() + " RP";
    }
  },
  KOM_RP_WES(KOM_WES) {
    @Override
    public String getBezeichnung() {
      return KOM_WES.getBezeichnung() + " RP";
    }
  },
  KOM_SH_WOS(KOM_WOS, ACTIVE_DIRECTORY_SUPPORT /* ELECT-11850 */, MANDANT_INIT /*ELECT-15403*/) {
    @Override
    public String getBezeichnung() {
      return KOM_WOS.getBezeichnung() + " SH";
    }
  },
  KOM_SH_WAS(KOM_WAS, ACTIVE_DIRECTORY_SUPPORT /* ELECT-11850 */, MANDANT_INIT /*ELECT-15403*/) {
    @Override
    public String getBezeichnung() {
      return KOM_WAS.getBezeichnung() + " SH";
    }
  },
  KOM_SH_WAS_EXTERN(KOM_SH_WAS, WVP_ANBINDUNG) {
    @Override
    public String getBezeichnung() {
      return KOM_SH_WAS.getBezeichnung() + " (extern)";
    }
  },
  KOM_HE_WAS(KOM_WAS, ACTIVE_DIRECTORY_SUPPORT /* ELECT-11850 */, MANDANT_INIT /*ELECT-15403*/) {
    @Override
    public String getBezeichnung() {
      return KOM_WAS.getBezeichnung() + " HE";
    }
  },
  KOM_HE_WAS_EXTERN(KOM_HE_WAS, WVP_ANBINDUNG) {
    @Override
    public String getBezeichnung() {
      return KOM_HE_WAS.getBezeichnung() + " (extern)";
    }
  },
  KOM_ST_WOS(KOM_WOS, ACTIVE_DIRECTORY_SUPPORT) {
    @Override
    public String getBezeichnung() {
      return KOM_WOS.getBezeichnung() + " ST";
    }
  },
  KOM_ST_WAS(KOM_WAS, ACTIVE_DIRECTORY_SUPPORT) {
    @Override
    public String getBezeichnung() {
      return KOM_WAS.getBezeichnung() + " ST";
    }
  },
  KOM_SN_WOS(KOM_WOS, ACTIVE_DIRECTORY_SUPPORT) {
    @Override
    public String getBezeichnung() {
      return KOM_WOS.getBezeichnung() + " SN";
    }
  },
  KOM_SN_WAS(KOM_WAS, ACTIVE_DIRECTORY_SUPPORT) {
    @Override
    public String getBezeichnung() {
      return KOM_WAS.getBezeichnung() + " SN";
    }
  },

  KOM_HH_WAS(KOM_WAS, ACTIVE_DIRECTORY_SUPPORT /* ELECT-11850 */) {
    @Override
    public String getBezeichnung() {
      return KOM_WAS.getBezeichnung() + " HH";
    }
  },
  KOM_HH_WOS(KOM_WOS, ACTIVE_DIRECTORY_SUPPORT /* ELECT-11850 */) {
    @Override
    public String getBezeichnung() {
      return KOM_WOS.getBezeichnung() + " HH";
    }
  },
  KOM_HB_WAS(KOM_WAS, ACTIVE_DIRECTORY_SUPPORT /* ELECT-11850 */, WVP_ANBINDUNG /* ELECT-14963 */, WES_UNTERSTUETZUNG /*ELECTKOM-2145*/) {
    @Override
    public String getBezeichnung() {
      return KOM_WAS.getBezeichnung() + " HB";
    }
  },
  KOM_HB_WOS(KOM_WOS, ACTIVE_DIRECTORY_SUPPORT /* ELECT-11850 */) {
    @Override
    public String getBezeichnung() {
      return KOM_WOS.getBezeichnung() + " HB";
    }
  },
  KOM_HB_WES(KOM_WES) {
    @Override
    public String getBezeichnung() {
      return KOM_WES.getBezeichnung() + " HB";
    }
  },
  KOM_TH_WAS(KOM_WAS, ACTIVE_DIRECTORY_SUPPORT) {
    @Override
    public String getBezeichnung() {
      return KOM_WAS.getBezeichnung() + " TH";
    }
  },

  KOM_TH_WOS(KOM_WOS, ACTIVE_DIRECTORY_SUPPORT) {
    @Override
    public String getBezeichnung() {
      return KOM_WOS.getBezeichnung() + " TH";
    }
  },

  NL_COMMON(COMMON) {
    @Override
    protected String getJiraProjektIdInternal() {
      return "TODO";
    }

    @Override
    public String getBezeichnung() {
      return "Niederlande " + BASE.getBezeichnung();
    }
  },
  NL_WUS(NL_COMMON, WUS, WVP_ANBINDUNG, PERSONENREGISTER, PERSONENPRUEFUNG_CORE) {
    @Override
    public String getBezeichnung() {
      return "Niederlande " + WUS.getBezeichnung();
    }

    @Override
    public Collection<LokalisierungLocale> getUnterstuetzteSprachen() {
      return SPRACHEN_NL;
    }
  },
  NL_WAS(NL_COMMON, WAS) {
    @Override
    public String getBezeichnung() {
      return "Niederlande " + WAS.getBezeichnung();
    }

    @Override
    public Collection<LokalisierungLocale> getUnterstuetzteSprachen() {
      return SPRACHEN_NL;
    }
  };

  private static final Collection<LokalisierungLocale> NUR_DEUTSCH = singletonList(LokalisierungLocale.DEUTSCH);

  private static final Collection<LokalisierungLocale> DEUTSCH_ENGLISCH = asList(LokalisierungLocale.DEUTSCH, LokalisierungLocale.ENGLISCH);

  private static final Collection<LokalisierungLocale> SPRACHEN_MUC = /* NUR_DEUTSCH; */ DEUTSCH_ENGLISCH; // für Screenshots ocs

  private static final Collection<LokalisierungLocale> SPRACHEN_KOM = /* NUR_DEUTSCH; */ DEUTSCH_ENGLISCH; // Irgendwelche Demos für WUS/WAS zusammen

  private static final Collection<LokalisierungLocale> SPRACHEN_DD = NUR_DEUTSCH;

  private static final Collection<LokalisierungLocale> SPRACHEN_BB = NUR_DEUTSCH;

  private static final Collection<LokalisierungLocale> SPRACHEN_DESTATIS = NUR_DEUTSCH;

  private static final Collection<LokalisierungLocale> SPRACHEN_SL = NUR_DEUTSCH;

  private static final Collection<LokalisierungLocale> SPRACHEN_NL = asList(LokalisierungLocale.NIEDERLAENDISCH, LokalisierungLocale.DEUTSCH);

  private final List<Customer> parents = new ArrayList<>();

  Customer(Customer... parents) {
    if (parents != null) {
      this.parents.addAll(asList(parents));
    }
  }

  public List<Customer> getParents() {
    return parents;
  }

  /**
   * @return The complete customer-hierarchy inclusive itself
   */
  public Collection<Customer> getContainedCustomers() {
    Collection<Customer> result = new HashSet<>();

    result.add(this);

    for (Customer parent : getParents()) {
      result.addAll(parent.getContainedCustomers());
    }

    return result;
  }

  public String getJiraProjektId() {
    if (getJiraProjektIdInternal() != null) {
      return getJiraProjektIdInternal();
    }

    return getParents().stream().filter(customer -> customer.getJiraProjektIdInternal() != null).findFirst().map(Customer::getJiraProjektIdInternal)
        .orElse(null);
  }

  @Nullable
  protected String getJiraProjektIdInternal() {
    return null;
  }

  /**
   * Name des Kunden, keine Lokalisierung, weil diese bei Verwendung noch nicht initialisiert ist
   */
  public abstract String getBezeichnung();

  public boolean containsAny(Collection<Customer> customers) {
    Collection<Customer> others = new HashSet<>(getContainedCustomers());
    others.retainAll(customers);

    return !others.isEmpty();
  }

  public boolean contains(Customer one, Customer... more) {
    Collection<Customer> others = new HashSet<>(asList(more));
    others.add(one);

    return getContainedCustomers().containsAll(others);
  }

  public Collection<LokalisierungLocale> getUnterstuetzteSprachen() {
    return EnumSet.allOf(LokalisierungLocale.class);
  }

  public boolean isMandantUnterstuetzt() {
    return getContainedCustomers().stream().filter(containedCustomer -> !this.equals(containedCustomer)).allMatch(Customer::isMandantUnterstuetzt);
  }

  public boolean isWas() {
    return getContainedCustomers().stream().anyMatch(Customer::isWasInternal);
  }

  protected boolean isWasInternal() {
    return false;
  }

  public boolean isWos() {
    return getContainedCustomers().stream().anyMatch(Customer::isWosInternal);
  }

  protected boolean isWosInternal() {
    return false;
  }

  public boolean isWus() {
    return getContainedCustomers().stream().anyMatch(Customer::isWusInternal);
  }

  protected boolean isWusInternal() {
    return false;
  }

  public boolean isWes() {
    return getContainedCustomers().stream().anyMatch(Customer::isWesInternal);
  }

  protected boolean isWesInternal() {
    return false;
  }

  public boolean isWvz() {
    return getContainedCustomers().stream().anyMatch(Customer::isWvzInternal);
  }

  protected boolean isWvzInternal() {
    return false;
  }

}
