
package de.ivu.elect.sitzberechnung.konflikt;

import static java.util.Collections.emptyList;
import static java.util.stream.Collectors.toList;

import java.util.Collection;
import java.util.List;

import com.google.gson.Gson;

import de.ivu.elect.sitzberechnung.Gebiet;
import de.ivu.elect.sitzberechnung.Gruppe;
import de.ivu.elect.sitzberechnung.Kandidatur;
import de.ivu.elect.sitzberechnung.Liste;
import de.ivu.elect.sitzberechnung.SitzberechnungEntity;

public class ErgebnisKonfliktKandidaturenSortieren extends AbstractErgebnisKonfliktEntitiesSortieren {

  private final List<String> kandidaturKeysSortierbar;

  private final List<String> kandidaturKeysSortiert;

  private final String gruppeKey;

  private final String listeKey;

  private ErgebnisKonfliktKandidaturenSortieren(String wahlgebietKey, String wahlvorschlaggebietKey, String gruppeKey, String listeKey, Enum< ? > typ, ErgebnisKonfliktStatus ergebnisKonfliktStatus,
      List<String> kandidaturKeysSortierbar, List<String> kandidaturKeysSortiert) {
    super(wahlgebietKey, wahlvorschlaggebietKey, typ, ergebnisKonfliktStatus);

    this.gruppeKey = gruppeKey;
    this.listeKey = listeKey;

    this.kandidaturKeysSortierbar = kandidaturKeysSortierbar;
    this.kandidaturKeysSortiert = kandidaturKeysSortiert;
  }

  @Override
  public ErgebnisKonfliktArt getErgebnisKonfliktArt() {
    return ErgebnisKonfliktArt.LOSENTSCHEID_SORTIERUNG_KANDIDATUREN;
  }

  public boolean isAuswahlInGruppe() {
    return getGruppeKey() != null && !getGruppeKey().isBlank();
  }

  public String getGruppeKey() {
    return gruppeKey;
  }

  public boolean isAuswahlInListe() {
    return getListeKey() != null && !getListeKey().isBlank();
  }

  public String getListeKey() {
    return listeKey;
  }

  public List<String> getKandidaturKeysSortierbar() {
    return kandidaturKeysSortierbar;
  }

  public List<String> getKandidaturKeysSortiert() {
    return kandidaturKeysSortiert;
  }

  @Override
  public boolean isFachlichGleich(ErgebnisKonflikt other) {
    return other instanceof ErgebnisKonfliktKandidaturenSortieren && isFachlichGleich((ErgebnisKonfliktKandidaturenSortieren) other);
  }

  protected boolean isFachlichGleich(ErgebnisKonfliktKandidaturenSortieren other) {
    return super.isFachlichGleich(other) && other.getKandidaturKeysSortierbar().size() == getKandidaturKeysSortierbar().size()
        && other.getKandidaturKeysSortierbar().containsAll(getKandidaturKeysSortierbar());
  }

  public <E extends SitzberechnungEntity> List<E> filterKandidaturenSortierbar(Collection<E> entities) {
    return filterEntitiesByEntityKeys(entities, getKandidaturKeysSortierbar());
  }

  public <E extends SitzberechnungEntity> List<E> filterKandidaturenSortiert(Collection<E> entities) {
    return filterEntitiesByEntityKeys(entities, getKandidaturKeysSortiert());
  }

  @Override
  public String toJson() {
    return toJson(this);
  }

  public static String toJson(ErgebnisKonfliktKandidaturenSortieren ergebnisKonflikt) {
    ErgebnisKonfliktEntitiesDaten daten = new ErgebnisKonfliktEntitiesDaten();
    daten.setWahlgebietKey(ergebnisKonflikt.getWahlgebietKey());
    daten.setWahlvorschlaggebietKey(ergebnisKonflikt.getWahlvorschlaggebietKey());
    daten.setGruppeKey(ergebnisKonflikt.getGruppeKey());
    daten.setListeKey(ergebnisKonflikt.getListeKey());
    daten.setLosentscheidTyp(ergebnisKonflikt.getLosentscheidTyp());
    daten.setAnzahlAuszuwaehlen(ergebnisKonflikt.getKandidaturKeysSortierbar().size());
    daten.setErgebnisKonfliktStatus(ergebnisKonflikt.getErgebnisKonfliktStatus());
    daten.setKandidaturKeysAuswaehlbar(ergebnisKonflikt.getKandidaturKeysSortierbar());
    daten.setKandidaturKeysAusgewaehlt(ergebnisKonflikt.getKandidaturKeysSortiert());

    return new Gson().toJson(daten);
  }

  public static ErgebnisKonfliktKandidaturenSortieren fromJson(String json) {
    ErgebnisKonfliktEntitiesDaten daten = new Gson().fromJson(json, ErgebnisKonfliktEntitiesDaten.class);

    if (daten != null && !daten.isEmpty()) {
      return newInstance(daten.getWahlgebietKey(), daten.getWahlvorschlaggebietKey(), daten.getGruppeKey(), daten.getListeKey(), daten.getLosentscheidTyp(), daten.getErgebnisKonfliktStatus(),
          daten.getKandidaturKeysAuswaehlbar(), daten.getKandidaturKeysAusgewaehlt());
    }

    return null;
  }

  public static ErgebnisKonfliktKandidaturenSortieren newInstance(Gebiet wahlgebiet, Gebiet wahlvorschlaggebiet, Gruppe gruppe, Liste liste, Enum< ? > typ, List<Kandidatur> sortierbar) {
    return newInstance(wahlgebiet == null ? "" : wahlgebiet.getKey(), wahlvorschlaggebiet == null ? "" : wahlvorschlaggebiet.getKey(), gruppe == null ? "" : gruppe.getKey(),
        liste == null ? "" : liste.getKey(), typ, ErgebnisKonfliktStatus.UNGELOEST, sortierbar.stream().map(SitzberechnungEntity::getKey).collect(toList()), emptyList());
  }

  public static ErgebnisKonfliktKandidaturenSortieren newInstance(String wahlgebietKey, String wahlvorschlaggebietKey, String gruppeKey, String listeKey, Enum< ? > typ,
      ErgebnisKonfliktStatus ergebnisKonfliktStatus, List<String> kandidaturKeysSortierbar, List<String> kandidaturKeysSortiert) {
    return new ErgebnisKonfliktKandidaturenSortieren(wahlgebietKey, wahlvorschlaggebietKey, gruppeKey, listeKey, typ, ergebnisKonfliktStatus, kandidaturKeysSortierbar, kandidaturKeysSortiert);
  }
}
