
package de.ivu.elect.presentation.anschrift.table;

import static org.apache.commons.lang3.StringUtils.isNotBlank;

import de.ivu.elect.business.anschrift.entity.Anschrift;
import de.ivu.elect.business.anschrift.entity.EntityMitAnschrift;
import de.ivu.elect.business.anschrift.entity.EntityMitErreichbarkeitsanschrift;
import de.ivu.elect.jee.faces.Messages;
import de.ivu.elect.jee.presentation.dynamictable.ColumnType;
import de.ivu.elect.presentation.table.AbstractColumnEntry;

public class EntityMitAnschriftColumns {

  private EntityMitAnschriftColumns() {
    super();
  }

  public static class EntityMitAnschriftStrasseMitHausnummerColumn<E extends EntityMitAnschrift> extends AbstractAnschriftStrasseMitHausnummerColumn<E> {

    private static final long serialVersionUID = 1L;

    public EntityMitAnschriftStrasseMitHausnummerColumn(Messages messages) {
      super(messages);
    }

    @Override
    protected Anschrift extractAnschrift(E entityMitAnschrift) {
      return entityMitAnschrift.getAnschrift();
    }
  }

  public static class EntityMitErreichbarkeitsanschriftStrasseMitHausnummerColumn<E extends EntityMitErreichbarkeitsanschrift> extends AbstractAnschriftStrasseMitHausnummerColumn<E> {

    private static final long serialVersionUID = 1L;

    public EntityMitErreichbarkeitsanschriftStrasseMitHausnummerColumn(Messages messages) {
      super(messages);
    }

    @Override
    protected Anschrift extractAnschrift(E entityMitErreichbarkeitsanschrift) {
      return entityMitErreichbarkeitsanschrift.getErreichbarkeitsanschrift();
    }
  }

  private abstract static class AbstractAnschriftStrasseMitHausnummerColumn<E> extends AbstractColumnEntry<E> {

    private static final long serialVersionUID = 1L;

    private final AbstractAnschriftColumn<Anschrift> anschriftStrasseColumn;

    private final AbstractAnschriftColumn<Anschrift> anschriftHausnummerColumn;

    private final AbstractAnschriftColumn<Anschrift> anschriftHausnummerzusatzColumn;

    private final AbstractAnschriftColumn<Anschrift> anschriftWohnungsnummerColumn;

    protected AbstractAnschriftStrasseMitHausnummerColumn(Messages messages) {
      super(messages);

      this.anschriftStrasseColumn = AbstractAnschriftColumn.createAnschriftStrasseColumn(messages);
      this.anschriftHausnummerColumn = AbstractAnschriftColumn.createAnschriftHausnummerColumn(messages);
      this.anschriftHausnummerzusatzColumn = AbstractAnschriftColumn.createAnschriftHausnummerzusatzColumn(messages);
      this.anschriftWohnungsnummerColumn = AbstractAnschriftColumn.createAnschriftWohnungsnummerColumn(messages);
    }

    protected abstract Anschrift extractAnschrift(E entity);

    @Override
    public ColumnType getType() {
      return ColumnType.STRING;
    }

    @Override
    public boolean isRendered() {
      return anschriftStrasseColumn.isRendered();
    }

    @Override
    public String getHeader() {
      return getMessage("zusammengesetzte.strasse.column.header"); // ELECT-12932
    }

    @Override // https://www.din-5008-richtlinien.de/startseite/anschriftenfeld/
    public Object getValue(E entity) {
      if (entity == null) {
        return "";
      }

      String result = "";

      Anschrift anschrift = extractAnschrift(entity);

      String strasse = (String) anschriftStrasseColumn.getDisplayValue(anschrift);

      if (isNotBlank(strasse)) {
        result += strasse;
      }

      String hausnummer = (String) anschriftHausnummerColumn.getDisplayValue(anschrift);

      if (isNotBlank(hausnummer)) {
        if (isNotBlank(result)) {
          result += " ";
        }

        result += hausnummer;
      }

      String hausnummerzusatz = (String) anschriftHausnummerzusatzColumn.getDisplayValue(anschrift);

      if (isNotBlank(hausnummerzusatz)) {
        if (isNotBlank(result)) {
          result += ", ";
        }

        result += hausnummerzusatz;
      }

      String wohnungsnummer = (String) anschriftWohnungsnummerColumn.getDisplayValue(anschrift);

      if (isNotBlank(wohnungsnummer)) {
        if (isNotBlank(result)) {
          result += " ";
        }

        result += "// ";
        result += wohnungsnummer;
      }

      return result;
    }
  }

  public static class EntityMitAnschriftStrasseColumn<E extends EntityMitAnschrift> extends AbstractAnschriftStrasseColumn<E> {

    private static final long serialVersionUID = 1L;

    public EntityMitAnschriftStrasseColumn(Messages messages) {
      super(messages);
    }

    @Override
    protected Anschrift extractAnschrift(E entityMitAnschrift) {
      return entityMitAnschrift.getAnschrift();
    }
  }

  public static class EntityMitErreichbarkeitsanschriftStrasseColumn<E extends EntityMitErreichbarkeitsanschrift> extends AbstractAnschriftStrasseColumn<E> {

    private static final long serialVersionUID = 1L;

    public EntityMitErreichbarkeitsanschriftStrasseColumn(Messages messages) {
      super(messages);
    }

    @Override
    protected Anschrift extractAnschrift(E entityMitErreichbarkeitsanschrift) {
      return entityMitErreichbarkeitsanschrift.getErreichbarkeitsanschrift();
    }
  }

  private abstract static class AbstractAnschriftStrasseColumn<E> extends AbstractColumnEntry<E> {

    private static final long serialVersionUID = 1L;

    private final AbstractAnschriftColumn<Anschrift> anschriftStrasseColumn;

    protected AbstractAnschriftStrasseColumn(Messages messages) {
      super(messages);

      this.anschriftStrasseColumn = AbstractAnschriftColumn.createAnschriftStrasseColumn(messages);
    }

    protected abstract Anschrift extractAnschrift(E entity);

    @Override
    public ColumnType getType() {
      return anschriftStrasseColumn.getType();
    }

    @Override
    public boolean isRendered() {
      return anschriftStrasseColumn.isRendered();
    }

    @Override
    public String getHeader() {
      return anschriftStrasseColumn.getHeader();
    }

    @Override
    public Object getValue(E entity) {
      if (entity == null) {
        return "";
      }

      return anschriftStrasseColumn.getDisplayValue(extractAnschrift(entity));
    }
  }

  public static class EntityMitAnschriftHausnummerColumn<E extends EntityMitAnschrift> extends AbstractAnschriftHausnummerColumn<E> {

    private static final long serialVersionUID = 1L;

    public EntityMitAnschriftHausnummerColumn(Messages messages) {
      super(messages);
    }

    @Override
    protected Anschrift extractAnschrift(E entityMitAnschrift) {
      return entityMitAnschrift.getAnschrift();
    }
  }

  public static class EntityMitErreichbarkeitsanschriftHausnummerColumn<E extends EntityMitErreichbarkeitsanschrift> extends AbstractAnschriftHausnummerColumn<E> {

    private static final long serialVersionUID = 1L;

    public EntityMitErreichbarkeitsanschriftHausnummerColumn(Messages messages) {
      super(messages);
    }

    @Override
    protected Anschrift extractAnschrift(E entityMitErreichbarkeitsanschrift) {
      return entityMitErreichbarkeitsanschrift.getErreichbarkeitsanschrift();
    }
  }

  private abstract static class AbstractAnschriftHausnummerColumn<E> extends AbstractColumnEntry<E> {

    private static final long serialVersionUID = 1L;

    private final AbstractAnschriftColumn<Anschrift> anschriftHausnummerColumn;

    protected AbstractAnschriftHausnummerColumn(Messages messages) {
      super(messages);

      this.anschriftHausnummerColumn = AbstractAnschriftColumn.createAnschriftHausnummerColumn(messages);
    }

    protected abstract Anschrift extractAnschrift(E entity);

    @Override
    public ColumnType getType() {
      return anschriftHausnummerColumn.getType();
    }

    @Override
    public boolean isRendered() {
      return anschriftHausnummerColumn.isRendered();
    }

    @Override
    public String getHeader() {
      return anschriftHausnummerColumn.getHeader();
    }

    @Override
    public Object getValue(E entity) {
      if (entity == null) {
        return "";
      }

      return anschriftHausnummerColumn.getDisplayValue(extractAnschrift(entity));
    }
  }

  public static class EntityMitAnschriftHausnummerzusatzColumn<E extends EntityMitAnschrift> extends AbstractAnschriftHausnummerzusatzColumn<E> {

    private static final long serialVersionUID = 1L;

    public EntityMitAnschriftHausnummerzusatzColumn(Messages messages) {
      super(messages);
    }

    @Override
    protected Anschrift extractAnschrift(E entityMitAnschrift) {
      return entityMitAnschrift.getAnschrift();
    }
  }

  public static class EntityMitErreichbarkeitsanschriftHausnummerzusatzColumn<E extends EntityMitErreichbarkeitsanschrift> extends AbstractAnschriftHausnummerzusatzColumn<E> {

    private static final long serialVersionUID = 1L;

    public EntityMitErreichbarkeitsanschriftHausnummerzusatzColumn(Messages messages) {
      super(messages);
    }

    @Override
    protected Anschrift extractAnschrift(E entityMitErreichbarkeitsanschrift) {
      return entityMitErreichbarkeitsanschrift.getErreichbarkeitsanschrift();
    }
  }

  private abstract static class AbstractAnschriftHausnummerzusatzColumn<E> extends AbstractColumnEntry<E> {

    private static final long serialVersionUID = 1L;

    private final AbstractAnschriftColumn<Anschrift> anschriftHausnummerzusatzColumn;

    protected AbstractAnschriftHausnummerzusatzColumn(Messages messages) {
      super(messages);

      this.anschriftHausnummerzusatzColumn = AbstractAnschriftColumn.createAnschriftHausnummerzusatzColumn(messages);
    }

    protected abstract Anschrift extractAnschrift(E entity);

    @Override
    public ColumnType getType() {
      return anschriftHausnummerzusatzColumn.getType();
    }

    @Override
    public boolean isRendered() {
      return anschriftHausnummerzusatzColumn.isRendered();
    }

    @Override
    public String getHeader() {
      return anschriftHausnummerzusatzColumn.getHeader();
    }

    @Override
    public Object getValue(E entity) {
      if (entity == null) {
        return "";
      }

      return anschriftHausnummerzusatzColumn.getDisplayValue(extractAnschrift(entity));
    }
  }

  public static class EntityMitAnschriftWohnungsnummerColumn<E extends EntityMitAnschrift> extends AbstractAnschriftWohnungsnummerColumn<E> {

    private static final long serialVersionUID = 1L;

    public EntityMitAnschriftWohnungsnummerColumn(Messages messages) {
      super(messages);
    }

    @Override
    protected Anschrift extractAnschrift(E entityMitAnschrift) {
      return entityMitAnschrift.getAnschrift();
    }
  }

  public static class EntityMitErreichbarkeitsanschriftWohnungsnummerColumn<E extends EntityMitErreichbarkeitsanschrift> extends AbstractAnschriftWohnungsnummerColumn<E> {

    private static final long serialVersionUID = 1L;

    public EntityMitErreichbarkeitsanschriftWohnungsnummerColumn(Messages messages) {
      super(messages);
    }

    @Override
    protected Anschrift extractAnschrift(E entityMitErreichbarkeitsanschrift) {
      return entityMitErreichbarkeitsanschrift.getErreichbarkeitsanschrift();
    }
  }

  private abstract static class AbstractAnschriftWohnungsnummerColumn<E> extends AbstractColumnEntry<E> {

    private static final long serialVersionUID = 1L;

    private final AbstractAnschriftColumn<Anschrift> anschriftWohnungsnummerColumn;

    protected AbstractAnschriftWohnungsnummerColumn(Messages messages) {
      super(messages);

      this.anschriftWohnungsnummerColumn = AbstractAnschriftColumn.createAnschriftWohnungsnummerColumn(messages);
    }

    protected abstract Anschrift extractAnschrift(E entity);

    @Override
    public ColumnType getType() {
      return anschriftWohnungsnummerColumn.getType();
    }

    @Override
    public boolean isRendered() {
      return anschriftWohnungsnummerColumn.isRendered();
    }

    @Override
    public String getHeader() {
      return anschriftWohnungsnummerColumn.getHeader();
    }

    @Override
    public Object getValue(E entity) {
      if (entity == null) {
        return "";
      }

      return anschriftWohnungsnummerColumn.getDisplayValue(extractAnschrift(entity));
    }
  }

  public static class EntityMitAnschriftOrtColumn<E extends EntityMitAnschrift> extends AbstractAnschriftOrtColumn<E> {

    private static final long serialVersionUID = 1L;

    public EntityMitAnschriftOrtColumn(Messages messages) {
      super(messages);
    }

    public EntityMitAnschriftOrtColumn(Messages messages, String headerMsgKey) {
      super(messages, headerMsgKey);
    }

    @Override
    protected Anschrift extractAnschrift(E entityMitAnschrift) {
      return entityMitAnschrift.getAnschrift();
    }
  }

  public static class EntityMitErreichbarkeitsanschriftOrtColumn<E extends EntityMitErreichbarkeitsanschrift> extends AbstractAnschriftOrtColumn<E> {

    private static final long serialVersionUID = 1L;

    public EntityMitErreichbarkeitsanschriftOrtColumn(Messages messages) {
      super(messages);
    }

    public EntityMitErreichbarkeitsanschriftOrtColumn(Messages messages, String headerMsgKey) {
      super(messages, headerMsgKey);
    }

    @Override
    protected Anschrift extractAnschrift(E entityMitErreichbarkeitsanschrift) {
      return entityMitErreichbarkeitsanschrift.getErreichbarkeitsanschrift();
    }
  }

  private abstract static class AbstractAnschriftOrtColumn<E> extends AbstractColumnEntry<E> {

    private static final long serialVersionUID = 1L;

    private final String headerMsgKey;

    private final AbstractAnschriftColumn<Anschrift> anschriftOrtColumn;

    protected AbstractAnschriftOrtColumn(Messages messages) {
      this(messages, "");
    }

    protected AbstractAnschriftOrtColumn(Messages messages, String headerMsgKey) {
      super(messages);

      this.headerMsgKey = headerMsgKey;

      this.anschriftOrtColumn = AbstractAnschriftColumn.createAnschriftOrtColumn(messages);
    }

    protected abstract Anschrift extractAnschrift(E entity);

    @Override
    public ColumnType getType() {
      return anschriftOrtColumn.getType();
    }

    @Override
    public boolean isRendered() {
      return anschriftOrtColumn.isRendered();
    }

    @Override
    public String getHeader() {
      if (isNotBlank(headerMsgKey)) {
        return getMessage(headerMsgKey);
      }

      return anschriftOrtColumn.getHeader();
    }

    @Override
    public Object getValue(E entity) {
      if (entity == null) {
        return "";
      }

      return anschriftOrtColumn.getDisplayValue(extractAnschrift(entity));
    }
  }

  public static class EntityMitAnschriftOrtsteilColumn<E extends EntityMitAnschrift> extends AbstractAnschriftOrtsteilColumn<E> {

    private static final long serialVersionUID = 1L;

    public EntityMitAnschriftOrtsteilColumn(Messages messages) {
      super(messages);
    }

    @Override
    protected Anschrift extractAnschrift(E entityMitAnschrift) {
      return entityMitAnschrift.getAnschrift();
    }
  }

  public static class EntityMitErreichbarkeitsanschriftOrtsteilColumn<E extends EntityMitErreichbarkeitsanschrift> extends AbstractAnschriftOrtsteilColumn<E> {

    private static final long serialVersionUID = 1L;

    public EntityMitErreichbarkeitsanschriftOrtsteilColumn(Messages messages) {
      super(messages);
    }

    @Override
    protected Anschrift extractAnschrift(E entityMitErreichbarkeitsanschrift) {
      return entityMitErreichbarkeitsanschrift.getErreichbarkeitsanschrift();
    }
  }

  private abstract static class AbstractAnschriftOrtsteilColumn<E> extends AbstractColumnEntry<E> {

    private static final long serialVersionUID = 1L;

    private final AbstractAnschriftColumn<Anschrift> anschriftOrtsteilColumn;

    protected AbstractAnschriftOrtsteilColumn(Messages messages) {
      super(messages);

      this.anschriftOrtsteilColumn = AbstractAnschriftColumn.createAnschriftOrtsteilColumn(messages);
    }

    protected abstract Anschrift extractAnschrift(E entity);

    @Override
    public ColumnType getType() {
      return anschriftOrtsteilColumn.getType();
    }

    @Override
    public boolean isRendered() {
      return anschriftOrtsteilColumn.isRendered();
    }

    @Override
    public String getHeader() {
      return anschriftOrtsteilColumn.getHeader();
    }

    @Override
    public Object getValue(E entity) {
      if (entity == null) {
        return "";
      }

      return anschriftOrtsteilColumn.getDisplayValue(extractAnschrift(entity));
    }
  }

  public static class EntityMitAnschriftPlzColumn<E extends EntityMitAnschrift> extends AbstractAnschriftPlzColumn<E> {

    private static final long serialVersionUID = 1L;

    public EntityMitAnschriftPlzColumn(Messages messages) {
      super(messages);
    }

    @Override
    protected Anschrift extractAnschrift(E entityMitAnschrift) {
      return entityMitAnschrift.getAnschrift();
    }
  }

  public static class EntityMitErreichbarkeitsanschriftPlzColumn<E extends EntityMitErreichbarkeitsanschrift> extends AbstractAnschriftPlzColumn<E> {

    private static final long serialVersionUID = 1L;

    public EntityMitErreichbarkeitsanschriftPlzColumn(Messages messages) {
      super(messages);
    }

    @Override
    protected Anschrift extractAnschrift(E entityMitErreichbarkeitsanschrift) {
      return entityMitErreichbarkeitsanschrift.getErreichbarkeitsanschrift();
    }
  }

  private abstract static class AbstractAnschriftPlzColumn<E> extends AbstractColumnEntry<E> {

    private static final long serialVersionUID = 1L;

    private final AbstractAnschriftColumn<Anschrift> anschriftPlzColumn;

    protected AbstractAnschriftPlzColumn(Messages messages) {
      super(messages);

      this.anschriftPlzColumn = AbstractAnschriftColumn.createAnschriftPlzColumn(messages);
    }

    protected abstract Anschrift extractAnschrift(E entity);

    @Override
    public ColumnType getType() {
      return anschriftPlzColumn.getType();
    }

    @Override
    public boolean isRendered() {
      return anschriftPlzColumn.isRendered();
    }

    @Override
    public String getHeader() {
      return anschriftPlzColumn.getHeader();
    }

    @Override
    public Object getValue(E entity) {
      if (entity == null) {
        return "";
      }

      return anschriftPlzColumn.getDisplayValue(extractAnschrift(entity));
    }
  }

  public static class EntityMitAnschriftZustellanweisungColumn<E extends EntityMitAnschrift> extends AbstractAnschriftZustellanweisungColumn<E> {

    private static final long serialVersionUID = 1L;

    public EntityMitAnschriftZustellanweisungColumn(Messages messages) {
      super(messages);
    }

    @Override
    protected Anschrift extractAnschrift(E entityMitAnschrift) {
      return entityMitAnschrift.getAnschrift();
    }
  }

  public static class EntityMitErreichbarkeitsanschriftZustellanweisungColumn<E extends EntityMitErreichbarkeitsanschrift> extends AbstractAnschriftZustellanweisungColumn<E> {

    private static final long serialVersionUID = 1L;

    public EntityMitErreichbarkeitsanschriftZustellanweisungColumn(Messages messages) {
      super(messages);
    }

    @Override
    protected Anschrift extractAnschrift(E entityMitErreichbarkeitsanschrift) {
      return entityMitErreichbarkeitsanschrift.getErreichbarkeitsanschrift();
    }
  }

  private abstract static class AbstractAnschriftZustellanweisungColumn<E> extends AbstractColumnEntry<E> {

    private static final long serialVersionUID = 1L;

    private final AbstractAnschriftColumn<Anschrift> anschriftZustellanweisungColumn;

    protected AbstractAnschriftZustellanweisungColumn(Messages messages) {
      super(messages);

      this.anschriftZustellanweisungColumn = AbstractAnschriftColumn.createAnschriftZustellanweisungColumn(messages);
    }

    protected abstract Anschrift extractAnschrift(E entity);

    @Override
    public ColumnType getType() {
      return anschriftZustellanweisungColumn.getType();
    }

    @Override
    public boolean isRendered() {
      return anschriftZustellanweisungColumn.isRendered();
    }

    @Override
    public String getHeader() {
      return anschriftZustellanweisungColumn.getHeader();
    }

    @Override
    public Object getValue(E entity) {
      if (entity == null) {
        return "";
      }

      return anschriftZustellanweisungColumn.getDisplayValue(extractAnschrift(entity));
    }
  }

  public static class EntityMitAnschriftPostfachColumn<E extends EntityMitAnschrift> extends AbstractAnschriftPostfachColumn<E> {

    private static final long serialVersionUID = 1L;

    public EntityMitAnschriftPostfachColumn(Messages messages) {
      super(messages);
    }

    @Override
    protected Anschrift extractAnschrift(E entityMitAnschrift) {
      return entityMitAnschrift.getAnschrift();
    }
  }

  public static class EntityMitErreichbarkeitsanschriftPostfachColumn<E extends EntityMitErreichbarkeitsanschrift> extends AbstractAnschriftPostfachColumn<E> {

    private static final long serialVersionUID = 1L;

    public EntityMitErreichbarkeitsanschriftPostfachColumn(Messages messages) {
      super(messages);
    }

    @Override
    protected Anschrift extractAnschrift(E entityMitErreichbarkeitsanschrift) {
      return entityMitErreichbarkeitsanschrift.getErreichbarkeitsanschrift();
    }
  }

  private abstract static class AbstractAnschriftPostfachColumn<E> extends AbstractColumnEntry<E> {

    private static final long serialVersionUID = 1L;

    private final AbstractAnschriftColumn<Anschrift> anschriftPostfachColumn;

    protected AbstractAnschriftPostfachColumn(Messages messages) {
      super(messages);

      this.anschriftPostfachColumn = AbstractAnschriftColumn.createAnschriftPostfachColumn(messages);
    }

    protected abstract Anschrift extractAnschrift(E entity);

    @Override
    public ColumnType getType() {
      return anschriftPostfachColumn.getType();
    }

    @Override
    public boolean isRendered() {
      return anschriftPostfachColumn.isRendered();
    }

    @Override
    public String getHeader() {
      return anschriftPostfachColumn.getHeader();
    }

    @Override
    public Object getValue(E entity) {
      if (entity == null) {
        return "";
      }

      return anschriftPostfachColumn.getDisplayValue(extractAnschrift(entity));
    }
  }
}
