
package de.ivu.elect.presentation;

import static java.util.Arrays.asList;

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

public enum NlElectionLevel {

  UNBEKANNT {

    @Override
    public boolean isLevelGesetzt() {
      return false;
    }
  },

  /**
   * Nationaal BriefStemBureau
   */
  NBSB {

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

    @Override
    public boolean isNBSB() {
      return true;
    }
  },
  /**
   * Nationaal BriefStemBureau voor Correcties
   */
  NBSBC {

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

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

  /**
   * A.k.a. GSB, Gemeentelijk StemBureau
   */
  PSB {

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

  /**
   * HoofdStemBureau
   */
  HSB {

    @Override
    public boolean isHSB() {
      return true;
    }
  },
  /**
   * HoofdStemBureau met nationaal Briefstembureau
   */
  HSBB {

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

    @Override
    public boolean isHSBB() {
      return true;
    }
  },
  /**
   * HoofdStemBureau voor Correcties
   */
  HSBC {

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

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

  /**
   * Centraal StemBureau
   */
  CSB {

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

  CSB_HSB_PSB {

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

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

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

    @Override
    public boolean isShowInHeader() {
      return false; // ELECTVAPP-99
    }
  },
  CSB_HSB {

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

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

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

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

  public boolean isLevelGesetzt() {
    return true;
  }

  /**
   * Nationaal BriefStemBureau
   */
  public boolean isNBSB() {
    return false;
  }

  /**
   * Nationaal BriefStemBureau voor Correcties
   */
  public boolean isNBSBC() {
    return false;
  }

  /**
   * Gemeentelijk StemBureau
   */
  public boolean isGSB() {
    return false;
  }

  /**
   * HoofdStemBureau
   */
  public boolean isHSB() {
    return false;
  }

  /**
   * HoofdStemBureau met nationaal Briefstembureau
   */
  public boolean isHSBB() {
    return false;
  }

  /**
   * HoofdStemBureau voor Correcties
   */
  public boolean isHSBC() {
    return false;
  }

  /**
   * Centraal StemBureau
   */
  public boolean isCSB() {
    return false;
  }

  public static NlElectionLevel kombiniere(NlElectionLevel... levels) {
    return kombiniere(new HashSet<>(asList(levels)));
  }

  public static NlElectionLevel kombiniere(Set<NlElectionLevel> levels) {
    var csb = levels.stream().anyMatch(NlElectionLevel::isCSB);
    var hsb = levels.stream().anyMatch(NlElectionLevel::isHSB);
    var gsb = levels.stream().anyMatch(NlElectionLevel::isGSB);

    for (var value : values()) {
      if (!value.isHSBB() && !value.isHSBC() && !value.isNBSB() && !value.isNBSBC()) {
        if (value.isCSB() == csb && value.isHSB() == hsb && value.isGSB() == gsb) {
          return value;
        }
      }
    }

    throw new IllegalStateException("Ungültige Kombination: " + levels);
  }

  public boolean isPrivateKeyNeeded() {
    if (isCSB()) {
      return false;
    }

    if (isGSB()) {
      return !isHSB() || !isCSB();
    }

    if (isHSB()) {
      return !isCSB();
    }

    return false;
  }

  public boolean isPublicKeyNeeded() {
    if (isGSB()) {
      return isNBSBC(); // ELECT-16725
    }

    if (isHSB()) {
      return !isGSB();
    }

    if (isCSB()) {
      return !isGSB() || !isHSB();
    }

    return false;
  }

  public boolean isShowInHeader() {
    return true; // ELECTVAPP-849
  }

  public boolean isReinesHsb() {
    return isHSB() && !isGSB() && !isCSB();
  }
}
