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

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import javax.enterprise.inject.Specializes;

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

import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.GebietTK;
import de.ivu.elect.business.gruppe.entity.GruppeTK;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.jee.exchange.Violations;

@Specializes
public class NlGruppeImGebietGruppenGebieteValidator extends GruppeImGebietGruppenGebieteValidator {

  private static final Logger LOG = LoggerFactory.getLogger(NlGruppeImGebietGruppenGebieteValidator.class);

  @Override
  protected Set<GebietTK> behandleFehlendeGebiete(Wahl wahl, Set<GebietTK> fehlendeGebiete, Collection<Gebiet> gebiete, Collection<Gebiet> gebieteDerWahl) {
    Set<GebietTK> zubehandeln = super.behandleFehlendeGebiete(wahl, fehlendeGebiete, gebiete, gebieteDerWahl);

    if (zubehandeln.isEmpty()) {
      return zubehandeln;
    }

    Set<GebietTK> result = new HashSet<>();
    for (Gebiet gebiet : gebiete) {
      if (zubehandeln.contains(gebiet.getGebietTK())) {
        if ("alle".equalsIgnoreCase(gebiet.getNummer())) {
          LOG.warn("Gebiet 'alle' gefunden!");
          // ELECT-9765 Spezialfall "alle" => einfach oberstes Gebiet nehmen - wird hoffentlich passen
          setzeAufOberstesGebiet(gebieteDerWahl, gebiet);
        } else {
          Set<Gebiet> gebieteMitGleichemNamen = new HashSet<>();
          for (Gebiet gebietInDb : gebieteDerWahl) {
            String name = gebietInDb.getName();
            if (StringUtils.isNotBlank(name)) {
              if (name.equalsIgnoreCase(gebiet.getName())) {
                gebieteMitGleichemNamen.add(gebietInDb);
              }
            }
          }

          boolean found = false;
          if (gebieteMitGleichemNamen.size() == 1) {
            Gebiet gebietInDb = gebieteMitGleichemNamen.iterator().next();
            gebiet.setNummer(gebietInDb.getNummer());
            gebiet.setGebietsart(gebietInDb.getGebietsart());
            found = true;
          } else {
            // ELECT-9933
            for (Gebiet gebietInDb : gebieteMitGleichemNamen) {
              if (isNummerGleich(gebietInDb, gebiet)) {
                gebiet.setNummer(gebietInDb.getNummer());
                gebiet.setGebietsart(gebietInDb.getGebietsart());
                found = true;
              }
            }
          }

          if (!found) {
            // ELECT-10076 Workaround
            setzeAufOberstesGebiet(gebieteDerWahl, gebiet);
          }

        }
        if (zubehandeln.contains(gebiet.getGebietTK())) {
          result.add(gebiet.getGebietTK());
        }
      }
    }
    return result;
  }

  private void setzeAufOberstesGebiet(Collection<Gebiet> gebieteDerWahl, Gebiet gebiet) {
    for (Gebiet gebietInDb : gebieteDerWahl) {
      if (!gebietInDb.hasUebergeordnetesGebiet()) {
        gebiet.setNummer(gebietInDb.getNummer());
        gebiet.setGebietsart(gebietInDb.getGebietsart());
      }
    }
  }

  private boolean isNummerGleich(Gebiet gebietInDb, Gebiet gebiet) {

    String nummerA = gebietInDb.getNummer();
    String nummerB = gebiet.getNummer();

    if (StringUtils.isBlank(nummerA) || StringUtils.isBlank(nummerB)) {
      return false;
    }
    return nummerA.equalsIgnoreCase(nummerB) || isLongValueGleich(nummerA, nummerB);
  }

  private boolean isLongValueGleich(String nummerA, String nummerB) {
    try {
      return Long.parseLong(nummerA) == Long.parseLong(nummerB);
    } catch (Exception e) {
      return false;
    }
  }

  @Override
  protected void addGruppeFehltViolation(Violations violations, GruppeTK gruppeTK) {
   // für NL unwichtig, lenkt ab violations.add(new GruppeNichtGefundenViolation(ViolationLevel.INFO, gruppeTK));
  }
}
