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

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;

import de.ivu.elect.business.security.Customer;


import static java.util.Arrays.asList;
import static java.util.Collections.emptySet;
import static java.util.Collections.singletonList;

public enum NlWahlPhase {

  NICHT_GESETZT {

    @Override
    public boolean isAccept(Customer customer, Wahl wahl) {
      return false;
    }

    @Override
    public Collection<NlWahlPhase> getNachfolger() {
      return Collections.emptySet();
    }

    @Override
    public String getNumber(Customer customer, Wahl wahl) {
      return "";
    }
  },

  INITIAL {

    @Override
    public boolean isInitial() {
      return true;
    }

    @Override
    public boolean isAccept(Customer customer, Wahl wahl) {
      return true;
    }

    @Override
    public Collection<NlWahlPhase> getNachfolger() {
      return asList(EINREICHUNG, ERFASSUNG);
    }
  },

  EINREICHUNG {

    @Override
    public boolean isEinreichung() {
      return true;
    }

    @Override
    public boolean isAccept(Customer customer, Wahl wahl) {
      return Customer.NL_WUS.equals(customer);
    }

    @Override
    public Collection<NlWahlPhase> getNachfolger() {
      return singletonList(PRUEFUNG);
    }
  },
  PRUEFUNG {

    @Override
    public boolean isPruefung() {
      return true;
    }

    @Override
    public boolean isAccept(Customer customer, Wahl wahl) {
      return Customer.NL_WUS.equals(customer);
    }

    @Override
    public Collection<NlWahlPhase> getNachfolger() {
      return singletonList(NUMMERIERUNG);
    }

  },
  NUMMERIERUNG {

    @Override
    public boolean isNummerierung() {
      return true;
    }

    @Override
    public boolean isAccept(Customer customer, Wahl wahl) {
      return Customer.NL_WUS.equals(customer);
    }

    @Override
    public Collection<NlWahlPhase> getNachfolger() {
      return singletonList(FREIGABE);
    }
  },

  ERFASSUNG {

    @Override
    public boolean isErfassung() {
      return true;
    }

    @Override
    public boolean isAccept(Customer customer, Wahl wahl) {
      return Customer.NL_WAS.equals(customer);
    }

    @Override
    public Collection<NlWahlPhase> getNachfolger() {
      return singletonList(ABSCHLUSS);
    }
  },
  ABSCHLUSS {

    @Override
    public boolean isAbschluss() {
      return true;
    }

    @Override
    public boolean isAccept(Customer customer, Wahl wahl) {
      return Customer.NL_WAS.equals(customer);
    }

    @Override
    public Collection<NlWahlPhase> getNachfolger() {
      return asList(SITZBERECHNUNG/*, FREIGABE ELECTVAPP-458 laut elect ist das nicht mehr so*/);
    }
  },
  SITZBERECHNUNG {

    @Override
    public boolean isSitzberechnung() {
      return true;
    }

    @Override
    public boolean isAccept(Customer customer, Wahl wahl) {
      return Customer.NL_WAS.equals(customer) && NlWahlart.isWasCSB(wahl, customer);
    }

    @Override
    public Collection<NlWahlPhase> getNachfolger() {
      return singletonList(FREIGABE);
    }

    @Override
    public boolean isErgebnisAnzeigen() {
      return true;
    }
  },

  FREIGABE {

    @Override
    public boolean isFreigabe() {
      return true;
    }

    @Override
    public boolean isAccept(Customer customer, Wahl wahl) {
      return Customer.NL_WUS.equals(customer) || Customer.NL_WAS.equals(customer) && NlWahlart.isWasCSB(wahl, customer);
    }

    @Override
    public Collection<NlWahlPhase> getNachfolger() {
      return emptySet();
    }

    @Override
    public boolean isErgebnisAnzeigen() {
      return true;
    }
  };

  public boolean isDokumenteZurEinreichungErzeugbar() {
    return isEinreichung();
  }

  public boolean isInitial() {
    return false;
  }

  public boolean isEinreichung() {
    return false;
  }

  public boolean isDokumenteZurPruefungErzeugbar() {
    return isPruefung();
  }

  public boolean isPruefung() {
    return false;
  }

  public boolean isNummerierung() {
    return false;
  }

  public boolean isErfassung() {
    return false;
  }

  public boolean isAbschluss() {
    return false;
  }

  public boolean isSitzberechnung() {
    return false;
  }

  public boolean isDokumenteZurFreigabeErzeugbar() {
    return isFreigabe();
  }

  public boolean isFreigabe() {
    return false;
  }

  public abstract boolean isAccept(Customer customer, Wahl wahl);

  public abstract Collection<NlWahlPhase> getNachfolger();

  public Set<NlWahlPhase> getVorgaenger() {
    return Arrays.stream(NlWahlPhase.values()).filter(value -> value.getNachfolger().contains(this)).collect(Collectors.toSet());
  }

  // ELECT-10268
  public boolean isErgebnisAnzeigen() {
    return false;
  }

  public String getNumber(Customer customer, Wahl wahl) {
    return Character.toString((char) (9311 + bestimmePositionOneBased(this, customer, wahl)));
  }

  protected static int bestimmePositionOneBased(NlWahlPhase nlWahlPhase, Customer customer, Wahl wahl) {
    // ELECTVAPP-458 die längste Kette ist die korrekte
    int result = 0;
    for (NlWahlPhase vorgaenger : nlWahlPhase.getVorgaenger()) {
      if (vorgaenger.isAccept(customer, wahl)) {
        int vorgaengerPos = bestimmePositionOneBased(vorgaenger, customer, wahl);
        if (vorgaengerPos > result) {
          result = vorgaengerPos;
        }
      }
    }
    return result + 1;

    // return nlWahlPhase.getVorgaenger().stream().filter(wahlPhase -> wahlPhase.isAccept(customer, wahl)).findFirst().map(wahlPhase -> bestimmePosition
    // (wahlPhase, customer, wahl) + 1).orElse(0);
  }

}
