/*
 * P2ListImpl
 *
 * Created on 18.12.2008 Copyright (c) 2008 Kiesraad
 */

package de.ivu.wahl.result.builder;

import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import de.ivu.wahl.result.CandidateList;
import de.ivu.wahl.result.determination.P2List;
import de.ivu.wahl.result.drawlots.DrawingLotsIdentifier;
import de.ivu.wahl.result.result.GeneralListKey;

/**
 * Default implementation of the P2List interface. _candidateLists may be changed (by adding candidate lists) during
 * construction.
 *
 * @author , IVU Traffic Technologies AG
 */
public class P2ListImpl implements P2List {

  private final Set<CandidateList> candidateLists;
  private final Object externalKey;

  public P2ListImpl(Object externalKey) {
    this.candidateLists = new LinkedHashSet<>();
    this.externalKey = externalKey;
  }

  @Override
  public Set<CandidateList> getCandidateLists() {
    return Collections.unmodifiableSet(candidateLists);
  }

  @Override
  public Object getExternalKey() {
    return externalKey;
  }

  public void addCandidateList(final CandidateList candidateList) {
    candidateLists.add(candidateList);
  }

  @Override
  public String getName() {
    if (candidateLists.isEmpty()) {
      return "Empty P2-list"; //$NON-NLS-1$
    }
    StringBuilder builder = new StringBuilder();
    builder.append(getFirstCandidateList().getListNumberOrName());
    builder.append(" ("); //$NON-NLS-1$
    boolean first = true;
    for (CandidateList candidateList : candidateLists) {
      if (first) {
        first = false;
      } else {
        builder.append(", "); //$NON-NLS-1$
      }
      builder.append(candidateList.getElectoralDistrict().getName());
    }
    builder.append(")"); //$NON-NLS-1$

    return builder.toString();
  }

  public int compareTo(P2List other) {
    boolean xEmpty = this.getCandidateLists().isEmpty();
    boolean yEmpty = other.getCandidateLists().isEmpty();
    if (xEmpty && yEmpty) {
      return 0;
    } else if (!xEmpty && yEmpty) {
      return 1;
    } else if (xEmpty && !yEmpty) {
      return -1;
    }
    return this.getFirstCandidateList().compareTo(other.getFirstCandidateList());
  }

  @Override
  public String toString() {
    return getName();
  }

  @Override
  public String getKey() {
    return new GeneralListKey(this).getKey();
  }

  @Override
  public int getElectoralDistrictNumber() {
    return candidateLists.stream().map(cl -> cl.getElectoralDistrict().getNumber()).min(Comparator.naturalOrder())
            .orElseThrow(IllegalStateException::new);
  }

  @Override
  public DrawingLotsIdentifier getIdentifier() {
    return new DrawingLotsIdentifier(this);
  }

  @Override
  public String getElectoralDistrictNumbers() {
    SortedSet<Integer> set = new TreeSet<>();
    for (CandidateList candidateList : candidateLists) {
      set.add(candidateList.getElectoralDistrict().getNumber());
    }
    Integer[] array = set.toArray(new Integer[0]);
    StringBuilder b = new StringBuilder();
    for (int i = 0; i < array.length; i++) {
      Integer integer = array[i];
      b.append(integer);
      if (i < array.length - 2) {
        b.append(", ");
      } else if (i == array.length - 2) {
        b.append(" en ");
      }
    }
    return b.toString();
  }
}