
package de.ivu.elect.business.gruppe.entity;

import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

import javax.annotation.Nullable;
import javax.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.gruppe.boundary.GruppeFactory;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.jee.faces.Messages;

public class SystemGruppeEigenschaften implements Serializable {

  private static final Logger LOGGER = LoggerFactory.getLogger(SystemGruppeEigenschaften.class);

  private static final long serialVersionUID = 1L;

  @Inject
  protected transient Messages messages;

  @Inject
  protected transient GruppeFactory gruppeFactory;

  private static final Map<SystemGruppe, String> nameMap = new ConcurrentHashMap<>();

  @Nullable
  public String getName(SystemGruppe systemGruppe) {
    if (nameMap.containsKey(systemGruppe)) {
      return nameMap.get(systemGruppe);
    }

    String result = getMessage("gruppe.system.name." + systemGruppe.name());
    if (result != null) {
      nameMap.put(systemGruppe, result);
    }
    return result;
  }

  private static final Map<SystemGruppe, String> kurznameMap = new ConcurrentHashMap<>();

  @Nullable
  public String getKurzname(SystemGruppe systemGruppe) {
    if (kurznameMap.containsKey(systemGruppe)) {
      return kurznameMap.get(systemGruppe);
    }

    String result = getMessage("gruppe.system.kurzname." + systemGruppe.name());
    if (result != null) {
      kurznameMap.put(systemGruppe, result);
    }
    return result;
  }

  public String getSchluessel(SystemGruppe systemGruppe) {
    return systemGruppe.name();
  }

  private static final Map<SystemGruppe, String> farbeMap = new ConcurrentHashMap<>();

  @Nullable
  public String getFarbe(SystemGruppe systemGruppe) {
    if (farbeMap.containsKey(systemGruppe)) {
      return farbeMap.get(systemGruppe);
    }

    String result = getMessage("gruppe.system.farbe." + systemGruppe.name());
    if (result != null) {
      farbeMap.put(systemGruppe, result);
    }
    return result;
  }

  private static final Map<SystemGruppe, String> farbeExternMap = new ConcurrentHashMap<>();

  @Nullable
  public String getFarbeExtern(SystemGruppe systemGruppe) {
    if (farbeExternMap.containsKey(systemGruppe)) {
      return farbeExternMap.get(systemGruppe);
    }

    String result = getMessage("gruppe.system.farbe.extern." + systemGruppe.name());
    if (result != null) {
      farbeExternMap.put(systemGruppe, result);
    }
    return result;
  }

  private static final Map<SystemGruppe, Long> positionMap = new ConcurrentHashMap<>();

  private static final AtomicLong nextPos = new AtomicLong(1L);

  @Nullable
  public Long getPosition(SystemGruppe systemGruppe) {
    if (positionMap.containsKey(systemGruppe)) {
      return positionMap.get(systemGruppe);
    }

    Long result = null;

    String message = getMessage("gruppe.system.position." + systemGruppe.name());
    try {
      result = Long.valueOf(message);
    } catch (NumberFormatException nfe) {
      result = nextPos.getAndIncrement();
      LOGGER.warn("Keine hinterlegte Position für: " + systemGruppe + ", habe: " + message + " und verwende: " + result);
    }

    positionMap.put(systemGruppe, result);

    return result;
  }

  public boolean isGruppeEqualsSystemGruppe(AbstractGruppe gruppe, SystemGruppe systemGruppe) {
    return gruppe != null && getSchluessel(systemGruppe).equals(gruppe.getSchluessel());
  }

  public Gruppe createGruppeAusSystemGruppe(SystemGruppe systemGruppe, @Nullable Wahl wahl) {
    Gruppe gruppe = createGruppe();
    if (wahl != null) {
      gruppe.setWahl(wahl);
    }
    gruppe.setGruppeArt(GruppeArt.SYSTEM_GRUPPE);
    gruppe.setKurzname(getKurzname(systemGruppe));
    gruppe.setName(getName(systemGruppe));
    gruppe.setSchluessel(getSchluessel(systemGruppe));
    gruppe.setFarbe(getFarbe(systemGruppe));
    gruppe.setFarbeExtern(getFarbeExtern(systemGruppe));
    gruppe.setRelativePosition(getPosition(systemGruppe));

    return gruppe;
  }

  protected String getMessage(String msgKey, Object... params) {
    return messages.getMessageForMessageKey(msgKey, params);
  }

  protected Gruppe createGruppe() {
    return gruppeFactory.create();
  }
}
