
package de.ivu.elect.business.gebietsbaum.boundary;

import static org.apache.commons.lang3.StringUtils.containsOnly;
import static org.apache.commons.lang3.StringUtils.deleteWhitespace;
import static org.apache.commons.lang3.StringUtils.isAllBlank;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.leftPad;
import static org.apache.commons.lang3.StringUtils.substringBeforeLast;
import static org.apache.commons.lang3.StringUtils.trimToEmpty;

import java.util.Optional;

import javax.annotation.Nullable;

import de.ivu.elect.business.datei.entity.FileType;
import de.ivu.elect.business.exchange.control.FileKonfiguration;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.Gebietsgruppierung;
import de.ivu.elect.util.FileUtil;

public class WahlverwaltungGebietInformation {

  private final Optional<Gebiet> gebiet;

  private final Optional<Gebietsgruppierung> gebietsgruppierung;

  private final int artIndexOneBased;

  private final String art;

  private final String name;

  private final String nummer;

  private final String kuerzel;

  public WahlverwaltungGebietInformation(Gebiet gebiet) {
    this(gebiet, gebiet.getNummer());
  }

  public WahlverwaltungGebietInformation(Gebiet gebiet, String nummer) {
    this(Optional.of(gebiet), Optional.empty(), gebiet.getGebietsart() != null ? gebiet.getGebietsart().getName() : "", 0, gebiet.getName(), nummer, gebiet.getKuerzel());
  }

  public WahlverwaltungGebietInformation(int artIndexOneBased, Gebietsgruppierung gebietsgruppierung) {
    this(Optional.empty(), Optional.of(gebietsgruppierung), gebietsgruppierung.getGebietsgruppierungArt(), artIndexOneBased, gebietsgruppierung.getName(),
        gebietsgruppierung.getPosition() != null ? String.valueOf(gebietsgruppierung.getPosition()) : "", "");
  }

  public WahlverwaltungGebietInformation(String art, String name, String nummer, String kuerzel) {
    this(Optional.empty(), Optional.empty(), art, 0, name, nummer, kuerzel);
  }

  WahlverwaltungGebietInformation(Optional<Gebiet> gebiet, Optional<Gebietsgruppierung> gebietsgruppierung, String art, int artIndexOneBased, String name, String nummer, String kuerzel) {
    super();

    this.gebiet = gebiet;
    this.gebietsgruppierung = gebietsgruppierung;

    this.art = trimToEmpty(art);
    this.artIndexOneBased = artIndexOneBased; // ELECT-8091

    this.name = trimToEmpty(name);
    this.nummer = deleteWhitespace(trimToEmpty(nummer));
    this.kuerzel = trimToEmpty(kuerzel);
  }

  public boolean isUnbekannt() {
    return isAllBlank(getName(), getNummer(), getKuerzel());
  }

  public boolean equalsGebiet(Gebiet another) {
    return getGebiet().filter(one -> one.equals(another)).isPresent();
  }

  public Optional<Gebiet> getGebiet() {
    return gebiet;
  }

  public boolean equalsGebietsgruppierung(Gebietsgruppierung another) {
    return getGebietsgruppierung().filter(one -> one.equals(another)).isPresent();
  }

  public Optional<Gebietsgruppierung> getGebietsgruppierung() {
    return gebietsgruppierung;
  }

  public String getArt() {
    return art;
  }

  public int getArtIndex() {
    return artIndexOneBased;
  }

  public String getName() {
    return name;
  }

  public String getNummer() {
    return nummer;
  }

  public String getKuerzel() {
    return kuerzel;
  }

  public String createFileName(FileType fileType) {
    return createFileName(null, fileType);
  }

  public String createFileName(FileKonfiguration fileKonfiguration, FileType fileType) {
    return createSimpleFileName(fileKonfiguration) + "." + fileType.getFileExtension();
  }

  public String createFileNameOrDefaultByIndex(FileKonfiguration fileKonfiguration, FileType fileType, int index) {
    return createSimpleFileNameOrDefaultByIndex(fileKonfiguration, index) + "." + fileType.getFileExtension();
  }

  public String createSimpleFileName(FileKonfiguration fileKonfiguration) {
    return FileUtil.normalizeZipEntryName(createSimpleFileNameOrFallback(fileKonfiguration));
  }

  public String createSimpleFileNameOrDefaultByIndex(FileKonfiguration fileKonfiguration, int index) {
    return FileUtil.normalizeZipEntryNameOrDefaultByIndex(createSimpleFileNameOrFallback(fileKonfiguration), index);
  }

  protected String createSimpleFileNameOrFallback(@Nullable FileKonfiguration fileKonfiguration) {
    String result = getNummer();

    if (isNotBlank(getName())) {
      result += "-" + getName();
    }

    if (getArtIndex() > 0) {
      result += "-" + leftPad(String.valueOf(getArtIndex()), 2, "0");
    }

    if ((isBlank(result) || containsOnly(result, "_")) && fileKonfiguration != null) { // ELECT-8535
      String fallbackValue = substringBeforeLast(fileKonfiguration.getFileName(), ".");

      if (isNotBlank(fallbackValue)) {
        result = fallbackValue;
      }
    }

    return trimToEmpty(result);
  }

  /*
   * AUTO-GENERATED
   */

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + (art == null ? 0 : art.hashCode());
    result = prime * result + artIndexOneBased;
    result = prime * result + (kuerzel == null ? 0 : kuerzel.hashCode());
    result = prime * result + (name == null ? 0 : name.hashCode());
    result = prime * result + (nummer == null ? 0 : nummer.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null) {
      return false;
    }
    if (getClass() != obj.getClass()) {
      return false;
    }
    WahlverwaltungGebietInformation other = (WahlverwaltungGebietInformation) obj;
    if (art == null) {
      if (other.art != null) {
        return false;
      }
    } else if (!art.equals(other.art)) {
      return false;
    }
    if (artIndexOneBased != other.artIndexOneBased) {
      return false;
    }
    if (kuerzel == null) {
      if (other.kuerzel != null) {
        return false;
      }
    } else if (!kuerzel.equals(other.kuerzel)) {
      return false;
    }
    if (name == null) {
      if (other.name != null) {
        return false;
      }
    } else if (!name.equals(other.name)) {
      return false;
    }
    if (nummer == null) {
      if (other.nummer != null) {
        return false;
      }
    } else if (!nummer.equals(other.nummer)) {
      return false;
    }
    return true;
  }
}
