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

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebiet;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebietTK;
import de.ivu.elect.business.kandidatur.control.ListenkandidaturByRelativePositionComparator;
import de.ivu.elect.business.kandidatur.control.ListenkandidaturNamenUndListeTK;
import de.ivu.elect.business.kandidatur.entity.Listenkandidatur;
import de.ivu.elect.business.kandidatur.entity.ListenkandidaturTK;
import de.ivu.elect.business.stimmeingabe.control.StimmeingabeImporterHelper;

public enum StandardStimmeingabeImporterListenkandidaturErsetzenStrategie implements StimmeingabeImporterListenkandidaturErsetzenStrategie {

  NACH_TK {
    @Override
    public boolean isListenkandidaturVorhanden(Gebiet erfassungsgebiet, Map<ListenkandidaturTK, Listenkandidatur> listenkandidaturenInDbNachListenkandidaturTk, Map<ListenkandidaturNamenUndListeTK, Listenkandidatur> listenkandidaturenInDbNachNamenUndListeTk, Listenkandidatur listenkandidatur, Map<GruppeImGebietTK, GruppeImGebiet> gruppenImGebietInDb, StimmeingabeImporterGigContext gigInDbContext, StimmeingabeImporterHelper stimmeingabeImporterHelper) {
      return listenkandidaturenInDbNachListenkandidaturTk.containsKey(listenkandidatur.getListenkandidaturTK());
    }

    @Override
    public Listenkandidatur findeListenkandidatur(Gebiet erfassungsgebiet, ListenkandidaturTK listenkandidaturTk, Listenkandidatur listenkandidaturInDatei, Map<ListenkandidaturTK, Listenkandidatur> listenkandidaturenInDbNachListenkandidaturTk, Map<ListenkandidaturNamenUndListeTK, Listenkandidatur> listenkandidaturenInDbNachNamenUndListeTk, Map<GruppeImGebietTK, GruppeImGebiet> gruppenImGebietInDb, StimmeingabeImporterGigContext gigInDbContext, StimmeingabeImporterHelper stimmeingabeImporterHelper) {
      return listenkandidaturenInDbNachListenkandidaturTk.get(listenkandidaturTk);
    }
  },

  NACH_NAME {
    @Override
    public boolean isListenkandidaturVorhanden(Gebiet erfassungsgebiet, Map<ListenkandidaturTK, Listenkandidatur> listenkandidaturenInDbNachListenkandidaturTk, Map<ListenkandidaturNamenUndListeTK, Listenkandidatur> listenkandidaturenInDbNachNamenUndListeTk, Listenkandidatur listenkandidatur, Map<GruppeImGebietTK, GruppeImGebiet> gruppenImGebietInDb, StimmeingabeImporterGigContext gigInDbContext, StimmeingabeImporterHelper stimmeingabeImporterHelper) {
      return listenkandidaturenInDbNachNamenUndListeTk.containsKey(ListenkandidaturNamenUndListeTK.createFromListenkandidatur(listenkandidatur));
    }

    @Override
    public Listenkandidatur findeListenkandidatur(Gebiet erfassungsgebiet, ListenkandidaturTK listenkandidaturTk, Listenkandidatur listenkandidaturInDatei, Map<ListenkandidaturTK, Listenkandidatur> listenkandidaturenInDbNachListenkandidaturTk, Map<ListenkandidaturNamenUndListeTK, Listenkandidatur> listenkandidaturenInDbNachNamenUndListeTk, Map<GruppeImGebietTK, GruppeImGebiet> gruppenImGebietInDb, StimmeingabeImporterGigContext gigInDbContext, StimmeingabeImporterHelper stimmeingabeImporterHelper) {
      return listenkandidaturenInDbNachNamenUndListeTk.get(ListenkandidaturNamenUndListeTK.createFromListenkandidatur(listenkandidaturInDatei));

    }
  },

  NACH_TK_FALLBACK_NACH_NAME {
    @Override
    public boolean isListenkandidaturVorhanden(Gebiet erfassungsgebiet, Map<ListenkandidaturTK, Listenkandidatur> listenkandidaturenInDbNachListenkandidaturTk, Map<ListenkandidaturNamenUndListeTK, Listenkandidatur> listenkandidaturenInDbNachNamenUndListeTk, Listenkandidatur listenkandidatur, Map<GruppeImGebietTK, GruppeImGebiet> gruppenImGebietInDb, StimmeingabeImporterGigContext gigInDbContext, StimmeingabeImporterHelper stimmeingabeImporterHelper) {
      return NACH_TK.isListenkandidaturVorhanden(erfassungsgebiet, listenkandidaturenInDbNachListenkandidaturTk, listenkandidaturenInDbNachNamenUndListeTk,
          listenkandidatur, gruppenImGebietInDb, gigInDbContext, stimmeingabeImporterHelper) ||
          NACH_NAME.isListenkandidaturVorhanden(erfassungsgebiet, listenkandidaturenInDbNachListenkandidaturTk, listenkandidaturenInDbNachNamenUndListeTk,
              listenkandidatur, gruppenImGebietInDb, gigInDbContext, stimmeingabeImporterHelper);
    }

    @Override
    public Listenkandidatur findeListenkandidatur(Gebiet erfassungsgebiet, ListenkandidaturTK listenkandidaturTk, Listenkandidatur listenkandidaturInDatei, Map<ListenkandidaturTK, Listenkandidatur> listenkandidaturenInDbNachListenkandidaturTk, Map<ListenkandidaturNamenUndListeTK, Listenkandidatur> listenkandidaturenInDbNachNamenUndListeTk, Map<GruppeImGebietTK, GruppeImGebiet> gruppenImGebietInDb, StimmeingabeImporterGigContext gigInDbContext, StimmeingabeImporterHelper stimmeingabeImporterHelper) {
      Listenkandidatur result = NACH_TK
          .findeListenkandidatur(erfassungsgebiet, listenkandidaturTk, listenkandidaturInDatei, listenkandidaturenInDbNachListenkandidaturTk,
              listenkandidaturenInDbNachNamenUndListeTk, gruppenImGebietInDb, gigInDbContext, stimmeingabeImporterHelper);
      if (result == null) {
        result = NACH_NAME.findeListenkandidatur(erfassungsgebiet, listenkandidaturTk, listenkandidaturInDatei, listenkandidaturenInDbNachListenkandidaturTk,
            listenkandidaturenInDbNachNamenUndListeTk, gruppenImGebietInDb, gigInDbContext, stimmeingabeImporterHelper);
      }
      return result;
    }
  },

  NACH_GRUPPE_IM_GEBIET_POSITION_UND_LISTENKANDIDATUR_POSITION {
    @Override
    public boolean isListenkandidaturVorhanden(Gebiet erfassungsgebiet, Map<ListenkandidaturTK, Listenkandidatur> listenkandidaturenInDbNachListenkandidaturTk, Map<ListenkandidaturNamenUndListeTK, Listenkandidatur> listenkandidaturenInDbNachNamenUndListeTk, Listenkandidatur listenkandidatur, Map<GruppeImGebietTK, GruppeImGebiet> gruppenImGebietInDb, StimmeingabeImporterGigContext gigInDbContext, StimmeingabeImporterHelper stimmeingabeImporterHelper) {
      return findeListenkandidatur(erfassungsgebiet, listenkandidatur.getListenkandidaturTK(), listenkandidatur, listenkandidaturenInDbNachListenkandidaturTk,
          listenkandidaturenInDbNachNamenUndListeTk, gruppenImGebietInDb, gigInDbContext, stimmeingabeImporterHelper) != null;
    }

    @Override
    public Listenkandidatur findeListenkandidatur(Gebiet erfassungsgebiet, ListenkandidaturTK listenkandidaturTk, Listenkandidatur listenkandidaturInDatei, Map<ListenkandidaturTK, Listenkandidatur> listenkandidaturenInDbNachListenkandidaturTk, Map<ListenkandidaturNamenUndListeTK, Listenkandidatur> listenkandidaturenInDbNachNamenUndListeTk, Map<GruppeImGebietTK, GruppeImGebiet> gruppenImGebietInDb, StimmeingabeImporterGigContext gigInDbContext, StimmeingabeImporterHelper stimmeingabeImporterHelper) {
      final GruppeImGebiet gruppeImGebietInDatei = listenkandidaturInDatei.getGruppeImGebiet();
      if (gruppeImGebietInDatei != null && gruppeImGebietInDatei.getVorgegebenePosition() != null && listenkandidaturInDatei.getVorgegebenePosition() != null) {
        final GruppeImGebiet gruppeImGebietInDb = StandardStimmeingabeImporterGruppeImGebietErsetzenStrategie.ERSETZE_GRUPPE_IM_GEBIET_NACH_POSITION.findGruppeImGebiet(gruppeImGebietInDatei, gruppenImGebietInDb, gigInDbContext, stimmeingabeImporterHelper);
        if (gruppeImGebietInDb != null) {
          List<Listenkandidatur> listenkandidaturenInDbSortiert = listenkandidaturenInDbNachListenkandidaturTk.values().stream()
              .filter(l -> gruppeImGebietInDb.getGruppeImGebietTK().equals(l.getGruppeImGebiet().getGruppeImGebietTK())
                  || l.getGruppe().getGruppeTK().equals(gruppeImGebietInDb.getGruppe().getGruppeTK()) && l.getGebiet().isInGebietshierarchieUebergeordnetesGebietVon(gruppeImGebietInDb.getGebiet()))
              .filter(l -> erfassungsgebiet == null || l.getListe().getGebiet().isInGebietshierarchieUebergeordnetesGebietVon(erfassungsgebiet)) // ELECT-8643
              .sorted(new ListenkandidaturByRelativePositionComparator())
              .collect(Collectors.toList());
          int listenkandidaturIndex = (int) (listenkandidaturInDatei.getVorgegebenePosition() - 1L);
          if (listenkandidaturIndex < listenkandidaturenInDbSortiert.size()) {
            return listenkandidaturenInDbSortiert.get(listenkandidaturIndex);
          }
        }
      }
      return null;
    }
  }
}
