
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.Kandidatur;
import de.ivu.elect.sitzberechnung.SitzberechnungEntity;

public class ErgebnisKonfliktKandidaturenAuswaehlen extends AbstractErgebnisKonfliktEntitiesAuswaehlen {

  private final List<String> kandidaturKeysAuswaehlbar;

  private final List<String> kandidaturKeysAusgewaehlt;

  private ErgebnisKonfliktKandidaturenAuswaehlen(Enum< ? > typ, ErgebnisKonfliktStatus ergebnisKonfliktStatus, long anzahlAuszuwaehlen, List<String> kandidaturKeysAuswaehlbar,
      List<String> kandidaturKeysAusgewaehlt) {
    super(typ, ergebnisKonfliktStatus, anzahlAuszuwaehlen);

    this.kandidaturKeysAuswaehlbar = kandidaturKeysAuswaehlbar;
    this.kandidaturKeysAusgewaehlt = kandidaturKeysAusgewaehlt;
  }

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

  public List<String> getKandidaturKeysAuswaehlbar() {
    return kandidaturKeysAuswaehlbar;
  }

  public List<String> getKandidaturKeysAusgewaehlt() {
    return kandidaturKeysAusgewaehlt;
  }

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

  protected boolean isFachlichGleich(ErgebnisKonfliktKandidaturenAuswaehlen other) {
    return other.getAnzahlAuszuwaehlen() == getAnzahlAuszuwaehlen() && other.getKandidaturKeysAuswaehlbar().size() == getKandidaturKeysAuswaehlbar().size()
        && other.getKandidaturKeysAuswaehlbar().containsAll(getKandidaturKeysAuswaehlbar());
  }

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

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

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

  public static String toJson(ErgebnisKonfliktKandidaturenAuswaehlen ergebnisKonflikt) {
    ErgebnisKonfliktEntitiesAuswaehlenDaten daten = new ErgebnisKonfliktEntitiesAuswaehlenDaten();
    daten.setLosentscheidTyp(ergebnisKonflikt.getLosentscheidTyp());
    daten.setAnzahlAuszuwaehlen(ergebnisKonflikt.getAnzahlAuszuwaehlen());
    daten.setErgebnisKonfliktStatus(ergebnisKonflikt.getErgebnisKonfliktStatus());
    daten.setKandidaturKeysAuswaehlbar(ergebnisKonflikt.getKandidaturKeysAuswaehlbar());
    daten.setKandidaturKeysAusgewaehlt(ergebnisKonflikt.getKandidaturKeysAusgewaehlt());

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

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

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

    return null;
  }

  public static ErgebnisKonfliktKandidaturenAuswaehlen newInstance(Enum< ? > typ, long anzahlAuszuwaehlen, List<Kandidatur> auswaehlbar) {
    return newInstance(typ, ErgebnisKonfliktStatus.UNGELOEST, anzahlAuszuwaehlen, auswaehlbar.stream().map(SitzberechnungEntity::getKey).collect(toList()), emptyList());
  }

  public static ErgebnisKonfliktKandidaturenAuswaehlen newInstance(Enum< ? > typ, ErgebnisKonfliktStatus ergebnisKonfliktStatus, long anzahlAuszuwaehlen, List<String> kandidaturKeysAuswaehlbar,
      List<String> kandidaturKeysAusgewaehlt) {
    return new ErgebnisKonfliktKandidaturenAuswaehlen(typ, ergebnisKonfliktStatus, anzahlAuszuwaehlen, kandidaturKeysAuswaehlbar, kandidaturKeysAusgewaehlt);
  }
}
